1 /*
   2  * Copyright (c) 2009, 2018, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nio.zipfs;
  27 
  28 import java.io.IOException;
  29 import java.nio.file.attribute.BasicFileAttributeView;
  30 import java.nio.file.attribute.FileAttributeView;
  31 import java.nio.file.attribute.FileTime;
  32 import java.nio.file.attribute.GroupPrincipal;
  33 import java.nio.file.attribute.PosixFileAttributeView;
  34 import java.nio.file.attribute.PosixFilePermission;
  35 import java.nio.file.attribute.UserPrincipal;
  36 import java.util.LinkedHashMap;
  37 import java.util.Map;
  38 import java.util.Set;
  39 
  40 /**
  41  * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
  42  */
  43 class ZipFileAttributeView implements PosixFileAttributeView {
  44     private static enum AttrID {
  45         size,
  46         creationTime,
  47         lastAccessTime,
  48         lastModifiedTime,
  49         isDirectory,
  50         isRegularFile,
  51         isSymbolicLink,
  52         isOther,
  53         fileKey,
  54         compressedSize,
  55         crc,
  56         method,
  57         permissions
  58     };
  59 
  60     private static enum ViewType {
  61         zip,
  62         posix,
  63         basic
  64     }
  65 
  66     private final ZipPath path;
  67     private final ViewType type;
  68 
  69     private ZipFileAttributeView(ZipPath path, ViewType type) {
  70         this.path = path;
  71         this.type = type;
  72     }
  73 
  74     @SuppressWarnings("unchecked") // Cast to V
  75     static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) {
  76         if (type == null)
  77             throw new NullPointerException();
  78         if (type == BasicFileAttributeView.class)
  79             return (V)new ZipFileAttributeView(path, ViewType.basic);
  80         if (type == PosixFileAttributeView.class)
  81             return (V)new ZipFileAttributeView(path, ViewType.posix);
  82         if (type == ZipFileAttributeView.class)
  83             return (V)new ZipFileAttributeView(path, ViewType.zip);
  84         return null;
  85     }
  86 
  87     static ZipFileAttributeView get(ZipPath path, String type) {
  88         if (type == null)
  89             throw new NullPointerException();
  90         if (type.equals("basic"))
  91             return new ZipFileAttributeView(path, ViewType.basic);
  92         if (type.equals("posix"))
  93             return new ZipFileAttributeView(path, ViewType.posix);
  94         if (type.equals("zip"))
  95             return new ZipFileAttributeView(path, ViewType.zip);
  96         return null;
  97     }
  98 
  99     @Override
 100     public String name() {
 101         switch (type) {
 102         case zip:
 103             return "zip";
 104         case posix:
 105             return "posix";
 106         case basic:
 107         default:
 108             return "basic";
 109         }
 110     }
 111 
 112     public ZipFileAttributes readAttributes() throws IOException {
 113         return path.getAttributes();
 114     }
 115 
 116     @Override
 117     public void setTimes(FileTime lastModifiedTime,
 118                          FileTime lastAccessTime,
 119                          FileTime createTime)
 120         throws IOException
 121     {
 122         path.setTimes(lastModifiedTime, lastAccessTime, createTime);
 123     }
 124 
 125     @Override
 126     public UserPrincipal getOwner() throws IOException {
 127         throw new UnsupportedOperationException("ZipFileSystem does not support getOwner.");
 128     }
 129 
 130     @Override
 131     public void setOwner(UserPrincipal owner) throws IOException {
 132         throw new UnsupportedOperationException("ZipFileSystem does not support setOwner.");
 133     }
 134 
 135     @Override
 136     public void setPermissions(Set<PosixFilePermission> perms) throws IOException {
 137         path.setPermissions(perms);
 138     }
 139 
 140     @Override
 141     public void setGroup(GroupPrincipal group) throws IOException {
 142         throw new UnsupportedOperationException("ZipFileSystem does not support setGroup.");
 143     }
 144 
 145     @SuppressWarnings("unchecked")
 146     void setAttribute(String attribute, Object value)
 147         throws IOException
 148     {
 149         try {
 150             if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime)
 151                 setTimes((FileTime)value, null, null);
 152             if (AttrID.valueOf(attribute) == AttrID.lastAccessTime)
 153                 setTimes(null, (FileTime)value, null);
 154             if (AttrID.valueOf(attribute) == AttrID.creationTime)
 155                 setTimes(null, null, (FileTime)value);
 156             if (AttrID.valueOf(attribute) == AttrID.permissions)
 157                 setPermissions((Set<PosixFilePermission>)value);
 158             return;
 159         } catch (IllegalArgumentException x) {
 160             throw new UnsupportedOperationException("'" + attribute +
 161                 "' is unknown or read-only attribute");
 162         }
 163     }
 164 
 165     Map<String, Object> readAttributes(String attributes)
 166         throws IOException
 167     {
 168         ZipFileAttributes zfas = readAttributes();
 169         LinkedHashMap<String, Object> map = new LinkedHashMap<>();
 170         if ("*".equals(attributes)) {
 171             for (AttrID id : AttrID.values()) {
 172                 try {
 173                     map.put(id.name(), attribute(id, zfas));
 174                 } catch (IllegalArgumentException x) {}
 175             }
 176         } else {
 177             String[] as = attributes.split(",");
 178             for (String a : as) {
 179                 try {
 180                     map.put(a, attribute(AttrID.valueOf(a), zfas));
 181                 } catch (IllegalArgumentException x) {}
 182             }
 183         }
 184         return map;
 185     }
 186 
 187     private Object attribute(AttrID id, ZipFileAttributes zfas) {
 188         switch (id) {
 189         case size:
 190             return zfas.size();
 191         case creationTime:
 192             return zfas.creationTime();
 193         case lastAccessTime:
 194             return zfas.lastAccessTime();
 195         case lastModifiedTime:
 196             return zfas.lastModifiedTime();
 197         case isDirectory:
 198             return zfas.isDirectory();
 199         case isRegularFile:
 200             return zfas.isRegularFile();
 201         case isSymbolicLink:
 202             return zfas.isSymbolicLink();
 203         case isOther:
 204             return zfas.isOther();
 205         case fileKey:
 206             return zfas.fileKey();
 207         case permissions:
 208             if (type == ViewType.posix || type == ViewType.zip) {
 209                 try {
 210                    return zfas.permissions();
 211                 } catch (UnsupportedOperationException e) {
 212                     return null;
 213                 }
 214             }
 215             break;
 216         case compressedSize:
 217             if (type == ViewType.zip) {
 218                 return zfas.compressedSize();
 219             }
 220             break;
 221         case crc:
 222             if (type == ViewType.zip) {
 223                 return zfas.crc();
 224             }
 225             break;
 226         case method:
 227             if (type == ViewType.zip) {
 228                 return zfas.method();
 229             }
 230             break;
 231         }
 232         return null;
 233     }
 234 }