001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.compress.harmony.unpack200; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Iterator; 022import java.util.List; 023 024import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationDefaultAttribute; 025import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation; 026import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue; 027import org.apache.commons.compress.harmony.unpack200.bytecode.Attribute; 028import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble; 029import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat; 030import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger; 031import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong; 032import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8; 033import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute; 034import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute; 035import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation; 036 037/** 038 * A group of metadata bands, such as class_RVA_bands, method_AD_bands etc. 039 */ 040public class MetadataBandGroup { 041 042 private static CPUTF8 rvaUTF8; 043 private static CPUTF8 riaUTF8; 044 045 private static CPUTF8 rvpaUTF8; 046 private static CPUTF8 ripaUTF8; 047 public static void setRiaAttributeName(final CPUTF8 cpUTF8Value) { 048 riaUTF8 = cpUTF8Value; 049 } 050 public static void setRipaAttributeName(final CPUTF8 cpUTF8Value) { 051 ripaUTF8 = cpUTF8Value; 052 } 053 054 public static void setRvaAttributeName(final CPUTF8 cpUTF8Value) { 055 rvaUTF8 = cpUTF8Value; 056 } 057 058 public static void setRvpaAttributeName(final CPUTF8 cpUTF8Value) { 059 rvpaUTF8 = cpUTF8Value; 060 } 061 062 private final String type; 063 064 private final CpBands cpBands; 065 066 private List<Attribute> attributes; 067 068 public int[] param_NB; 069 070 public int[] anno_N; 071 public CPUTF8[][] type_RS; 072 public int[][] pair_N; 073 public CPUTF8[] name_RU; 074 public int[] T; 075 public CPInteger[] caseI_KI; 076 public CPDouble[] caseD_KD; 077 public CPFloat[] caseF_KF; 078 public CPLong[] caseJ_KJ; 079 public CPUTF8[] casec_RS; 080 public String[] caseet_RS; 081 public String[] caseec_RU; 082 public CPUTF8[] cases_RU; 083 public int[] casearray_N; 084 public CPUTF8[] nesttype_RS; 085 public int[] nestpair_N; 086 public CPUTF8[] nestname_RU; 087 private int caseI_KI_Index; 088 089 private int caseD_KD_Index; 090 091 private int caseF_KF_Index; 092 093 private int caseJ_KJ_Index; 094 095 private int casec_RS_Index; 096 097 private int caseet_RS_Index; 098 099 private int caseec_RU_Index; 100 101 private int cases_RU_Index; 102 103 private int casearray_N_Index; 104 105 private int T_index; 106 107 private int nesttype_RS_Index; 108 109 private int nestpair_N_Index; 110 111 private Iterator<CPUTF8> nestname_RU_Iterator; 112 113 private int anno_N_Index; 114 115 private int pair_N_Index; 116 117 public MetadataBandGroup(final String type, final CpBands cpBands) { 118 this.type = type; 119 this.cpBands = cpBands; 120 } 121 122 private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator<CPUTF8> namesIterator) { 123 final CPUTF8[] elementNames = new CPUTF8[pairCount]; 124 final ElementValue[] elementValues = new ElementValue[pairCount]; 125 for (int j = 0; j < elementNames.length; j++) { 126 elementNames[j] = namesIterator.next(); 127 final int t = T[T_index++]; 128 elementValues[j] = new ElementValue(t, getNextValue(t)); 129 } 130 return new Annotation(pairCount, type, elementNames, elementValues); 131 } 132 133 private Attribute getAttribute(final int numAnnotations, final CPUTF8[] types, final int[] pairCounts, 134 final Iterator<CPUTF8> namesIterator) { 135 final Annotation[] annotations = new Annotation[numAnnotations]; 136 Arrays.setAll(annotations, i -> getAnnotation(types[i], pairCounts[i], namesIterator)); 137 return new RuntimeVisibleorInvisibleAnnotationsAttribute(type.equals("RVA") ? rvaUTF8 : riaUTF8, annotations); 138 } 139 140 public List<Attribute> getAttributes() { 141 // TODO: Optimize iterators! 142 if (attributes == null) { 143 attributes = new ArrayList<>(); 144 if (name_RU != null) { 145 final Iterator<CPUTF8> name_RU_Iterator = Arrays.asList(name_RU).iterator(); 146 if (!type.equals("AD")) { 147 T_index = 0; 148 } 149 caseI_KI_Index = 0; 150 caseD_KD_Index = 0; 151 caseF_KF_Index = 0; 152 caseJ_KJ_Index = 0; 153 casec_RS_Index = 0; 154 caseet_RS_Index = 0; 155 caseec_RU_Index = 0; 156 cases_RU_Index = 0; 157 casearray_N_Index = 0; 158 nesttype_RS_Index = 0; 159 nestpair_N_Index = 0; 160 nestname_RU_Iterator = Arrays.asList(nestname_RU).iterator(); 161 if (type.equals("RVA") || type.equals("RIA")) { 162 for (int i = 0; i < anno_N.length; i++) { 163 attributes.add(getAttribute(anno_N[i], type_RS[i], pair_N[i], name_RU_Iterator)); 164 } 165 } else if (type.equals("RVPA") || type.equals("RIPA")) { 166 anno_N_Index = 0; 167 pair_N_Index = 0; 168 for (final int element : param_NB) { 169 attributes.add(getParameterAttribute(element, name_RU_Iterator)); 170 } 171 } 172 } else if (type.equals("AD")) { 173 for (final int element : T) { 174 attributes.add(new AnnotationDefaultAttribute(new ElementValue(element, getNextValue(element)))); 175 } 176 } 177 } 178 return attributes; 179 } 180 181 private Object getNextValue(final int t) { 182 switch (t) { 183 case 'B': 184 case 'C': 185 case 'I': 186 case 'S': 187 case 'Z': 188 return caseI_KI[caseI_KI_Index++]; 189 case 'D': 190 return caseD_KD[caseD_KD_Index++]; 191 case 'F': 192 return caseF_KF[caseF_KF_Index++]; 193 case 'J': 194 return caseJ_KJ[caseJ_KJ_Index++]; 195 case 'c': 196 return casec_RS[casec_RS_Index++]; 197 case 'e': 198 // TODO: check this - it may not work if the first string already 199 // has a colon in it 200 final String enumString = caseet_RS[caseet_RS_Index++] + ":" + caseec_RU[caseec_RU_Index++]; 201 return cpBands.cpNameAndTypeValue(enumString); 202 case 's': 203 return cases_RU[cases_RU_Index++]; 204 case '[': 205 final int arraySize = casearray_N[casearray_N_Index++]; 206 final ElementValue[] nestedArray = new ElementValue[arraySize]; 207 for (int i = 0; i < arraySize; i++) { 208 final int nextT = T[T_index++]; 209 nestedArray[i] = new ElementValue(nextT, getNextValue(nextT)); 210 } 211 return nestedArray; 212 case '@': 213 final CPUTF8 type = nesttype_RS[nesttype_RS_Index++]; 214 final int numPairs = nestpair_N[nestpair_N_Index++]; 215 216 return getAnnotation(type, numPairs, nestname_RU_Iterator); 217 } 218 return null; 219 } 220 221 private Attribute getParameterAttribute(final int numParameters, final Iterator<CPUTF8> namesIterator) { 222 final ParameterAnnotation[] parameterAnnotations = new ParameterAnnotation[numParameters]; 223 for (int i = 0; i < numParameters; i++) { 224 final int numAnnotations = anno_N[anno_N_Index++]; 225 final int[] pairCounts = pair_N[pair_N_Index++]; 226 final Annotation[] annotations = new Annotation[numAnnotations]; 227 Arrays.setAll(annotations, j -> getAnnotation(type_RS[anno_N_Index - 1][j], pairCounts[j], namesIterator)); 228 parameterAnnotations[i] = new ParameterAnnotation(annotations); 229 } 230 return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type.equals("RVPA") ? rvpaUTF8 : ripaUTF8, 231 parameterAnnotations); 232 } 233 234}