001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028 029package io.ebean.enhance.asm.commons; 030 031import java.util.ArrayList; 032import java.util.List; 033 034import io.ebean.enhance.asm.*; 035import io.ebean.enhance.asm.ByteVector; 036 037/** 038 * A ModuleHashes attribute. This attribute is specific to the OpenJDK and may change in the future. 039 * 040 * @author Remi Forax 041 */ 042public final class ModuleHashesAttribute extends Attribute { 043 044 /** The name of the hashing algorithm. */ 045 public String algorithm; 046 047 /** A list of module names. */ 048 public List<String> modules; 049 050 /** The hash of the modules in {@link #modules}. The two lists must have the same size. */ 051 public List<byte[]> hashes; 052 053 /** 054 * Constructs a new {@link ModuleHashesAttribute}. 055 * 056 * @param algorithm the name of the hashing algorithm. 057 * @param modules a list of module names. 058 * @param hashes the hash of the modules in 'modules'. The two lists must have the same size. 059 */ 060 public ModuleHashesAttribute( 061 final String algorithm, final List<String> modules, final List<byte[]> hashes) { 062 super("ModuleHashes"); 063 this.algorithm = algorithm; 064 this.modules = modules; 065 this.hashes = hashes; 066 } 067 068 /** 069 * Constructs an empty {@link ModuleHashesAttribute}. This object can be passed as a prototype to 070 * the {@link ClassReader#accept(ClassVisitor, Attribute[], int)} method. 071 */ 072 public ModuleHashesAttribute() { 073 this(null, null, null); 074 } 075 076 @Override 077 protected Attribute read( 078 final ClassReader classReader, 079 final int offset, 080 final int length, 081 final char[] charBuffer, 082 final int codeAttributeOffset, 083 final Label[] labels) { 084 int currentOffset = offset; 085 086 String hashAlgorithm = classReader.readUTF8(currentOffset, charBuffer); 087 currentOffset += 2; 088 089 int numModules = classReader.readUnsignedShort(currentOffset); 090 currentOffset += 2; 091 092 ArrayList<String> moduleList = new ArrayList<>(numModules); 093 ArrayList<byte[]> hashList = new ArrayList<>(numModules); 094 095 for (int i = 0; i < numModules; ++i) { 096 String module = classReader.readModule(currentOffset, charBuffer); 097 currentOffset += 2; 098 moduleList.add(module); 099 100 int hashLength = classReader.readUnsignedShort(currentOffset); 101 currentOffset += 2; 102 byte[] hash = new byte[hashLength]; 103 for (int j = 0; j < hashLength; ++j) { 104 hash[j] = (byte) classReader.readByte(currentOffset); 105 currentOffset += 1; 106 } 107 hashList.add(hash); 108 } 109 return new ModuleHashesAttribute(hashAlgorithm, moduleList, hashList); 110 } 111 112 @Override 113 protected ByteVector write( 114 final ClassWriter classWriter, 115 final byte[] code, 116 final int codeLength, 117 final int maxStack, 118 final int maxLocals) { 119 ByteVector byteVector = new ByteVector(); 120 byteVector.putShort(classWriter.newUTF8(algorithm)); 121 if (modules == null) { 122 byteVector.putShort(0); 123 } else { 124 int numModules = modules.size(); 125 byteVector.putShort(numModules); 126 for (int i = 0; i < numModules; ++i) { 127 String module = modules.get(i); 128 byte[] hash = hashes.get(i); 129 byteVector 130 .putShort(classWriter.newModule(module)) 131 .putShort(hash.length) 132 .putByteArray(hash, 0, hash.length); 133 } 134 } 135 return byteVector; 136 } 137}