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.internal.jimage; 27 28 import java.nio.ByteBuffer; 29 30 public final class ImageLocation { 31 final static int ATTRIBUTE_END = 0; 32 final static int ATTRIBUTE_BASE = 1; 33 final static int ATTRIBUTE_PARENT = 2; 34 final static int ATTRIBUTE_EXTENSION = 3; 35 final static int ATTRIBUTE_OFFSET = 4; 36 final static int ATTRIBUTE_COMPRESSED = 5; 37 final static int ATTRIBUTE_UNCOMPRESSED = 6; 38 final static int ATTRIBUTE_COUNT = 7; 39 40 private int locationOffset; 41 private long[] attributes; 42 private byte[] bytes; 43 private final ImageStrings strings; 44 45 private ImageLocation(ImageStrings strings) { 46 this.strings = strings; 47 } 48 49 void writeTo(ImageStream stream) { 50 compress(); 51 locationOffset = stream.getPosition(); 52 stream.put(bytes, 0, bytes.length); 53 } 54 55 static ImageLocation readFrom(ByteBuffer locationsBuffer, int offset, ImageStrings strings) { 56 final long[] attributes = new long[ATTRIBUTE_COUNT]; 57 58 for (int i = offset; true; ) { 59 int data = locationsBuffer.get(i++) & 0xFF; 60 int kind = attributeKind(data); 61 assert ATTRIBUTE_END <= kind && kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 62 63 if (kind == ATTRIBUTE_END) { 64 break; 65 } 66 67 int length = attributeLength(data); 68 long value = 0; 69 70 for (int j = 0; j < length; j++) { 71 value <<= 8; 72 value |= locationsBuffer.get(i++) & 0xFF; 73 } 74 75 attributes[kind] = value; 76 } 77 78 ImageLocation location = new ImageLocation(strings); 79 location.attributes = attributes; 80 81 return location; 82 } 83 84 private static int attributeLength(int data) { 85 return (data & 0x7) + 1; 86 } 87 88 private static int attributeKind(int data) { 89 return data >>> 3; 90 } 91 92 public boolean verify(UTF8String name) { 93 UTF8String match = UTF8String.match(name, getParent()); 94 95 if (match == null) { 96 return false; 97 } 98 99 match = UTF8String.match(match, getBase()); 100 101 if (match == null) { 102 return false; 103 } 104 105 match = UTF8String.match(match, getExtension()); 106 107 return match != null && match.length() == 0; 108 } 109 110 111 long getAttribute(int kind) { 112 assert ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 113 decompress(); 114 115 return attributes[kind]; 116 } 117 118 UTF8String getAttributeUTF8String(int kind) { 119 assert ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 120 decompress(); 121 122 return strings.get((int)attributes[kind]); 123 } 124 125 String getAttributeString(int kind) { 126 return getAttributeUTF8String(kind).toString(); 127 } 128 129 ImageLocation addAttribute(int kind, long value) { 130 assert ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 131 decompress(); 132 attributes[kind] = value; 133 return this; 134 } 135 136 private void decompress() { 137 if (attributes == null) { 138 attributes = new long[ATTRIBUTE_COUNT]; 139 } 140 141 if (bytes != null) { 142 for (int i = 0; i < bytes.length; ) { 143 int data = bytes[i++] & 0xFF; 144 int kind = attributeKind(data); 145 146 if (kind == ATTRIBUTE_END) { 147 break; 148 } 149 150 assert ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT : "Invalid attribute kind"; 151 int length = attributeLength(data); 152 long value = 0; 153 154 for (int j = 0; j < length; j++) { 155 value <<= 8; 156 value |= bytes[i++] & 0xFF; 157 } 158 159 attributes[kind] = value; 160 } 161 162 bytes = null; 163 } 164 } 165 166 private void compress() { 167 if (bytes == null) { 168 ImageStream stream = new ImageStream(16); 169 170 for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) { 171 long value = attributes[kind]; 172 173 if (value != 0) { 174 int n = (63 - Long.numberOfLeadingZeros(value)) >> 3; 175 stream.put((kind << 3) | n); 176 177 for (int i = n; i >= 0; i--) { 178 stream.put((int)(value >> (i << 3))); 179 } 180 } 181 } 182 183 stream.put(ATTRIBUTE_END << 3); 184 bytes = stream.toArray(); 185 attributes = null; 186 } 187 } 188 189 static ImageLocation newLocation(UTF8String fullname, ImageStrings strings, long contentOffset, long compressedSize, long uncompressedSize) { 190 UTF8String base; 191 UTF8String extension = extension(fullname); 192 int parentOffset = ImageStrings.EMPTY_OFFSET; 193 int extensionOffset = ImageStrings.EMPTY_OFFSET; 194 int baseOffset; 195 196 if (extension.length() != 0) { 197 UTF8String parent = parent(fullname); 198 base = base(fullname); 199 parentOffset = strings.add(parent); 200 extensionOffset = strings.add(extension); 201 } else { 202 base = fullname; 203 } 204 205 baseOffset = strings.add(base); 206 207 return new ImageLocation(strings) 208 .addAttribute(ATTRIBUTE_BASE, baseOffset) 209 .addAttribute(ATTRIBUTE_PARENT, parentOffset) 210 .addAttribute(ATTRIBUTE_EXTENSION, extensionOffset) 211 .addAttribute(ATTRIBUTE_OFFSET, contentOffset) 212 .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize) 213 .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize); 214 } 215 216 @Override 217 public int hashCode() { 218 return getExtension().hashCode(getBase().hashCode(getParent().hashCode())); 219 } 220 221 int hashCode(int base) { 222 return getExtension().hashCode(getBase().hashCode(getParent().hashCode(base))); 223 } 224 225 @Override 226 public boolean equals(Object obj) { 227 if (this == obj) { 228 return true; 229 } 230 231 if (!(obj instanceof ImageLocation)) { 232 return false; 233 } 234 235 ImageLocation other = (ImageLocation)obj; 236 237 return getBaseOffset() == other.getBaseOffset() && 238 getParentOffset() == other.getParentOffset() && 239 getExtensionOffset() == other.getExtensionOffset(); 240 } 241 242 static UTF8String parent(UTF8String fullname) { 243 int slash = fullname.lastIndexOf('/'); 244 245 return slash == UTF8String.NOT_FOUND ? UTF8String.EMPTY_STRING : fullname.substring(0, slash + 1); 246 } 247 248 static UTF8String extension(UTF8String fullname) { 249 int dot = fullname.lastIndexOf('.'); 250 251 return dot == UTF8String.NOT_FOUND ? UTF8String.EMPTY_STRING : fullname.substring(dot); 252 } 253 254 static UTF8String base(UTF8String fullname) { 255 int slash = fullname.lastIndexOf('/'); 256 257 if (slash != UTF8String.NOT_FOUND) { 258 fullname = fullname.substring(slash + 1); 259 } 260 261 int dot = fullname.lastIndexOf('.'); 262 263 if (dot != UTF8String.NOT_FOUND) { 264 fullname = fullname.substring(0, dot); 265 } 266 267 return fullname; 268 } 269 270 int getLocationOffset() { 271 return locationOffset; 272 } 273 274 UTF8String getBase() { 275 return getAttributeUTF8String(ATTRIBUTE_BASE); 276 } 277 278 public String getBaseString() { 279 return getBase().toString(); 280 } 281 282 int getBaseOffset() { 283 return (int)getAttribute(ATTRIBUTE_BASE); 284 } 285 286 UTF8String getParent() { 287 return getAttributeUTF8String(ATTRIBUTE_PARENT); 288 } 289 290 public String getParentString() { 291 return getParent().toString(); 292 } 293 294 int getParentOffset() { 295 return (int)getAttribute(ATTRIBUTE_PARENT); 296 } 297 298 UTF8String getExtension() { 299 return getAttributeUTF8String(ATTRIBUTE_EXTENSION); 300 } 301 302 public String getExtensionString() { 303 return getExtension().toString(); 304 } 305 306 int getExtensionOffset() { 307 return (int)getAttribute(ATTRIBUTE_EXTENSION); 308 } 309 310 UTF8String getName() { 311 return getBase().concat(getExtension()); 312 } 313 314 String getNameString() { 315 return getName().toString(); 316 } 317 318 UTF8String getFullname() { 319 return getParent().concat(getBase(), getExtension()); 320 } 321 322 String getFullnameString() { 323 return getFullname().toString(); 324 } 325 326 public long getContentOffset() { 327 return getAttribute(ATTRIBUTE_OFFSET); 328 } 329 330 public long getCompressedSize() { 331 return getAttribute(ATTRIBUTE_COMPRESSED); 332 } 333 334 public long getUncompressedSize() { 335 return getAttribute(ATTRIBUTE_UNCOMPRESSED); 336 } 337 338 @Override 339 public String toString() { 340 final StringBuilder sb = new StringBuilder(); 341 decompress(); 342 343 for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) { 344 long value = attributes[kind]; 345 346 if (value == 0) { 347 continue; 348 } 349 350 switch (kind) { 351 case ATTRIBUTE_BASE: 352 sb.append("Base: "); 353 sb.append(value); 354 sb.append(' '); 355 sb.append(strings.get((int)value).toString()); 356 break; 357 358 case ATTRIBUTE_PARENT: 359 sb.append("Parent: "); 360 sb.append(value); 361 sb.append(' '); 362 sb.append(strings.get((int)value).toString()); 363 break; 364 365 case ATTRIBUTE_EXTENSION: 366 sb.append("Extension: "); 367 sb.append(value); 368 sb.append(' '); 369 sb.append(strings.get((int)value).toString()); 370 break; 371 372 case ATTRIBUTE_OFFSET: 373 sb.append("Offset: "); 374 sb.append(value); 375 break; 376 377 case ATTRIBUTE_COMPRESSED: 378 sb.append("Compressed: "); 379 sb.append(value); 380 break; 381 382 case ATTRIBUTE_UNCOMPRESSED: 383 sb.append("Uncompressed: "); 384 sb.append(value); 385 break; 386 } 387 388 sb.append("; "); 389 } 390 391 return sb.toString(); 392 } 393 } | 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.internal.jimage; 27 28 public final class ImageLocation extends ImageLocationBase { 29 ImageLocation(long[] attributes, ImageStringsReader strings) { 30 super(attributes, strings); 31 } 32 33 static ImageLocation readFrom(BasicImageReader reader, int offset) { 34 long[] attributes = reader.getAttributes(offset); 35 ImageStringsReader strings = reader.getStrings(); 36 37 return new ImageLocation(attributes, strings); 38 } 39 } |