WindowsFileStore.java revision 893
893N/A/*
893N/A * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
893N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
893N/A *
893N/A * This code is free software; you can redistribute it and/or modify it
893N/A * under the terms of the GNU General Public License version 2 only, as
893N/A * published by the Free Software Foundation. Sun designates this
893N/A * particular file as subject to the "Classpath" exception as provided
893N/A * by Sun in the LICENSE file that accompanied this code.
893N/A *
893N/A * This code is distributed in the hope that it will be useful, but WITHOUT
893N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
893N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
893N/A * version 2 for more details (a copy is included in the LICENSE file that
893N/A * accompanied this code).
893N/A *
893N/A * You should have received a copy of the GNU General Public License version
893N/A * 2 along with this work; if not, write to the Free Software Foundation,
893N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
893N/A *
893N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
893N/A * CA 95054 USA or visit www.sun.com if you need additional information or
893N/A * have any questions.
893N/A */
893N/A
893N/Apackage sun.nio.fs;
893N/A
893N/Aimport java.nio.file.*;
893N/Aimport java.nio.file.attribute.*;
893N/Aimport java.util.*;
893N/Aimport java.io.IOException;
893N/A
893N/Aimport static sun.nio.fs.WindowsConstants.*;
893N/Aimport static sun.nio.fs.WindowsNativeDispatcher.*;
893N/A
893N/A/**
893N/A * Windows implementation of FileStore.
893N/A */
893N/A
893N/Aclass WindowsFileStore
893N/A extends FileStore
893N/A{
893N/A private final String root;
893N/A private final VolumeInformation volInfo;
893N/A private final int volType;
893N/A private final String displayName; // returned by toString
893N/A
893N/A private WindowsFileStore(String root) throws WindowsException {
893N/A assert root.charAt(root.length()-1) == '\\';
893N/A this.root = root;
893N/A this.volInfo = GetVolumeInformation(root);
893N/A this.volType = GetDriveType(root);
893N/A
893N/A // file store "display name" is the volume name if available
893N/A String vol = volInfo.volumeName();
893N/A if (vol.length() > 0) {
893N/A this.displayName = vol;
893N/A } else {
893N/A // TBD - should we map all types? Does this need to be localized?
893N/A this.displayName = (volType == DRIVE_REMOVABLE) ? "Removable Disk" : "";
893N/A }
893N/A }
893N/A
893N/A static WindowsFileStore create(String root, boolean ignoreNotReady)
893N/A throws IOException
893N/A {
893N/A try {
893N/A return new WindowsFileStore(root);
893N/A } catch (WindowsException x) {
893N/A if (ignoreNotReady && x.lastError() == ERROR_NOT_READY)
893N/A return null;
893N/A x.rethrowAsIOException(root);
893N/A return null; // keep compiler happy
893N/A }
893N/A }
893N/A
893N/A static WindowsFileStore create(WindowsPath file) throws IOException {
893N/A try {
893N/A // if the file is a link then GetVolumePathName returns the
893N/A // volume that the link is on so we need to call it with the
893N/A // final target
893N/A String target;
893N/A if (file.getFileSystem().supportsLinks()) {
893N/A target = WindowsLinkSupport.getFinalPath(file, true);
893N/A } else {
893N/A // file must exist
893N/A WindowsFileAttributes.get(file, true);
893N/A target = file.getPathForWin32Calls();
893N/A }
893N/A String root = GetVolumePathName(target);
893N/A return new WindowsFileStore(root);
893N/A } catch (WindowsException x) {
893N/A x.rethrowAsIOException(file);
893N/A return null; // keep compiler happy
893N/A }
893N/A }
893N/A
893N/A VolumeInformation volumeInformation() {
893N/A return volInfo;
893N/A }
893N/A
893N/A int volumeType() {
893N/A return volType;
893N/A }
893N/A
893N/A @Override
893N/A public String name() {
893N/A return volInfo.volumeName(); // "SYSTEM", "DVD-RW", ...
893N/A }
893N/A
893N/A @Override
893N/A public String type() {
893N/A return volInfo.fileSystemName(); // "FAT", "NTFS", ...
893N/A }
893N/A
893N/A @Override
893N/A public boolean isReadOnly() {
893N/A return ((volInfo.flags() & FILE_READ_ONLY_VOLUME) != 0);
893N/A }
893N/A
893N/A @Override
893N/A @SuppressWarnings("unchecked")
893N/A public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) {
893N/A if (view == FileStoreSpaceAttributeView.class)
893N/A return (V) new WindowsFileStoreAttributeView(this);
893N/A return (V) null;
893N/A }
893N/A
893N/A @Override
893N/A public FileStoreAttributeView getFileStoreAttributeView(String name) {
893N/A if (name.equals("space"))
893N/A return new WindowsFileStoreAttributeView(this);
893N/A if (name.equals("volume"))
893N/A return new VolumeFileStoreAttributeView(this);
893N/A return null;
893N/A }
893N/A
893N/A @Override
893N/A public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
893N/A if (type == BasicFileAttributeView.class)
893N/A return true;
893N/A if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class)
893N/A return ((volInfo.flags() & FILE_PERSISTENT_ACLS) != 0);
893N/A if (type == UserDefinedFileAttributeView.class)
893N/A return ((volInfo.flags() & FILE_NAMED_STREAMS) != 0);
893N/A return false;
893N/A }
893N/A
893N/A @Override
893N/A public boolean supportsFileAttributeView(String name) {
893N/A if (name.equals("basic") || name.equals("dos"))
893N/A return true;
893N/A if (name.equals("acl"))
893N/A return supportsFileAttributeView(AclFileAttributeView.class);
893N/A if (name.equals("owner"))
893N/A return supportsFileAttributeView(FileOwnerAttributeView.class);
893N/A if (name.equals("xattr"))
893N/A return supportsFileAttributeView(UserDefinedFileAttributeView.class);
893N/A return false;
893N/A }
893N/A
893N/A @Override
893N/A public boolean equals(Object ob) {
893N/A if (ob == this)
893N/A return true;
893N/A if (!(ob instanceof WindowsFileStore))
893N/A return false;
893N/A WindowsFileStore other = (WindowsFileStore)ob;
893N/A return this.volInfo.volumeSerialNumber() == other.volInfo.volumeSerialNumber();
893N/A }
893N/A
893N/A @Override
893N/A public int hashCode() {
893N/A // reveals VSN without permission check - okay?
893N/A return volInfo.volumeSerialNumber();
893N/A }
893N/A
893N/A @Override
893N/A public String toString() {
893N/A StringBuilder sb = new StringBuilder(displayName);
893N/A if (sb.length() > 0)
893N/A sb.append(" ");
893N/A sb.append("(");
893N/A // drop trailing slash
893N/A sb.append(root.subSequence(0, root.length()-1));
893N/A sb.append(")");
893N/A return sb.toString();
893N/A }
893N/A
893N/A static class WindowsFileStoreAttributeView
893N/A extends AbstractFileStoreSpaceAttributeView
893N/A {
893N/A private final WindowsFileStore fs;
893N/A
893N/A WindowsFileStoreAttributeView(WindowsFileStore fs) {
893N/A this.fs = fs;
893N/A }
893N/A
893N/A @Override
893N/A public FileStoreSpaceAttributes readAttributes()
893N/A throws IOException
893N/A {
893N/A // read the free space info
893N/A DiskFreeSpace info = null;
893N/A try {
893N/A info = GetDiskFreeSpaceEx(fs.root);
893N/A } catch (WindowsException x) {
893N/A x.rethrowAsIOException(fs.root);
893N/A }
893N/A
893N/A final DiskFreeSpace result = info;
893N/A return new FileStoreSpaceAttributes() {
893N/A @Override
893N/A public long totalSpace() {
893N/A return result.totalNumberOfBytes();
893N/A }
893N/A @Override
893N/A public long usableSpace() {
893N/A return result.freeBytesAvailable();
893N/A }
893N/A @Override
893N/A public long unallocatedSpace() {
893N/A return result.totalNumberOfFreeBytes();
893N/A }
893N/A };
893N/A }
893N/A }
893N/A
893N/A /**
893N/A * Windows-specific attribute view to allow access to volume information.
893N/A */
893N/A static class VolumeFileStoreAttributeView
893N/A implements FileStoreAttributeView
893N/A {
893N/A private static final String VSN_NAME = "vsn";
893N/A private static final String COMPRESSED_NAME = "compressed";
893N/A private static final String REMOVABLE_NAME = "removable";
893N/A private static final String CDROM_NAME = "cdrom";
893N/A
893N/A private final WindowsFileStore fs;
893N/A
893N/A VolumeFileStoreAttributeView(WindowsFileStore fs) {
893N/A this.fs = fs;
893N/A }
893N/A
893N/A @Override
893N/A public String name() {
893N/A return "volume";
893N/A }
893N/A
893N/A private int vsn() {
893N/A return fs.volumeInformation().volumeSerialNumber();
893N/A }
893N/A
893N/A private boolean isCompressed() {
893N/A return (fs.volumeInformation().flags() &
893N/A FILE_VOLUME_IS_COMPRESSED) > 0;
893N/A }
893N/A
893N/A private boolean isRemovable() {
893N/A return fs.volumeType() == DRIVE_REMOVABLE;
893N/A }
893N/A
893N/A private boolean isCdrom() {
893N/A return fs.volumeType() == DRIVE_CDROM;
893N/A }
893N/A
893N/A @Override
893N/A public Object getAttribute(String attribute) throws IOException {
893N/A if (attribute.equals(VSN_NAME))
893N/A return vsn();
893N/A if (attribute.equals(COMPRESSED_NAME))
893N/A return isCompressed();
893N/A if (attribute.equals(REMOVABLE_NAME))
893N/A return isRemovable();
893N/A if (attribute.equals(CDROM_NAME))
893N/A return isCdrom();
893N/A return null;
893N/A }
893N/A
893N/A @Override
893N/A public void setAttribute(String attribute, Object value)
893N/A throws IOException
893N/A {
893N/A throw new UnsupportedOperationException();
893N/A }
893N/A
893N/A @Override
893N/A public Map<String,?> readAttributes(String first, String... rest)
893N/A throws IOException
893N/A {
893N/A boolean all = false;
893N/A boolean vsn = false;
893N/A boolean compressed = false;
893N/A boolean removable = false;
893N/A boolean cdrom = false;
893N/A
893N/A if (first.equals(VSN_NAME)) vsn = true;
893N/A else if (first.equals(COMPRESSED_NAME)) compressed = true;
893N/A else if (first.equals(REMOVABLE_NAME)) removable = true;
893N/A else if (first.equals(CDROM_NAME)) cdrom = true;
893N/A else if (first.equals("*")) all = true;
893N/A
893N/A if (!all) {
893N/A for (String attribute: rest) {
893N/A if (attribute.equals("*")) {
893N/A all = true;
893N/A break;
893N/A }
893N/A if (attribute.equals(VSN_NAME)) {
893N/A vsn = true;
893N/A continue;
893N/A }
893N/A if (attribute.equals(COMPRESSED_NAME)) {
893N/A compressed = true;
893N/A continue;
893N/A }
893N/A if (attribute.equals(REMOVABLE_NAME)) {
893N/A removable = true;
893N/A continue;
893N/A }
893N/A }
893N/A }
893N/A
893N/A Map<String,Object> result = new HashMap<String,Object>();
893N/A if (all || vsn)
893N/A result.put(VSN_NAME, vsn());
893N/A if (all || compressed)
893N/A result.put(COMPRESSED_NAME, isCompressed());
893N/A if (all || removable)
893N/A result.put(REMOVABLE_NAME, isRemovable());
893N/A if (all || cdrom)
893N/A result.put(CDROM_NAME, isCdrom());
893N/A return result;
893N/A }
893N/A }
893N/A}