jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
changeset 2057 3acf8e5e2ca0
child 3065 452aaa2899fc
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.fs;
       
    27 
       
    28 
       
    29 import java.nio.file.attribute.*;
       
    30 import java.util.*;
       
    31 import java.util.concurrent.TimeUnit;
       
    32 import java.io.IOException;
       
    33 
       
    34 import static sun.nio.fs.WindowsNativeDispatcher.*;
       
    35 import static sun.nio.fs.WindowsConstants.*;
       
    36 
       
    37 class WindowsFileAttributeViews {
       
    38 
       
    39     private static class Basic extends AbstractBasicFileAttributeView {
       
    40         final WindowsPath file;
       
    41         final boolean followLinks;
       
    42 
       
    43         Basic(WindowsPath file, boolean followLinks) {
       
    44             this.file = file;
       
    45             this.followLinks = followLinks;
       
    46         }
       
    47 
       
    48         @Override
       
    49         public WindowsFileAttributes readAttributes() throws IOException {
       
    50             try {
       
    51                 return WindowsFileAttributes.get(file, followLinks);
       
    52             } catch (WindowsException x) {
       
    53                 x.rethrowAsIOException(file);
       
    54                 return null;    // keep compiler happy
       
    55             }
       
    56         }
       
    57 
       
    58         /**
       
    59          * Parameter values in Windows times.
       
    60          */
       
    61         void setFileTimes(long createTime, long lastAccessTime, long lastWriteTime)
       
    62             throws IOException
       
    63         {
       
    64             long handle = -1L;
       
    65             try {
       
    66                 int flags = FILE_FLAG_BACKUP_SEMANTICS;
       
    67                 if (!followLinks && file.getFileSystem().supportsLinks())
       
    68                     flags |= FILE_FLAG_OPEN_REPARSE_POINT;
       
    69 
       
    70                 handle = CreateFile(file.getPathForWin32Calls(),
       
    71                                     FILE_WRITE_ATTRIBUTES,
       
    72                                     (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
       
    73                                     OPEN_EXISTING,
       
    74                                     flags);
       
    75             } catch (WindowsException x) {
       
    76                 x.rethrowAsIOException(file);
       
    77             }
       
    78 
       
    79             // update attributes
       
    80             try {
       
    81                 SetFileTime(handle, createTime, lastAccessTime, lastWriteTime);
       
    82             } catch (WindowsException x) {
       
    83                 x.rethrowAsIOException(file);
       
    84             } finally {
       
    85                 CloseHandle(handle);
       
    86             }
       
    87         }
       
    88 
       
    89         @Override
       
    90         public void setTimes(Long lastModifiedTime,
       
    91                              Long lastAccessTime,
       
    92                              Long createTime,
       
    93                              TimeUnit unit) throws IOException
       
    94         {
       
    95             file.checkWrite();
       
    96 
       
    97             // if all null then do nothing
       
    98             if (lastModifiedTime == null && lastAccessTime == null &&
       
    99                 createTime == null)
       
   100             {
       
   101                 // no effect
       
   102                 return;
       
   103             }
       
   104 
       
   105             // null => no change
       
   106             // -1 => change to current time
       
   107             long now = System.currentTimeMillis();
       
   108             long modTime = 0L, accTime = 0L, crTime = 0L;
       
   109             if (lastModifiedTime != null) {
       
   110                 if (lastModifiedTime < 0L) {
       
   111                     if (lastModifiedTime != -1L)
       
   112                         throw new IllegalArgumentException();
       
   113                     modTime = now;
       
   114                 } else {
       
   115                     modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit);
       
   116                 }
       
   117                 modTime = WindowsFileAttributes.toWindowsTime(modTime);
       
   118             }
       
   119             if (lastAccessTime != null) {
       
   120                 if (lastAccessTime < 0L) {
       
   121                     if (lastAccessTime != -1L)
       
   122                         throw new IllegalArgumentException();
       
   123                     accTime = now;
       
   124                 } else {
       
   125                     accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit);
       
   126                 }
       
   127                 accTime = WindowsFileAttributes.toWindowsTime(accTime);
       
   128             }
       
   129             if (createTime != null) {
       
   130                 if (createTime < 0L) {
       
   131                     if (createTime != -1L)
       
   132                         throw new IllegalArgumentException();
       
   133                     crTime = now;
       
   134                 } else {
       
   135                     crTime = TimeUnit.MILLISECONDS.convert(createTime, unit);
       
   136                 }
       
   137                 crTime = WindowsFileAttributes.toWindowsTime(crTime);
       
   138             }
       
   139 
       
   140             setFileTimes(crTime, accTime, modTime);
       
   141         }
       
   142     }
       
   143 
       
   144     static class Dos extends Basic implements DosFileAttributeView {
       
   145         private static final String READONLY_NAME = "readonly";
       
   146         private static final String ARCHIVE_NAME = "archive";
       
   147         private static final String SYSTEM_NAME = "system";
       
   148         private static final String HIDDEN_NAME = "hidden";
       
   149         private static final String ATTRIBUTES_NAME = "attributes";
       
   150 
       
   151         Dos(WindowsPath file, boolean followLinks) {
       
   152             super(file, followLinks);
       
   153         }
       
   154 
       
   155         @Override
       
   156         public String name() {
       
   157             return "dos";
       
   158         }
       
   159 
       
   160         @Override
       
   161         public Object getAttribute(String attribute) throws IOException {
       
   162             if (attribute.equals(READONLY_NAME))
       
   163                 return readAttributes().isReadOnly();
       
   164             if (attribute.equals(ARCHIVE_NAME))
       
   165                 return readAttributes().isArchive();
       
   166             if (attribute.equals(SYSTEM_NAME))
       
   167                 return readAttributes().isSystem();
       
   168             if (attribute.equals(HIDDEN_NAME))
       
   169                 return readAttributes().isHidden();
       
   170             // implementation specific
       
   171             if (attribute.equals(ATTRIBUTES_NAME))
       
   172                 return readAttributes().attributes();
       
   173             return super.getAttribute(attribute);
       
   174         }
       
   175 
       
   176         @Override
       
   177         public void setAttribute(String attribute, Object value)
       
   178             throws IOException
       
   179         {
       
   180             if (attribute.equals(READONLY_NAME)) {
       
   181                 setReadOnly((Boolean)value);
       
   182                 return;
       
   183             }
       
   184             if (attribute.equals(ARCHIVE_NAME)) {
       
   185                 setArchive((Boolean)value);
       
   186                 return;
       
   187             }
       
   188             if (attribute.equals(SYSTEM_NAME)) {
       
   189                 setSystem((Boolean)value);
       
   190                 return;
       
   191             }
       
   192             if (attribute.equals(HIDDEN_NAME)) {
       
   193                 setHidden((Boolean)value);
       
   194                 return;
       
   195             }
       
   196             super.setAttribute(attribute, value);
       
   197         }
       
   198 
       
   199         @Override
       
   200         public Map<String,?> readAttributes(String first, String[] rest)
       
   201             throws IOException
       
   202         {
       
   203             AttributesBuilder builder = AttributesBuilder.create(first, rest);
       
   204             WindowsFileAttributes attrs = readAttributes();
       
   205             addBasicAttributesToBuilder(attrs, builder);
       
   206             if (builder.match(READONLY_NAME))
       
   207                 builder.add(READONLY_NAME, attrs.isReadOnly());
       
   208             if (builder.match(ARCHIVE_NAME))
       
   209                 builder.add(ARCHIVE_NAME, attrs.isArchive());
       
   210             if (builder.match(SYSTEM_NAME))
       
   211                 builder.add(SYSTEM_NAME, attrs.isSystem());
       
   212             if (builder.match(HIDDEN_NAME))
       
   213                 builder.add(HIDDEN_NAME, attrs.isHidden());
       
   214             if (builder.match(ATTRIBUTES_NAME))
       
   215                 builder.add(ATTRIBUTES_NAME, attrs.attributes());
       
   216             return builder.unmodifiableMap();
       
   217         }
       
   218 
       
   219         /**
       
   220          * Update DOS attributes
       
   221          */
       
   222         private void updateAttributes(int flag, boolean enable)
       
   223             throws IOException
       
   224         {
       
   225             file.checkWrite();
       
   226 
       
   227             // GetFileAttribtues & SetFileAttributes do not follow links so when
       
   228             // following links we need the final target
       
   229             String path = WindowsLinkSupport.getFinalPath(file, followLinks);
       
   230             try {
       
   231                 int oldValue = GetFileAttributes(path);
       
   232                 int newValue = oldValue;
       
   233                 if (enable) {
       
   234                     newValue |= flag;
       
   235                 } else {
       
   236                     newValue &= ~flag;
       
   237                 }
       
   238                 if (newValue != oldValue) {
       
   239                     SetFileAttributes(path, newValue);
       
   240                 }
       
   241             } catch (WindowsException x) {
       
   242                 // don't reveal target in exception
       
   243                 x.rethrowAsIOException(file);
       
   244             }
       
   245         }
       
   246 
       
   247         @Override
       
   248         public void setReadOnly(boolean value) throws IOException {
       
   249             updateAttributes(FILE_ATTRIBUTE_READONLY, value);
       
   250         }
       
   251 
       
   252         @Override
       
   253         public void setHidden(boolean value) throws IOException {
       
   254             updateAttributes(FILE_ATTRIBUTE_HIDDEN, value);
       
   255         }
       
   256 
       
   257         @Override
       
   258         public void setArchive(boolean value) throws IOException {
       
   259             updateAttributes(FILE_ATTRIBUTE_ARCHIVE, value);
       
   260         }
       
   261 
       
   262         @Override
       
   263         public void setSystem(boolean value) throws IOException {
       
   264             updateAttributes(FILE_ATTRIBUTE_SYSTEM, value);
       
   265         }
       
   266 
       
   267         // package-private
       
   268         // Copy given attributes to the file.
       
   269         void setAttributes(WindowsFileAttributes attrs)
       
   270             throws IOException
       
   271         {
       
   272             // copy DOS attributes to target
       
   273             int flags = 0;
       
   274             if (attrs.isReadOnly()) flags |= FILE_ATTRIBUTE_READONLY;
       
   275             if (attrs.isHidden()) flags |= FILE_ATTRIBUTE_HIDDEN;
       
   276             if (attrs.isArchive()) flags |= FILE_ATTRIBUTE_ARCHIVE;
       
   277             if (attrs.isSystem()) flags |= FILE_ATTRIBUTE_SYSTEM;
       
   278             updateAttributes(flags, true);
       
   279 
       
   280             // copy file times to target - must be done after updating FAT attributes
       
   281             // as otherwise the last modified time may be wrong.
       
   282             setFileTimes(
       
   283                 WindowsFileAttributes.toWindowsTime(attrs.creationTime()),
       
   284                 WindowsFileAttributes.toWindowsTime(attrs.lastModifiedTime()),
       
   285                 WindowsFileAttributes.toWindowsTime(attrs.lastAccessTime()));
       
   286         }
       
   287     }
       
   288 
       
   289     static BasicFileAttributeView createBasicView(WindowsPath file, boolean followLinks) {
       
   290         return new Basic(file, followLinks);
       
   291     }
       
   292 
       
   293     static WindowsFileAttributeViews.Dos createDosView(WindowsPath file, boolean followLinks) {
       
   294         return new Dos(file, followLinks);
       
   295     }
       
   296 }