1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.signature.cts; 17 18 import java.io.File; 19 import java.io.FileInputStream; 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.net.URL; 23 import java.util.Objects; 24 import java.util.zip.ZipEntry; 25 import java.util.zip.ZipFile; 26 27 /** 28 * Workaround for the lack of a zip file system provider on Android. 29 */ 30 public abstract class VirtualPath { 31 32 /** 33 * Get a path to the local file system. 34 */ get(String path)35 public static LocalFilePath get(String path) { 36 return new LocalFilePath(path); 37 } 38 39 /** 40 * Get a path to an entry in a zip file, i.e. a zip file system. 41 */ get(ZipFile zip, ZipEntry entry)42 public static ZipEntryPath get(ZipFile zip, ZipEntry entry) { 43 return new ZipEntryPath(zip, entry); 44 } 45 46 /** 47 * Get a path to a resource in a ClassLoader. 48 * 49 * @param classLoader the ClassLoader containing the resource. 50 * @param resourceName the name of the resource, must not start with a /. 51 */ get(ClassLoader classLoader, String resourceName)52 public static ResourcePath get(ClassLoader classLoader, String resourceName) 53 throws IOException { 54 return new ResourcePath(classLoader, resourceName); 55 } 56 newInputStream()57 public abstract InputStream newInputStream() throws IOException; 58 59 /** 60 * Override as abstract to force sub-classes to implement it. 61 */ 62 @Override hashCode()63 public abstract int hashCode(); 64 65 /** 66 * Override as abstract to force sub-classes to implement it. 67 */ 68 @Override equals(Object obj)69 public abstract boolean equals(Object obj); 70 71 /** 72 * Override as abstract to force sub-classes to implement it. 73 */ 74 @Override toString()75 public abstract String toString(); 76 77 public static class LocalFilePath extends VirtualPath { 78 private final String path; 79 LocalFilePath(String path)80 LocalFilePath(String path) { 81 this.path = path; 82 } 83 toFile()84 public File toFile() { 85 return new File(path); 86 } 87 resolve(String relative)88 public LocalFilePath resolve(String relative) { 89 return new LocalFilePath(path + "/" + relative); 90 } 91 92 @Override newInputStream()93 public InputStream newInputStream() throws IOException { 94 return new FileInputStream(path); 95 } 96 97 @Override equals(Object o)98 public boolean equals(Object o) { 99 if (this == o) { 100 return true; 101 } 102 if (o == null || getClass() != o.getClass()) { 103 return false; 104 } 105 LocalFilePath that = (LocalFilePath) o; 106 return path.equals(that.path); 107 } 108 109 @Override hashCode()110 public int hashCode() { 111 return Objects.hash(path); 112 } 113 114 @Override toString()115 public String toString() { 116 return path; 117 } 118 } 119 120 private static class ZipEntryPath extends VirtualPath { 121 122 private final ZipFile zip; 123 124 private final ZipEntry entry; 125 ZipEntryPath(ZipFile zip, ZipEntry entry)126 private ZipEntryPath(ZipFile zip, ZipEntry entry) { 127 this.zip = zip; 128 this.entry = entry; 129 } 130 131 @Override newInputStream()132 public InputStream newInputStream() throws IOException { 133 return zip.getInputStream(entry); 134 } 135 136 @Override equals(Object o)137 public boolean equals(Object o) { 138 if (this == o) { 139 return true; 140 } 141 if (o == null || getClass() != o.getClass()) { 142 return false; 143 } 144 ZipEntryPath that = (ZipEntryPath) o; 145 return zip.getName().equals(that.zip.getName()) 146 && entry.getName().equals(that.entry.getName()); 147 } 148 149 @Override hashCode()150 public int hashCode() { 151 return Objects.hash(zip.getName(), entry.getName()); 152 } 153 154 @Override toString()155 public String toString() { 156 return "zip:file:" + zip.getName() + "!/" + entry.getName(); 157 } 158 } 159 160 public static class ResourcePath extends VirtualPath { 161 private final URL url; 162 ResourcePath(ClassLoader classLoader, String path)163 ResourcePath(ClassLoader classLoader, String path) throws IOException { 164 this.url = classLoader.getResource(path); 165 if (url == null) { 166 throw new IOException("Could not find resource '" + path + "' in " + classLoader); 167 } 168 } 169 170 @Override newInputStream()171 public InputStream newInputStream() throws IOException { 172 return url.openStream(); 173 } 174 175 @Override equals(Object o)176 public boolean equals(Object o) { 177 if (this == o) { 178 return true; 179 } 180 if (o == null || getClass() != o.getClass()) { 181 return false; 182 } 183 ResourcePath that = (ResourcePath) o; 184 return url.equals(that.url); 185 } 186 187 @Override hashCode()188 public int hashCode() { 189 return Objects.hash(url); 190 } 191 192 @Override toString()193 public String toString() { 194 return url.toExternalForm(); 195 } 196 } 197 } 198