500 } |
500 } |
501 |
501 |
502 private final class ArchiveContainer implements Container { |
502 private final class ArchiveContainer implements Container { |
503 private final Path archivePath; |
503 private final Path archivePath; |
504 private final FileSystem fileSystem; |
504 private final FileSystem fileSystem; |
505 private final Map<RelativePath, Path> pathCache = new HashMap<>(); |
505 private final Map<RelativePath, Path> packages; |
506 |
506 |
507 public ArchiveContainer(Path archivePath) throws IOException, ProviderNotFoundException, SecurityException { |
507 public ArchiveContainer(Path archivePath) throws IOException, ProviderNotFoundException, SecurityException { |
508 this.archivePath = archivePath; |
508 this.archivePath = archivePath; |
509 if (multiReleaseValue != null && archivePath.toString().endsWith(".jar")) { |
509 if (multiReleaseValue != null && archivePath.toString().endsWith(".jar")) { |
510 Map<String,String> env = Collections.singletonMap("multi-release", multiReleaseValue); |
510 Map<String,String> env = Collections.singletonMap("multi-release", multiReleaseValue); |
511 FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider(); |
511 FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider(); |
512 Assert.checkNonNull(jarFSProvider, "should have been caught before!"); |
512 Assert.checkNonNull(jarFSProvider, "should have been caught before!"); |
513 this.fileSystem = jarFSProvider.newFileSystem(archivePath, env); |
513 this.fileSystem = jarFSProvider.newFileSystem(archivePath, env); |
514 } else { |
514 } else { |
515 this.fileSystem = FileSystems.newFileSystem(archivePath, null); |
515 this.fileSystem = FileSystems.newFileSystem(archivePath, null); |
|
516 } |
|
517 packages = new HashMap<>(); |
|
518 for (Path root : fileSystem.getRootDirectories()) { |
|
519 Files.walkFileTree(root, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, |
|
520 new SimpleFileVisitor<Path>() { |
|
521 @Override |
|
522 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { |
|
523 if (isValid(dir.getFileName())) { |
|
524 packages.put(new RelativeDirectory(root.relativize(dir).toString()), dir); |
|
525 return FileVisitResult.CONTINUE; |
|
526 } else { |
|
527 return FileVisitResult.SKIP_SUBTREE; |
|
528 } |
|
529 } |
|
530 }); |
516 } |
531 } |
517 } |
532 } |
518 |
533 |
519 /** |
534 /** |
520 * Insert all files in subdirectory subdirectory of this archive |
535 * Insert all files in subdirectory subdirectory of this archive |
524 public void list(Path userPath, |
539 public void list(Path userPath, |
525 RelativeDirectory subdirectory, |
540 RelativeDirectory subdirectory, |
526 Set<JavaFileObject.Kind> fileKinds, |
541 Set<JavaFileObject.Kind> fileKinds, |
527 boolean recurse, |
542 boolean recurse, |
528 ListBuffer<JavaFileObject> resultList) throws IOException { |
543 ListBuffer<JavaFileObject> resultList) throws IOException { |
529 Path resolvedSubdirectory = resolvePath(subdirectory); |
544 Path resolvedSubdirectory = packages.get(subdirectory); |
530 |
545 |
531 if (resolvedSubdirectory == null) |
546 if (resolvedSubdirectory == null) |
532 return ; |
547 return ; |
533 |
548 |
534 int maxDepth = (recurse ? Integer.MAX_VALUE : 1); |
549 int maxDepth = (recurse ? Integer.MAX_VALUE : 1); |
542 } else { |
557 } else { |
543 return FileVisitResult.SKIP_SUBTREE; |
558 return FileVisitResult.SKIP_SUBTREE; |
544 } |
559 } |
545 } |
560 } |
546 |
561 |
547 boolean isValid(Path fileName) { |
|
548 if (fileName == null) { |
|
549 return true; |
|
550 } else { |
|
551 String name = fileName.toString(); |
|
552 if (name.endsWith("/")) { |
|
553 name = name.substring(0, name.length() - 1); |
|
554 } |
|
555 return SourceVersion.isIdentifier(name); |
|
556 } |
|
557 } |
|
558 |
|
559 @Override |
562 @Override |
560 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { |
563 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { |
561 if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) { |
564 if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) { |
562 JavaFileObject fe = PathFileObject.forJarPath( |
565 JavaFileObject fe = PathFileObject.forJarPath( |
563 JavacFileManager.this, file, archivePath); |
566 JavacFileManager.this, file, archivePath); |
567 } |
570 } |
568 }); |
571 }); |
569 |
572 |
570 } |
573 } |
571 |
574 |
|
575 private boolean isValid(Path fileName) { |
|
576 if (fileName == null) { |
|
577 return true; |
|
578 } else { |
|
579 String name = fileName.toString(); |
|
580 if (name.endsWith("/")) { |
|
581 name = name.substring(0, name.length() - 1); |
|
582 } |
|
583 return SourceVersion.isIdentifier(name); |
|
584 } |
|
585 } |
|
586 |
572 @Override |
587 @Override |
573 public JavaFileObject getFileObject(Path userPath, RelativeFile name) throws IOException { |
588 public JavaFileObject getFileObject(Path userPath, RelativeFile name) throws IOException { |
574 Path p = resolvePath(name); |
589 RelativeDirectory root = name.dirname(); |
575 if (p != null) |
590 Path packagepath = packages.get(root); |
576 return PathFileObject.forJarPath(JavacFileManager.this, p, userPath); |
591 if (packagepath != null) { |
577 |
592 Path relpath = packagepath.resolve(name.basename()); |
|
593 if (Files.exists(relpath)) { |
|
594 return PathFileObject.forJarPath(JavacFileManager.this, relpath, userPath); |
|
595 } |
|
596 } |
578 return null; |
597 return null; |
579 } |
|
580 |
|
581 private synchronized Path resolvePath(RelativePath path) { |
|
582 if (!pathCache.containsKey(path)) { |
|
583 Path relativePath = path.resolveAgainst(fileSystem); |
|
584 |
|
585 if (!Files.exists(relativePath)) { |
|
586 relativePath = null; |
|
587 } |
|
588 |
|
589 pathCache.put(path, relativePath); |
|
590 return relativePath; |
|
591 } |
|
592 return pathCache.get(path); |
|
593 } |
598 } |
594 |
599 |
595 @Override |
600 @Override |
596 public void close() throws IOException { |
601 public void close() throws IOException { |
597 fileSystem.close(); |
602 fileSystem.close(); |