Tue, 25 Sep 2012 13:11:05 -0700
7196464: upgrade JavaCompiler.shouldStopPolicy to accomodate policies in face of error and no error
Reviewed-by: mcimadamore
jjg@450 | 1 | /* |
ohair@962 | 2 | * Copyright (c) 2009, 2011, Oracle and/or its affiliates. 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 |
ohair@554 | 7 | * published by the Free Software Foundation. Oracle designates this |
jjg@450 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@554 | 9 | * by Oracle 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 | * |
ohair@554 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@554 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@554 | 23 | * 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.File; |
jjg@450 | 29 | import java.io.IOException; |
jjg@450 | 30 | import java.net.MalformedURLException; |
jjg@450 | 31 | import java.net.URL; |
jjg@450 | 32 | import java.nio.charset.Charset; |
jjg@450 | 33 | import java.nio.file.Files; |
jjg@450 | 34 | import java.nio.file.FileSystem; |
jjg@450 | 35 | import java.nio.file.FileSystems; |
jjg@450 | 36 | import java.nio.file.FileVisitOption; |
jjg@450 | 37 | import java.nio.file.FileVisitResult; |
jjg@450 | 38 | import java.nio.file.Path; |
jjg@450 | 39 | import java.nio.file.SimpleFileVisitor; |
jjg@450 | 40 | import java.nio.file.attribute.BasicFileAttributes; |
jjg@450 | 41 | import java.util.ArrayList; |
jjg@450 | 42 | import java.util.Arrays; |
jjg@450 | 43 | import java.util.Collection; |
jjg@450 | 44 | import java.util.Collections; |
jjg@450 | 45 | import java.util.EnumSet; |
jjg@450 | 46 | import java.util.HashMap; |
jjg@450 | 47 | import java.util.Iterator; |
jjg@450 | 48 | import java.util.LinkedHashSet; |
jjg@450 | 49 | import java.util.Map; |
jjg@450 | 50 | import java.util.Set; |
jjg@450 | 51 | import javax.lang.model.SourceVersion; |
jjg@450 | 52 | import javax.tools.FileObject; |
jjg@450 | 53 | import javax.tools.JavaFileManager; |
jjg@450 | 54 | import javax.tools.JavaFileObject; |
jjg@450 | 55 | import javax.tools.JavaFileObject.Kind; |
jjg@450 | 56 | import javax.tools.StandardLocation; |
jjg@450 | 57 | |
jjg@450 | 58 | import static java.nio.file.FileVisitOption.*; |
jjg@450 | 59 | import static javax.tools.StandardLocation.*; |
jjg@450 | 60 | |
jjg@450 | 61 | import com.sun.tools.javac.util.BaseFileManager; |
jjg@450 | 62 | import com.sun.tools.javac.util.Context; |
jjg@450 | 63 | import com.sun.tools.javac.util.List; |
jjg@450 | 64 | import com.sun.tools.javac.util.ListBuffer; |
jjg@450 | 65 | |
jjg@1157 | 66 | import static com.sun.tools.javac.main.Option.*; |
jjg@450 | 67 | |
jjg@450 | 68 | |
jjg@450 | 69 | // NOTE the imports carefully for this compilation unit. |
jjg@450 | 70 | // |
jjg@450 | 71 | // Path: java.nio.file.Path -- the new NIO type for which this file manager exists |
jjg@450 | 72 | // |
jjg@450 | 73 | // Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options |
jjg@450 | 74 | // The other Paths (java.nio.file.Paths) is not used |
jjg@450 | 75 | |
jjg@450 | 76 | // NOTE this and related classes depend on new API in JDK 7. |
jjg@450 | 77 | // This requires special handling while bootstrapping the JDK build, |
jjg@450 | 78 | // when these classes might not yet have been compiled. To workaround |
jjg@450 | 79 | // this, the build arranges to make stubs of these classes available |
jjg@450 | 80 | // when compiling this and related classes. The set of stub files |
jjg@450 | 81 | // is specified in make/build.properties. |
jjg@450 | 82 | |
jjg@450 | 83 | /** |
jjg@450 | 84 | * Implementation of PathFileManager: a JavaFileManager based on the use |
jjg@450 | 85 | * of java.nio.file.Path. |
jjg@450 | 86 | * |
jjg@450 | 87 | * <p>Just as a Path is somewhat analagous to a File, so too is this |
jjg@450 | 88 | * JavacPathFileManager analogous to JavacFileManager, as it relates to the |
jjg@450 | 89 | * support of FileObjects based on File objects (i.e. just RegularFileObject, |
jjg@450 | 90 | * not ZipFileObject and its variants.) |
jjg@450 | 91 | * |
jjg@450 | 92 | * <p>The default values for the standard locations supported by this file |
jjg@450 | 93 | * manager are the same as the default values provided by JavacFileManager -- |
jjg@450 | 94 | * i.e. as determined by the javac.file.Paths class. To override these values, |
jjg@450 | 95 | * call {@link #setLocation}. |
jjg@450 | 96 | * |
jjg@450 | 97 | * <p>To reduce confusion with Path objects, the locations such as "class path", |
jjg@450 | 98 | * "source path", etc, are generically referred to here as "search paths". |
jjg@450 | 99 | * |
jjg@581 | 100 | * <p><b>This is NOT part of any supported API. |
jjg@581 | 101 | * If you write code that depends on this, you do so at your own risk. |
jjg@450 | 102 | * This code and its internal interfaces are subject to change or |
jjg@450 | 103 | * deletion without notice.</b> |
jjg@450 | 104 | */ |
jjg@450 | 105 | public class JavacPathFileManager extends BaseFileManager implements PathFileManager { |
jjg@450 | 106 | protected FileSystem defaultFileSystem; |
jjg@450 | 107 | |
jjg@450 | 108 | /** |
jjg@450 | 109 | * Create a JavacPathFileManager using a given context, optionally registering |
jjg@450 | 110 | * it as the JavaFileManager for that context. |
jjg@450 | 111 | */ |
jjg@450 | 112 | public JavacPathFileManager(Context context, boolean register, Charset charset) { |
jjg@450 | 113 | super(charset); |
jjg@450 | 114 | if (register) |
jjg@450 | 115 | context.put(JavaFileManager.class, this); |
jjg@450 | 116 | pathsForLocation = new HashMap<Location, PathsForLocation>(); |
jjg@450 | 117 | fileSystems = new HashMap<Path,FileSystem>(); |
jjg@450 | 118 | setContext(context); |
jjg@450 | 119 | } |
jjg@450 | 120 | |
jjg@450 | 121 | /** |
jjg@450 | 122 | * Set the context for JavacPathFileManager. |
jjg@450 | 123 | */ |
jjg@450 | 124 | @Override |
jjg@1111 | 125 | public void setContext(Context context) { |
jjg@450 | 126 | super.setContext(context); |
jjg@450 | 127 | } |
jjg@450 | 128 | |
jjg@450 | 129 | @Override |
jjg@450 | 130 | public FileSystem getDefaultFileSystem() { |
jjg@450 | 131 | if (defaultFileSystem == null) |
jjg@450 | 132 | defaultFileSystem = FileSystems.getDefault(); |
jjg@450 | 133 | return defaultFileSystem; |
jjg@450 | 134 | } |
jjg@450 | 135 | |
jjg@450 | 136 | @Override |
jjg@450 | 137 | public void setDefaultFileSystem(FileSystem fs) { |
jjg@450 | 138 | defaultFileSystem = fs; |
jjg@450 | 139 | } |
jjg@450 | 140 | |
jjg@450 | 141 | @Override |
jjg@450 | 142 | public void flush() throws IOException { |
jjg@450 | 143 | contentCache.clear(); |
jjg@450 | 144 | } |
jjg@450 | 145 | |
jjg@450 | 146 | @Override |
jjg@450 | 147 | public void close() throws IOException { |
jjg@450 | 148 | for (FileSystem fs: fileSystems.values()) |
jjg@450 | 149 | fs.close(); |
jjg@450 | 150 | } |
jjg@450 | 151 | |
jjg@450 | 152 | @Override |
jjg@450 | 153 | public ClassLoader getClassLoader(Location location) { |
jjg@450 | 154 | nullCheck(location); |
jjg@450 | 155 | Iterable<? extends Path> path = getLocation(location); |
jjg@450 | 156 | if (path == null) |
jjg@450 | 157 | return null; |
jjg@450 | 158 | ListBuffer<URL> lb = new ListBuffer<URL>(); |
jjg@450 | 159 | for (Path p: path) { |
jjg@450 | 160 | try { |
jjg@450 | 161 | lb.append(p.toUri().toURL()); |
jjg@450 | 162 | } catch (MalformedURLException e) { |
jjg@450 | 163 | throw new AssertionError(e); |
jjg@450 | 164 | } |
jjg@450 | 165 | } |
jjg@450 | 166 | |
jjg@450 | 167 | return getClassLoader(lb.toArray(new URL[lb.size()])); |
jjg@450 | 168 | } |
jjg@450 | 169 | |
jjg@757 | 170 | @Override |
jjg@757 | 171 | public boolean isDefaultBootClassPath() { |
jjg@1116 | 172 | return locations.isDefaultBootClassPath(); |
jjg@757 | 173 | } |
jjg@757 | 174 | |
jjg@450 | 175 | // <editor-fold defaultstate="collapsed" desc="Location handling"> |
jjg@450 | 176 | |
jjg@450 | 177 | public boolean hasLocation(Location location) { |
jjg@450 | 178 | return (getLocation(location) != null); |
jjg@450 | 179 | } |
jjg@450 | 180 | |
jjg@450 | 181 | public Iterable<? extends Path> getLocation(Location location) { |
jjg@450 | 182 | nullCheck(location); |
jjg@450 | 183 | lazyInitSearchPaths(); |
jjg@450 | 184 | PathsForLocation path = pathsForLocation.get(location); |
jjg@450 | 185 | if (path == null && !pathsForLocation.containsKey(location)) { |
jjg@450 | 186 | setDefaultForLocation(location); |
jjg@450 | 187 | path = pathsForLocation.get(location); |
jjg@450 | 188 | } |
jjg@450 | 189 | return path; |
jjg@450 | 190 | } |
jjg@450 | 191 | |
jjg@450 | 192 | private Path getOutputLocation(Location location) { |
jjg@450 | 193 | Iterable<? extends Path> paths = getLocation(location); |
jjg@450 | 194 | return (paths == null ? null : paths.iterator().next()); |
jjg@450 | 195 | } |
jjg@450 | 196 | |
jjg@450 | 197 | public void setLocation(Location location, Iterable<? extends Path> searchPath) |
jjg@450 | 198 | throws IOException |
jjg@450 | 199 | { |
jjg@450 | 200 | nullCheck(location); |
jjg@450 | 201 | lazyInitSearchPaths(); |
jjg@450 | 202 | if (searchPath == null) { |
jjg@450 | 203 | setDefaultForLocation(location); |
jjg@450 | 204 | } else { |
jjg@450 | 205 | if (location.isOutputLocation()) |
jjg@450 | 206 | checkOutputPath(searchPath); |
jjg@450 | 207 | PathsForLocation pl = new PathsForLocation(); |
jjg@450 | 208 | for (Path p: searchPath) |
jjg@450 | 209 | pl.add(p); // TODO -Xlint:path warn if path not found |
jjg@450 | 210 | pathsForLocation.put(location, pl); |
jjg@450 | 211 | } |
jjg@450 | 212 | } |
jjg@450 | 213 | |
jjg@450 | 214 | private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException { |
jjg@450 | 215 | Iterator<? extends Path> pathIter = searchPath.iterator(); |
jjg@450 | 216 | if (!pathIter.hasNext()) |
jjg@450 | 217 | throw new IllegalArgumentException("empty path for directory"); |
jjg@450 | 218 | Path path = pathIter.next(); |
jjg@450 | 219 | if (pathIter.hasNext()) |
jjg@450 | 220 | throw new IllegalArgumentException("path too long for directory"); |
alanb@847 | 221 | if (!isDirectory(path)) |
jjg@450 | 222 | throw new IOException(path + ": not a directory"); |
jjg@450 | 223 | } |
jjg@450 | 224 | |
jjg@450 | 225 | private void setDefaultForLocation(Location locn) { |
jjg@450 | 226 | Collection<File> files = null; |
jjg@450 | 227 | if (locn instanceof StandardLocation) { |
jjg@450 | 228 | switch ((StandardLocation) locn) { |
jjg@450 | 229 | case CLASS_PATH: |
jjg@1116 | 230 | files = locations.userClassPath(); |
jjg@450 | 231 | break; |
jjg@450 | 232 | case PLATFORM_CLASS_PATH: |
jjg@1116 | 233 | files = locations.bootClassPath(); |
jjg@450 | 234 | break; |
jjg@450 | 235 | case SOURCE_PATH: |
jjg@1116 | 236 | files = locations.sourcePath(); |
jjg@450 | 237 | break; |
jjg@450 | 238 | case CLASS_OUTPUT: { |
jjg@450 | 239 | String arg = options.get(D); |
jjg@450 | 240 | files = (arg == null ? null : Collections.singleton(new File(arg))); |
jjg@450 | 241 | break; |
jjg@450 | 242 | } |
jjg@450 | 243 | case SOURCE_OUTPUT: { |
jjg@450 | 244 | String arg = options.get(S); |
jjg@450 | 245 | files = (arg == null ? null : Collections.singleton(new File(arg))); |
jjg@450 | 246 | break; |
jjg@450 | 247 | } |
jjg@450 | 248 | } |
jjg@450 | 249 | } |
jjg@450 | 250 | |
jjg@450 | 251 | PathsForLocation pl = new PathsForLocation(); |
jjg@450 | 252 | if (files != null) { |
jjg@450 | 253 | for (File f: files) |
jjg@450 | 254 | pl.add(f.toPath()); |
jjg@450 | 255 | } |
jjg@450 | 256 | pathsForLocation.put(locn, pl); |
jjg@450 | 257 | } |
jjg@450 | 258 | |
jjg@450 | 259 | private void lazyInitSearchPaths() { |
jjg@450 | 260 | if (!inited) { |
jjg@450 | 261 | setDefaultForLocation(PLATFORM_CLASS_PATH); |
jjg@450 | 262 | setDefaultForLocation(CLASS_PATH); |
jjg@450 | 263 | setDefaultForLocation(SOURCE_PATH); |
jjg@450 | 264 | inited = true; |
jjg@450 | 265 | } |
jjg@450 | 266 | } |
jjg@450 | 267 | // where |
jjg@450 | 268 | private boolean inited = false; |
jjg@450 | 269 | |
jjg@450 | 270 | private Map<Location, PathsForLocation> pathsForLocation; |
jjg@450 | 271 | |
jjg@450 | 272 | private static class PathsForLocation extends LinkedHashSet<Path> { |
jjg@450 | 273 | private static final long serialVersionUID = 6788510222394486733L; |
jjg@450 | 274 | } |
jjg@450 | 275 | |
jjg@450 | 276 | // </editor-fold> |
jjg@450 | 277 | |
jjg@450 | 278 | // <editor-fold defaultstate="collapsed" desc="FileObject handling"> |
jjg@450 | 279 | |
jjg@450 | 280 | @Override |
jjg@450 | 281 | public Path getPath(FileObject fo) { |
jjg@450 | 282 | nullCheck(fo); |
jjg@450 | 283 | if (!(fo instanceof PathFileObject)) |
jjg@450 | 284 | throw new IllegalArgumentException(); |
jjg@450 | 285 | return ((PathFileObject) fo).getPath(); |
jjg@450 | 286 | } |
jjg@450 | 287 | |
jjg@450 | 288 | @Override |
jjg@450 | 289 | public boolean isSameFile(FileObject a, FileObject b) { |
jjg@450 | 290 | nullCheck(a); |
jjg@450 | 291 | nullCheck(b); |
jjg@450 | 292 | if (!(a instanceof PathFileObject)) |
jjg@450 | 293 | throw new IllegalArgumentException("Not supported: " + a); |
jjg@450 | 294 | if (!(b instanceof PathFileObject)) |
jjg@450 | 295 | throw new IllegalArgumentException("Not supported: " + b); |
jjg@450 | 296 | return ((PathFileObject) a).isSameFile((PathFileObject) b); |
jjg@450 | 297 | } |
jjg@450 | 298 | |
jjg@450 | 299 | @Override |
jjg@450 | 300 | public Iterable<JavaFileObject> list(Location location, |
jjg@450 | 301 | String packageName, Set<Kind> kinds, boolean recurse) |
jjg@450 | 302 | throws IOException { |
jjg@450 | 303 | // validatePackageName(packageName); |
jjg@450 | 304 | nullCheck(packageName); |
jjg@450 | 305 | nullCheck(kinds); |
jjg@450 | 306 | |
jjg@450 | 307 | Iterable<? extends Path> paths = getLocation(location); |
jjg@450 | 308 | if (paths == null) |
jjg@450 | 309 | return List.nil(); |
jjg@450 | 310 | ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); |
jjg@450 | 311 | |
jjg@450 | 312 | for (Path path : paths) |
jjg@450 | 313 | list(path, packageName, kinds, recurse, results); |
jjg@450 | 314 | |
jjg@450 | 315 | return results.toList(); |
jjg@450 | 316 | } |
jjg@450 | 317 | |
jjg@450 | 318 | private void list(Path path, String packageName, final Set<Kind> kinds, |
jjg@450 | 319 | boolean recurse, final ListBuffer<JavaFileObject> results) |
jjg@450 | 320 | throws IOException { |
alanb@847 | 321 | if (!Files.exists(path)) |
jjg@450 | 322 | return; |
jjg@450 | 323 | |
jjg@450 | 324 | final Path pathDir; |
jjg@450 | 325 | if (isDirectory(path)) |
jjg@450 | 326 | pathDir = path; |
jjg@450 | 327 | else { |
jjg@450 | 328 | FileSystem fs = getFileSystem(path); |
jjg@450 | 329 | if (fs == null) |
jjg@450 | 330 | return; |
jjg@450 | 331 | pathDir = fs.getRootDirectories().iterator().next(); |
jjg@450 | 332 | } |
jjg@450 | 333 | String sep = path.getFileSystem().getSeparator(); |
jjg@450 | 334 | Path packageDir = packageName.isEmpty() ? pathDir |
jjg@450 | 335 | : pathDir.resolve(packageName.replace(".", sep)); |
alanb@847 | 336 | if (!Files.exists(packageDir)) |
jjg@450 | 337 | return; |
jjg@450 | 338 | |
jjg@450 | 339 | /* Alternate impl of list, superceded by use of Files.walkFileTree */ |
jjg@450 | 340 | // Deque<Path> queue = new LinkedList<Path>(); |
jjg@450 | 341 | // queue.add(packageDir); |
jjg@450 | 342 | // |
jjg@450 | 343 | // Path dir; |
jjg@450 | 344 | // while ((dir = queue.poll()) != null) { |
jjg@450 | 345 | // DirectoryStream<Path> ds = dir.newDirectoryStream(); |
jjg@450 | 346 | // try { |
jjg@450 | 347 | // for (Path p: ds) { |
alanb@847 | 348 | // String name = p.getFileName().toString(); |
jjg@450 | 349 | // if (isDirectory(p)) { |
jjg@450 | 350 | // if (recurse && SourceVersion.isIdentifier(name)) { |
jjg@450 | 351 | // queue.add(p); |
jjg@450 | 352 | // } |
jjg@450 | 353 | // } else { |
jjg@450 | 354 | // if (kinds.contains(getKind(name))) { |
jjg@450 | 355 | // JavaFileObject fe = |
jjg@450 | 356 | // PathFileObject.createDirectoryPathFileObject(this, p, pathDir); |
jjg@450 | 357 | // results.append(fe); |
jjg@450 | 358 | // } |
jjg@450 | 359 | // } |
jjg@450 | 360 | // } |
jjg@450 | 361 | // } finally { |
jjg@450 | 362 | // ds.close(); |
jjg@450 | 363 | // } |
jjg@450 | 364 | // } |
jjg@450 | 365 | int maxDepth = (recurse ? Integer.MAX_VALUE : 1); |
alanb@701 | 366 | Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS); |
jjg@450 | 367 | Files.walkFileTree(packageDir, opts, maxDepth, |
jjg@450 | 368 | new SimpleFileVisitor<Path>() { |
jjg@450 | 369 | @Override |
alanb@701 | 370 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { |
alanb@847 | 371 | Path name = dir.getFileName(); |
jjg@803 | 372 | if (name == null || SourceVersion.isIdentifier(name.toString())) // JSR 292? |
jjg@450 | 373 | return FileVisitResult.CONTINUE; |
jjg@450 | 374 | else |
jjg@450 | 375 | return FileVisitResult.SKIP_SUBTREE; |
jjg@450 | 376 | } |
jjg@450 | 377 | |
jjg@450 | 378 | @Override |
jjg@450 | 379 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { |
alanb@847 | 380 | if (attrs.isRegularFile() && kinds.contains(getKind(file.getFileName().toString()))) { |
jjg@450 | 381 | JavaFileObject fe = |
jjg@450 | 382 | PathFileObject.createDirectoryPathFileObject( |
jjg@450 | 383 | JavacPathFileManager.this, file, pathDir); |
jjg@450 | 384 | results.append(fe); |
jjg@450 | 385 | } |
jjg@450 | 386 | return FileVisitResult.CONTINUE; |
jjg@450 | 387 | } |
jjg@450 | 388 | }); |
jjg@450 | 389 | } |
jjg@450 | 390 | |
jjg@450 | 391 | @Override |
jjg@450 | 392 | public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths( |
jjg@450 | 393 | Iterable<? extends Path> paths) { |
jjg@450 | 394 | ArrayList<PathFileObject> result; |
jjg@450 | 395 | if (paths instanceof Collection<?>) |
jjg@450 | 396 | result = new ArrayList<PathFileObject>(((Collection<?>)paths).size()); |
jjg@450 | 397 | else |
jjg@450 | 398 | result = new ArrayList<PathFileObject>(); |
jjg@450 | 399 | for (Path p: paths) |
jjg@450 | 400 | result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p))); |
jjg@450 | 401 | return result; |
jjg@450 | 402 | } |
jjg@450 | 403 | |
jjg@450 | 404 | @Override |
jjg@450 | 405 | public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) { |
jjg@450 | 406 | return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths))); |
jjg@450 | 407 | } |
jjg@450 | 408 | |
jjg@450 | 409 | @Override |
jjg@450 | 410 | public JavaFileObject getJavaFileForInput(Location location, |
jjg@450 | 411 | String className, Kind kind) throws IOException { |
jjg@450 | 412 | return getFileForInput(location, getRelativePath(className, kind)); |
jjg@450 | 413 | } |
jjg@450 | 414 | |
jjg@450 | 415 | @Override |
jjg@450 | 416 | public FileObject getFileForInput(Location location, |
jjg@450 | 417 | String packageName, String relativeName) throws IOException { |
jjg@450 | 418 | return getFileForInput(location, getRelativePath(packageName, relativeName)); |
jjg@450 | 419 | } |
jjg@450 | 420 | |
jjg@450 | 421 | private JavaFileObject getFileForInput(Location location, String relativePath) |
jjg@450 | 422 | throws IOException { |
jjg@450 | 423 | for (Path p: getLocation(location)) { |
jjg@450 | 424 | if (isDirectory(p)) { |
jjg@450 | 425 | Path f = resolve(p, relativePath); |
alanb@847 | 426 | if (Files.exists(f)) |
jjg@450 | 427 | return PathFileObject.createDirectoryPathFileObject(this, f, p); |
jjg@450 | 428 | } else { |
jjg@450 | 429 | FileSystem fs = getFileSystem(p); |
jjg@450 | 430 | if (fs != null) { |
jjg@450 | 431 | Path file = getPath(fs, relativePath); |
alanb@847 | 432 | if (Files.exists(file)) |
jjg@450 | 433 | return PathFileObject.createJarPathFileObject(this, file); |
jjg@450 | 434 | } |
jjg@450 | 435 | } |
jjg@450 | 436 | } |
jjg@450 | 437 | return null; |
jjg@450 | 438 | } |
jjg@450 | 439 | |
jjg@450 | 440 | @Override |
jjg@450 | 441 | public JavaFileObject getJavaFileForOutput(Location location, |
jjg@450 | 442 | String className, Kind kind, FileObject sibling) throws IOException { |
jjg@450 | 443 | return getFileForOutput(location, getRelativePath(className, kind), sibling); |
jjg@450 | 444 | } |
jjg@450 | 445 | |
jjg@450 | 446 | @Override |
jjg@450 | 447 | public FileObject getFileForOutput(Location location, String packageName, |
jjg@450 | 448 | String relativeName, FileObject sibling) |
jjg@450 | 449 | throws IOException { |
jjg@450 | 450 | return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling); |
jjg@450 | 451 | } |
jjg@450 | 452 | |
jjg@450 | 453 | private JavaFileObject getFileForOutput(Location location, |
jjg@450 | 454 | String relativePath, FileObject sibling) { |
jjg@450 | 455 | Path dir = getOutputLocation(location); |
jjg@450 | 456 | if (dir == null) { |
jjg@450 | 457 | if (location == CLASS_OUTPUT) { |
jjg@450 | 458 | Path siblingDir = null; |
jjg@450 | 459 | if (sibling != null && sibling instanceof PathFileObject) { |
jjg@450 | 460 | siblingDir = ((PathFileObject) sibling).getPath().getParent(); |
jjg@450 | 461 | } |
jjg@450 | 462 | return PathFileObject.createSiblingPathFileObject(this, |
jjg@450 | 463 | siblingDir.resolve(getBaseName(relativePath)), |
jjg@450 | 464 | relativePath); |
jjg@450 | 465 | } else if (location == SOURCE_OUTPUT) { |
jjg@450 | 466 | dir = getOutputLocation(CLASS_OUTPUT); |
jjg@450 | 467 | } |
jjg@450 | 468 | } |
jjg@450 | 469 | |
jjg@450 | 470 | Path file; |
jjg@450 | 471 | if (dir != null) { |
jjg@450 | 472 | file = resolve(dir, relativePath); |
jjg@450 | 473 | return PathFileObject.createDirectoryPathFileObject(this, file, dir); |
jjg@450 | 474 | } else { |
jjg@450 | 475 | file = getPath(getDefaultFileSystem(), relativePath); |
jjg@450 | 476 | return PathFileObject.createSimplePathFileObject(this, file); |
jjg@450 | 477 | } |
jjg@450 | 478 | |
jjg@450 | 479 | } |
jjg@450 | 480 | |
jjg@450 | 481 | @Override |
jjg@450 | 482 | public String inferBinaryName(Location location, JavaFileObject fo) { |
jjg@450 | 483 | nullCheck(fo); |
jjg@450 | 484 | // Need to match the path semantics of list(location, ...) |
jjg@450 | 485 | Iterable<? extends Path> paths = getLocation(location); |
jjg@450 | 486 | if (paths == null) { |
jjg@450 | 487 | return null; |
jjg@450 | 488 | } |
jjg@450 | 489 | |
jjg@450 | 490 | if (!(fo instanceof PathFileObject)) |
jjg@450 | 491 | throw new IllegalArgumentException(fo.getClass().getName()); |
jjg@450 | 492 | |
jjg@450 | 493 | return ((PathFileObject) fo).inferBinaryName(paths); |
jjg@450 | 494 | } |
jjg@450 | 495 | |
jjg@450 | 496 | private FileSystem getFileSystem(Path p) throws IOException { |
jjg@450 | 497 | FileSystem fs = fileSystems.get(p); |
jjg@450 | 498 | if (fs == null) { |
alanb@847 | 499 | fs = FileSystems.newFileSystem(p, null); |
jjg@450 | 500 | fileSystems.put(p, fs); |
jjg@450 | 501 | } |
jjg@450 | 502 | return fs; |
jjg@450 | 503 | } |
jjg@450 | 504 | |
jjg@450 | 505 | private Map<Path,FileSystem> fileSystems; |
jjg@450 | 506 | |
jjg@450 | 507 | // </editor-fold> |
jjg@450 | 508 | |
jjg@450 | 509 | // <editor-fold defaultstate="collapsed" desc="Utility methods"> |
jjg@450 | 510 | |
jjg@450 | 511 | private static String getRelativePath(String className, Kind kind) { |
jjg@450 | 512 | return className.replace(".", "/") + kind.extension; |
jjg@450 | 513 | } |
jjg@450 | 514 | |
jjg@450 | 515 | private static String getRelativePath(String packageName, String relativeName) { |
jjg@450 | 516 | return packageName.replace(".", "/") + relativeName; |
jjg@450 | 517 | } |
jjg@450 | 518 | |
jjg@450 | 519 | private static String getBaseName(String relativePath) { |
jjg@450 | 520 | int lastSep = relativePath.lastIndexOf("/"); |
jjg@450 | 521 | return relativePath.substring(lastSep + 1); // safe if "/" not found |
jjg@450 | 522 | } |
jjg@450 | 523 | |
jjg@450 | 524 | private static boolean isDirectory(Path path) throws IOException { |
alanb@847 | 525 | BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); |
jjg@450 | 526 | return attrs.isDirectory(); |
jjg@450 | 527 | } |
jjg@450 | 528 | |
jjg@450 | 529 | private static Path getPath(FileSystem fs, String relativePath) { |
jjg@450 | 530 | return fs.getPath(relativePath.replace("/", fs.getSeparator())); |
jjg@450 | 531 | } |
jjg@450 | 532 | |
jjg@450 | 533 | private static Path resolve(Path base, String relativePath) { |
jjg@450 | 534 | FileSystem fs = base.getFileSystem(); |
jjg@450 | 535 | Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator())); |
jjg@450 | 536 | return base.resolve(rp); |
jjg@450 | 537 | } |
jjg@450 | 538 | |
jjg@450 | 539 | // </editor-fold> |
jjg@450 | 540 | |
jjg@450 | 541 | } |