1 /* 2 * Copyright (c) 2015, 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 package jdk.internal.jimage; 26 27 import jdk.internal.jimage.decompressor.CompressedResourceHeader; 28 import java.nio.ByteBuffer; 29 import java.nio.ByteOrder; 30 import java.util.Collection; 31 import java.util.Map; 32 import java.util.Objects; 33 import java.util.Set; 34 35 /** 36 * Pool of resources. This class contain the content of a jimage file in the 37 * matter of Resource. 38 */ 39 public interface ResourcePool { 40 41 /** 42 * Resources visitor 43 */ 44 public interface Visitor { 45 46 /** 47 * Called for each visited Resource. 48 * 49 * @param resource The resource to deal with. 50 * @param order Byte order 51 * @param strings 52 * @return A resource or null if the passed resource is to be removed 53 * from the jimage. 54 * @throws Exception 55 */ 56 public Resource visit(Resource resource, ByteOrder order, 57 StringTable strings) throws Exception; 58 } 59 60 /** 61 * A JImage Resource. Fully identified by its path. 62 */ 63 public static class Resource { 64 65 private final String path; 66 private final ByteBuffer content; 67 68 private final String module; 69 70 public Resource(String path, ByteBuffer content) { 71 Objects.requireNonNull(path); 72 Objects.requireNonNull(content); 73 this.path = path; 74 this.content = content.asReadOnlyBuffer(); 75 String[] split = ImageFileCreator.splitPath(path); 76 module = split[0]; 77 } 78 79 public String getPath() { 80 return path; 81 } 82 83 public String getModule() { 84 return module; 85 } 86 87 /** 88 * The resource content. 89 * 90 * @return A read only buffer. 91 */ 92 public ByteBuffer getContent() { 93 return content; 94 } 95 96 public int getLength() { 97 return content.limit(); 98 } 99 100 public byte[] getByteArray() { 101 content.rewind(); 102 byte[] array = new byte[content.remaining()]; 103 content.get(array); 104 return array; 105 } 106 107 @Override 108 public String toString() { 109 return getPath(); 110 } 111 112 @Override 113 public boolean equals(Object obj) { 114 if (!(obj instanceof Resource)) { 115 return false; 116 } 117 Resource res = (Resource) obj; 118 return res.path.equals(path); 119 } 120 121 @Override 122 public int hashCode() { 123 int hash = 7; 124 hash = 53 * hash + Objects.hashCode(this.path); 125 return hash; 126 } 127 } 128 129 /** 130 * A resource that has been compressed. 131 */ 132 public static final class CompressedResource extends Resource { 133 134 private final long uncompressed_size; 135 136 private CompressedResource(String path, ByteBuffer content, 137 long uncompressed_size) { 138 super(path, content); 139 this.uncompressed_size = uncompressed_size; 140 } 141 142 public long getUncompressedSize() { 143 return uncompressed_size; 144 } 145 146 public static CompressedResource newCompressedResource(Resource original, 147 ByteBuffer compressed, 148 String plugin, String pluginConfig, StringTable strings, 149 ByteOrder order) throws Exception { 150 Objects.requireNonNull(original); 151 Objects.requireNonNull(compressed); 152 Objects.requireNonNull(plugin); 153 154 boolean isTerminal = !(original instanceof CompressedResource); 155 long uncompressed_size = original.getLength(); 156 if (original instanceof CompressedResource) { 157 CompressedResource comp = (CompressedResource) original; 158 uncompressed_size = comp.getUncompressedSize(); 159 } 160 int nameOffset = strings.addString(plugin); 161 int configOffset = -1; 162 if (pluginConfig != null) { 163 configOffset = strings.addString(plugin); 164 } 165 CompressedResourceHeader rh = 166 new CompressedResourceHeader(compressed.limit(), original.getLength(), 167 nameOffset, configOffset, isTerminal); 168 // Merge header with content; 169 byte[] h = rh.getBytes(order); 170 ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length); 171 bb.order(order); 172 bb.put(h); 173 bb.put(compressed); 174 ByteBuffer contentWithHeader = ByteBuffer.wrap(bb.array()); 175 176 CompressedResource compressedResource = 177 new CompressedResource(original.getPath(), 178 contentWithHeader, uncompressed_size); 179 return compressedResource; 180 } 181 } 182 183 /** 184 * Read only state. 185 * 186 * @return true if readonly false otherwise. 187 */ 188 public boolean isReadOnly(); 189 190 /** 191 * The byte order 192 * 193 * @return 194 */ 195 public ByteOrder getByteOrder(); 196 197 /** 198 * Add a resource. 199 * 200 * @param resource The Resource to add. 201 * @throws java.lang.Exception If the pool is read only. 202 */ 203 public void addResource(Resource resource) throws Exception; 204 205 /** 206 * Check if a resource is contained in the pool. 207 * 208 * @param res The resource to check. 209 * @return true if res is contained, false otherwise. 210 */ 211 public boolean contains(Resource res); 212 213 /** 214 * Get all resources contained in this pool instance. 215 * 216 * @return The collection of resources; 217 */ 218 public Collection<Resource> getResources(); 219 220 /** 221 * Get the resource for the passed path. 222 * 223 * @param path A resource path 224 * @return A Resource instance or null if the resource is not found 225 */ 226 public Resource getResource(String path); 227 228 /** 229 * The Image modules. It is computed based on the resources contained by 230 * this ResourcePool instance. 231 * 232 * @return The Image Modules. 233 */ 234 public Map<String, Set<String>> getModulePackages(); 235 236 /** 237 * Check if this pool contains some resources. 238 * 239 * @return True if contains some resources. 240 */ 241 public boolean isEmpty(); 242 243 /** 244 * Visit the resources contained in this ResourcePool. 245 * 246 * @param visitor The visitor 247 * @param output The pool to store resources. 248 * @param strings 249 * @throws Exception 250 */ 251 public void visit(Visitor visitor, ResourcePool output, StringTable strings) 252 throws Exception; 253 254 public void addTransformedResource(Resource original, ByteBuffer transformed) 255 throws Exception; 256 }