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; 033import io.ebean.enhance.asm.Attribute; 034import io.ebean.enhance.asm.ClassVisitor; 035import io.ebean.enhance.asm.ByteVector; 036import io.ebean.enhance.asm.ClassReader; 037import io.ebean.enhance.asm.ClassWriter; 038import io.ebean.enhance.asm.Label; 039 040/** 041 * A ModuleHashes attribute. This attribute is specific to the OpenJDK and may change in the future. 042 * 043 * @author Remi Forax 044 */ 045public final class ModuleHashesAttribute extends Attribute { 046 047 /** The name of the hashing algorithm. */ 048 public String algorithm; 049 050 /** A list of module names. */ 051 public List<String> modules; 052 053 /** The hash of the modules in {@link #modules}. The two lists must have the same size. */ 054 public List<byte[]> hashes; 055 056 /** 057 * Constructs a new {@link ModuleHashesAttribute}. 058 * 059 * @param algorithm the name of the hashing algorithm. 060 * @param modules a list of module names. 061 * @param hashes the hash of the modules in 'modules'. The two lists must have the same size. 062 */ 063 public ModuleHashesAttribute( 064 final String algorithm, final List<String> modules, final List<byte[]> hashes) { 065 super("ModuleHashes"); 066 this.algorithm = algorithm; 067 this.modules = modules; 068 this.hashes = hashes; 069 } 070 071 /** 072 * Constructs an empty {@link ModuleHashesAttribute}. This object can be passed as a prototype to 073 * the {@link ClassReader#accept(ClassVisitor, Attribute[], int)} method. 074 */ 075 public ModuleHashesAttribute() { 076 this(null, null, null); 077 } 078 079 @Override 080 protected Attribute read( 081 final ClassReader classReader, 082 final int offset, 083 final int length, 084 final char[] charBuffer, 085 final int codeAttributeOffset, 086 final Label[] labels) { 087 int currentOffset = offset; 088 089 String hashAlgorithm = classReader.readUTF8(currentOffset, charBuffer); 090 currentOffset += 2; 091 092 int numModules = classReader.readUnsignedShort(currentOffset); 093 currentOffset += 2; 094 095 ArrayList<String> moduleList = new ArrayList<>(numModules); 096 ArrayList<byte[]> hashList = new ArrayList<>(numModules); 097 098 for (int i = 0; i < numModules; ++i) { 099 String module = classReader.readModule(currentOffset, charBuffer); 100 currentOffset += 2; 101 moduleList.add(module); 102 103 int hashLength = classReader.readUnsignedShort(currentOffset); 104 currentOffset += 2; 105 byte[] hash = new byte[hashLength]; 106 for (int j = 0; j < hashLength; ++j) { 107 hash[j] = (byte) (classReader.readByte(currentOffset) & 0xFF); 108 currentOffset += 1; 109 } 110 hashList.add(hash); 111 } 112 return new ModuleHashesAttribute(hashAlgorithm, moduleList, hashList); 113 } 114 115 @Override 116 protected ByteVector write( 117 final ClassWriter classWriter, 118 final byte[] code, 119 final int codeLength, 120 final int maxStack, 121 final int maxLocals) { 122 ByteVector byteVector = new ByteVector(); 123 byteVector.putShort(classWriter.newUTF8(algorithm)); 124 if (modules == null) { 125 byteVector.putShort(0); 126 } else { 127 int numModules = modules.size(); 128 byteVector.putShort(numModules); 129 for (int i = 0; i < numModules; ++i) { 130 String module = modules.get(i); 131 byte[] hash = hashes.get(i); 132 byteVector 133 .putShort(classWriter.newModule(module)) 134 .putShort(hash.length) 135 .putByteArray(hash, 0, hash.length); 136 } 137 } 138 return byteVector; 139 } 140}