1/* 2 * Copyright (c) 2014, 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 */ 25package jdk.internal.jrtfs; 26 27import java.nio.file.LinkOption; 28import java.nio.file.attribute.*; 29import java.io.IOException; 30import java.util.LinkedHashMap; 31import java.util.Map; 32import java.util.Objects; 33 34/** 35 * File attribute view for jrt file system. 36 * 37 * @implNote This class needs to maintain JDK 8 source compatibility. 38 * 39 * It is used internally in the JDK to implement jimage/jrtfs access, 40 * but also compiled and delivered as part of the jrtfs.jar to support access 41 * to the jimage file provided by the shipped JDK by tools running on JDK 8. 42 */ 43final class JrtFileAttributeView implements BasicFileAttributeView { 44 45 private static enum AttrID { 46 size, 47 creationTime, 48 lastAccessTime, 49 lastModifiedTime, 50 isDirectory, 51 isRegularFile, 52 isSymbolicLink, 53 isOther, 54 fileKey, 55 compressedSize, 56 extension 57 }; 58 59 private final JrtPath path; 60 private final boolean isJrtView; 61 private final LinkOption[] options; 62 63 private JrtFileAttributeView(JrtPath path, boolean isJrtView, LinkOption... options) { 64 this.path = path; 65 this.isJrtView = isJrtView; 66 this.options = options; 67 } 68 69 @SuppressWarnings("unchecked") // Cast to V 70 static <V extends FileAttributeView> V get(JrtPath path, Class<V> type, LinkOption... options) { 71 Objects.requireNonNull(type); 72 if (type == BasicFileAttributeView.class) { 73 return (V) new JrtFileAttributeView(path, false, options); 74 } 75 if (type == JrtFileAttributeView.class) { 76 return (V) new JrtFileAttributeView(path, true, options); 77 } 78 return null; 79 } 80 81 static JrtFileAttributeView get(JrtPath path, String type, LinkOption... options) { 82 Objects.requireNonNull(type); 83 if (type.equals("basic")) { 84 return new JrtFileAttributeView(path, false, options); 85 } 86 if (type.equals("jrt")) { 87 return new JrtFileAttributeView(path, true, options); 88 } 89 return null; 90 } 91 92 @Override 93 public String name() { 94 return isJrtView ? "jrt" : "basic"; 95 } 96 97 @Override 98 public JrtFileAttributes readAttributes() throws IOException { 99 return path.getAttributes(options); 100 } 101 102 @Override 103 public void setTimes(FileTime lastModifiedTime, 104 FileTime lastAccessTime, 105 FileTime createTime) throws IOException { 106 path.setTimes(lastModifiedTime, lastAccessTime, createTime); 107 } 108 109 static void setAttribute(JrtPath path, String attribute, Object value) 110 throws IOException { 111 int colonPos = attribute.indexOf(':'); 112 if (colonPos != -1) { // type = "basic", if no ":" 113 String type = attribute.substring(0, colonPos++); 114 if (!type.equals("basic") && !type.equals("jrt")) { 115 throw new UnsupportedOperationException( 116 "view <" + type + "> is not supported"); 117 } 118 attribute = attribute.substring(colonPos); 119 } 120 try { 121 AttrID id = AttrID.valueOf(attribute); 122 if (id == AttrID.lastModifiedTime) { 123 path.setTimes((FileTime) value, null, null); 124 } else if (id == AttrID.lastAccessTime) { 125 path.setTimes(null, (FileTime) value, null); 126 } else if (id == AttrID.creationTime) { 127 path.setTimes(null, null, (FileTime) value); 128 } 129 return; 130 } catch (IllegalArgumentException x) {} 131 throw new UnsupportedOperationException("'" + attribute 132 + "' is unknown or read-only attribute"); 133 } 134 135 static Map<String, Object> readAttributes(JrtPath path, String attributes, 136 LinkOption... options) 137 throws IOException { 138 int colonPos = attributes.indexOf(':'); 139 boolean isJrtView = false; 140 if (colonPos != -1) { // type = "basic", if no ":" 141 String type = attributes.substring(0, colonPos++); 142 if (!type.equals("basic") && !type.equals("jrt")) { 143 throw new UnsupportedOperationException("view <" + type + 144 "> is not supported"); 145 } 146 isJrtView = true; 147 attributes = attributes.substring(colonPos); 148 } 149 JrtFileAttributes jrtfas = path.getAttributes(); 150 LinkedHashMap<String, Object> map = new LinkedHashMap<>(); 151 if ("*".equals(attributes)) { 152 for (AttrID id : AttrID.values()) { 153 map.put(id.name(), attribute(id, jrtfas, isJrtView)); 154 } 155 } else { 156 String[] as = attributes.split(","); 157 for (String a : as) { 158 //throw IllegalArgumentException 159 map.put(a, attribute(AttrID.valueOf(a), jrtfas, isJrtView)); 160 } 161 } 162 return map; 163 } 164 165 static Object attribute(AttrID id, JrtFileAttributes jrtfas, boolean isJrtView) { 166 switch (id) { 167 case size: 168 return jrtfas.size(); 169 case creationTime: 170 return jrtfas.creationTime(); 171 case lastAccessTime: 172 return jrtfas.lastAccessTime(); 173 case lastModifiedTime: 174 return jrtfas.lastModifiedTime(); 175 case isDirectory: 176 return jrtfas.isDirectory(); 177 case isRegularFile: 178 return jrtfas.isRegularFile(); 179 case isSymbolicLink: 180 return jrtfas.isSymbolicLink(); 181 case isOther: 182 return jrtfas.isOther(); 183 case fileKey: 184 return jrtfas.fileKey(); 185 case compressedSize: 186 if (isJrtView) { 187 return jrtfas.compressedSize(); 188 } 189 break; 190 case extension: 191 if (isJrtView) { 192 return jrtfas.extension(); 193 } 194 break; 195 } 196 return null; 197 } 198} 199