668 } else { 669 throw new NoSuchElementException(); 670 } 671 } 672 673 @Override 674 public void remove() { 675 throw new ReadOnlyFileSystemException(); 676 } 677 }; 678 } 679 680 ///////////////////////////////////////////////////////////////////// 681 // Helpers for JrtFileSystemProvider and JrtFileSystem 682 final int getPathLength() { 683 return path.length; 684 } 685 686 final void createDirectory(FileAttribute<?>... attrs) 687 throws IOException { 688 jrtfs.createDirectory(getResolvedPath(), attrs); 689 } 690 691 final InputStream newInputStream(OpenOption... options) throws IOException { 692 if (options.length > 0) { 693 for (OpenOption opt : options) { 694 if (opt != READ) { 695 throw new UnsupportedOperationException("'" + opt + "' not allowed"); 696 } 697 } 698 } 699 return jrtfs.newInputStream(getResolvedPath()); 700 } 701 702 final DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter) 703 throws IOException { 704 return new JrtDirectoryStream(this, filter); 705 } 706 707 final void delete() throws IOException { 708 jrtfs.deleteFile(getResolvedPath(), true); 709 } 710 711 final void deleteIfExists() throws IOException { 712 jrtfs.deleteFile(getResolvedPath(), false); 713 } 714 715 final AbstractJrtFileAttributes getAttributes(LinkOption... options) throws IOException { 716 AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(getResolvedPath(), options); 717 if (zfas == null) { 718 throw new NoSuchFileException(toString()); 719 } 720 return zfas; 721 } 722 723 final void setAttribute(String attribute, Object value, LinkOption... options) 724 throws IOException { 725 String type; 726 String attr; 727 int colonPos = attribute.indexOf(':'); 728 if (colonPos == -1) { 729 type = "basic"; 730 attr = attribute; 731 } else { 732 type = attribute.substring(0, colonPos++); 733 attr = attribute.substring(colonPos); 734 } 735 JrtFileAttributeView view = JrtFileAttributeView.get(this, type, options); 736 if (view == null) { 737 throw new UnsupportedOperationException("view <" + view + "> is not supported"); 738 } 739 view.setAttribute(attr, value); 740 } 741 742 final void setTimes(FileTime mtime, FileTime atime, FileTime ctime) 743 throws IOException { 744 jrtfs.setTimes(getResolvedPath(), mtime, atime, ctime); 745 } 746 747 final Map<String, Object> readAttributes(String attributes, LinkOption... options) 748 throws IOException { 749 String view; 750 String attrs; 751 int colonPos = attributes.indexOf(':'); 752 if (colonPos == -1) { 753 view = "basic"; 754 attrs = attributes; 755 } else { 756 view = attributes.substring(0, colonPos++); 757 attrs = attributes.substring(colonPos); 758 } 759 JrtFileAttributeView jrtfv = JrtFileAttributeView.get(this, view, options); 760 if (jrtfv == null) { 761 throw new UnsupportedOperationException("view not supported"); 762 } 763 return jrtfv.readAttributes(attrs); 764 } 772 } 773 774 final boolean isSameFile(Path other) throws IOException { 775 if (this.equals(other)) { 776 return true; 777 } 778 if (other == null 779 || this.getFileSystem() != other.getFileSystem()) { 780 return false; 781 } 782 this.checkAccess(); 783 AbstractJrtPath target = (AbstractJrtPath) other; 784 target.checkAccess(); 785 return Arrays.equals(this.getResolvedPath(), target.getResolvedPath()) 786 || jrtfs.isSameFile(this, target); 787 } 788 789 final SeekableByteChannel newByteChannel(Set<? extends OpenOption> options, 790 FileAttribute<?>... attrs) 791 throws IOException { 792 return jrtfs.newByteChannel(getResolvedPath(), options, attrs); 793 } 794 795 final FileChannel newFileChannel(Set<? extends OpenOption> options, 796 FileAttribute<?>... attrs) 797 throws IOException { 798 return jrtfs.newFileChannel(getResolvedPath(), options, attrs); 799 } 800 801 final void checkAccess(AccessMode... modes) throws IOException { 802 boolean w = false; 803 boolean x = false; 804 for (AccessMode mode : modes) { 805 switch (mode) { 806 case READ: 807 break; 808 case WRITE: 809 w = true; 810 break; 811 case EXECUTE: 812 x = true; 813 break; 814 default: 815 throw new UnsupportedOperationException(); 816 } 817 } 818 819 BasicFileAttributes attrs = jrtfs.getFileAttributes(getResolvedPath()); 820 if (attrs == null && (path.length != 1 || path[0] != '/')) { 821 throw new NoSuchFileException(toString()); 822 } 823 if (w) { 824 // if (jrtfs.isReadOnly()) 825 throw new AccessDeniedException(toString()); 826 } 827 if (x) { 828 throw new AccessDeniedException(toString()); 829 } 830 } 831 832 final boolean exists() { 833 try { 834 return jrtfs.exists(getResolvedPath()); 835 } catch (IOException x) { 836 } 837 return false; 838 } 839 840 final OutputStream newOutputStream(OpenOption... options) throws IOException { 841 if (options.length == 0) { 842 return jrtfs.newOutputStream(getResolvedPath(), 843 CREATE_NEW, WRITE); 844 } 845 return jrtfs.newOutputStream(getResolvedPath(), options); 846 } 847 848 final void move(AbstractJrtPath target, CopyOption... options) 849 throws IOException { 850 if (this.jrtfs == target.jrtfs) { 851 jrtfs.copyFile(true, 852 getResolvedPath(), target.getResolvedPath(), 853 options); 854 } else { 855 copyToTarget(target, options); 856 delete(); 857 } 858 } 859 860 final void copy(AbstractJrtPath target, CopyOption... options) 861 throws IOException { 862 if (this.jrtfs == target.jrtfs) { 863 jrtfs.copyFile(false, 864 getResolvedPath(), target.getResolvedPath(), 865 options); 866 } else { 867 copyToTarget(target, options); 868 } 869 } 870 871 private void copyToTarget(AbstractJrtPath target, CopyOption... options) 872 throws IOException { 873 boolean replaceExisting = false; 874 boolean copyAttrs = false; 875 for (CopyOption opt : options) { 876 if (opt == REPLACE_EXISTING) { 877 replaceExisting = true; 878 } else if (opt == COPY_ATTRIBUTES) { 879 copyAttrs = true; 880 } 881 } 882 // attributes of source file 883 BasicFileAttributes jrtfas = getAttributes(); 884 // check if target exists 885 boolean exists; 886 if (replaceExisting) { 887 try { 888 target.deleteIfExists(); 889 exists = false; 890 } catch (DirectoryNotEmptyException x) { 891 exists = true; 892 } 893 } else { 894 exists = target.exists(); 895 } 896 if (exists) { 897 throw new FileAlreadyExistsException(target.toString()); 898 } 899 900 if (jrtfas.isDirectory()) { 901 // create directory or file 902 target.createDirectory(); 903 } else { 904 try (InputStream is = jrtfs.newInputStream(getResolvedPath()); OutputStream os = target.newOutputStream()) { 905 byte[] buf = new byte[8192]; 906 int n; 907 while ((n = is.read(buf)) != -1) { 908 os.write(buf, 0, n); 909 } 910 } 911 } 912 if (copyAttrs) { 913 BasicFileAttributeView view 914 = JrtFileAttributeView.get(target, BasicFileAttributeView.class); 915 try { 916 view.setTimes(jrtfas.lastModifiedTime(), 917 jrtfas.lastAccessTime(), 918 jrtfas.creationTime()); 919 } catch (IOException x) { 920 // rollback? 921 try { 922 target.delete(); 923 } catch (IOException ignore) { 924 } | 668 } else { 669 throw new NoSuchElementException(); 670 } 671 } 672 673 @Override 674 public void remove() { 675 throw new ReadOnlyFileSystemException(); 676 } 677 }; 678 } 679 680 ///////////////////////////////////////////////////////////////////// 681 // Helpers for JrtFileSystemProvider and JrtFileSystem 682 final int getPathLength() { 683 return path.length; 684 } 685 686 final void createDirectory(FileAttribute<?>... attrs) 687 throws IOException { 688 jrtfs.createDirectory(this, attrs); 689 } 690 691 final InputStream newInputStream(OpenOption... options) throws IOException { 692 if (options.length > 0) { 693 for (OpenOption opt : options) { 694 if (opt != READ) { 695 throw new UnsupportedOperationException("'" + opt + "' not allowed"); 696 } 697 } 698 } 699 return jrtfs.newInputStream(this); 700 } 701 702 final DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter) 703 throws IOException { 704 return new JrtDirectoryStream(this, filter); 705 } 706 707 final void delete() throws IOException { 708 jrtfs.deleteFile(this, true); 709 } 710 711 final void deleteIfExists() throws IOException { 712 jrtfs.deleteFile(this, false); 713 } 714 715 final AbstractJrtFileAttributes getAttributes(LinkOption... options) throws IOException { 716 AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(this, options); 717 if (zfas == null) { 718 throw new NoSuchFileException(toString()); 719 } 720 return zfas; 721 } 722 723 final void setAttribute(String attribute, Object value, LinkOption... options) 724 throws IOException { 725 String type; 726 String attr; 727 int colonPos = attribute.indexOf(':'); 728 if (colonPos == -1) { 729 type = "basic"; 730 attr = attribute; 731 } else { 732 type = attribute.substring(0, colonPos++); 733 attr = attribute.substring(colonPos); 734 } 735 JrtFileAttributeView view = JrtFileAttributeView.get(this, type, options); 736 if (view == null) { 737 throw new UnsupportedOperationException("view <" + view + "> is not supported"); 738 } 739 view.setAttribute(attr, value); 740 } 741 742 final void setTimes(FileTime mtime, FileTime atime, FileTime ctime) 743 throws IOException { 744 jrtfs.setTimes(this, mtime, atime, ctime); 745 } 746 747 final Map<String, Object> readAttributes(String attributes, LinkOption... options) 748 throws IOException { 749 String view; 750 String attrs; 751 int colonPos = attributes.indexOf(':'); 752 if (colonPos == -1) { 753 view = "basic"; 754 attrs = attributes; 755 } else { 756 view = attributes.substring(0, colonPos++); 757 attrs = attributes.substring(colonPos); 758 } 759 JrtFileAttributeView jrtfv = JrtFileAttributeView.get(this, view, options); 760 if (jrtfv == null) { 761 throw new UnsupportedOperationException("view not supported"); 762 } 763 return jrtfv.readAttributes(attrs); 764 } 772 } 773 774 final boolean isSameFile(Path other) throws IOException { 775 if (this.equals(other)) { 776 return true; 777 } 778 if (other == null 779 || this.getFileSystem() != other.getFileSystem()) { 780 return false; 781 } 782 this.checkAccess(); 783 AbstractJrtPath target = (AbstractJrtPath) other; 784 target.checkAccess(); 785 return Arrays.equals(this.getResolvedPath(), target.getResolvedPath()) 786 || jrtfs.isSameFile(this, target); 787 } 788 789 final SeekableByteChannel newByteChannel(Set<? extends OpenOption> options, 790 FileAttribute<?>... attrs) 791 throws IOException { 792 return jrtfs.newByteChannel(this, options, attrs); 793 } 794 795 final FileChannel newFileChannel(Set<? extends OpenOption> options, 796 FileAttribute<?>... attrs) 797 throws IOException { 798 return jrtfs.newFileChannel(this, options, attrs); 799 } 800 801 final void checkAccess(AccessMode... modes) throws IOException { 802 boolean w = false; 803 boolean x = false; 804 for (AccessMode mode : modes) { 805 switch (mode) { 806 case READ: 807 break; 808 case WRITE: 809 w = true; 810 break; 811 case EXECUTE: 812 x = true; 813 break; 814 default: 815 throw new UnsupportedOperationException(); 816 } 817 } 818 819 BasicFileAttributes attrs = jrtfs.getFileAttributes(this); 820 if (attrs == null && (path.length != 1 || path[0] != '/')) { 821 throw new NoSuchFileException(toString()); 822 } 823 if (w) { 824 // if (jrtfs.isReadOnly()) 825 throw new AccessDeniedException(toString()); 826 } 827 if (x) { 828 throw new AccessDeniedException(toString()); 829 } 830 } 831 832 final boolean exists() { 833 try { 834 return jrtfs.exists(this); 835 } catch (IOException x) { 836 } 837 return false; 838 } 839 840 final OutputStream newOutputStream(OpenOption... options) throws IOException { 841 if (options.length == 0) { 842 return jrtfs.newOutputStream(this, 843 CREATE_NEW, WRITE); 844 } 845 return jrtfs.newOutputStream(this, options); 846 } 847 848 final void move(AbstractJrtPath target, CopyOption... options) 849 throws IOException { 850 if (this.jrtfs == target.jrtfs) { 851 jrtfs.copyFile(true, 852 this, target, 853 options); 854 } else { 855 copyToTarget(target, options); 856 delete(); 857 } 858 } 859 860 final void copy(AbstractJrtPath target, CopyOption... options) 861 throws IOException { 862 if (this.jrtfs == target.jrtfs) { 863 jrtfs.copyFile(false, 864 this, target, 865 options); 866 } else { 867 copyToTarget(target, options); 868 } 869 } 870 871 private void copyToTarget(AbstractJrtPath target, CopyOption... options) 872 throws IOException { 873 boolean replaceExisting = false; 874 boolean copyAttrs = false; 875 for (CopyOption opt : options) { 876 if (opt == REPLACE_EXISTING) { 877 replaceExisting = true; 878 } else if (opt == COPY_ATTRIBUTES) { 879 copyAttrs = true; 880 } 881 } 882 // attributes of source file 883 BasicFileAttributes jrtfas = getAttributes(); 884 // check if target exists 885 boolean exists; 886 if (replaceExisting) { 887 try { 888 target.deleteIfExists(); 889 exists = false; 890 } catch (DirectoryNotEmptyException x) { 891 exists = true; 892 } 893 } else { 894 exists = target.exists(); 895 } 896 if (exists) { 897 throw new FileAlreadyExistsException(target.toString()); 898 } 899 900 if (jrtfas.isDirectory()) { 901 // create directory or file 902 target.createDirectory(); 903 } else { 904 try (InputStream is = jrtfs.newInputStream(this); OutputStream os = target.newOutputStream()) { 905 byte[] buf = new byte[8192]; 906 int n; 907 while ((n = is.read(buf)) != -1) { 908 os.write(buf, 0, n); 909 } 910 } 911 } 912 if (copyAttrs) { 913 BasicFileAttributeView view 914 = JrtFileAttributeView.get(target, BasicFileAttributeView.class); 915 try { 916 view.setTimes(jrtfas.lastModifiedTime(), 917 jrtfas.lastAccessTime(), 918 jrtfas.creationTime()); 919 } catch (IOException x) { 920 // rollback? 921 try { 922 target.delete(); 923 } catch (IOException ignore) { 924 } |