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