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 048 public static void setRiaAttributeName(final CPUTF8 cpUTF8Value) { 049 riaUTF8 = cpUTF8Value; 050 } 051 052 public static void setRipaAttributeName(final CPUTF8 cpUTF8Value) { 053 ripaUTF8 = cpUTF8Value; 054 } 055 056 public static void setRvaAttributeName(final CPUTF8 cpUTF8Value) { 057 rvaUTF8 = cpUTF8Value; 058 } 059 060 public static void setRvpaAttributeName(final CPUTF8 cpUTF8Value) { 061 rvpaUTF8 = cpUTF8Value; 062 } 063 064 private final String type; 065 066 private final CpBands cpBands; 067 068 private List<Attribute> attributes; 069 070 public int[] param_NB; 071 072 public int[] anno_N; 073 public CPUTF8[][] type_RS; 074 public int[][] pair_N; 075 public CPUTF8[] name_RU; 076 public int[] T; 077 public CPInteger[] caseI_KI; 078 public CPDouble[] caseD_KD; 079 public CPFloat[] caseF_KF; 080 public CPLong[] caseJ_KJ; 081 public CPUTF8[] casec_RS; 082 public String[] caseet_RS; 083 public String[] caseec_RU; 084 public CPUTF8[] cases_RU; 085 public int[] casearray_N; 086 public CPUTF8[] nesttype_RS; 087 public int[] nestpair_N; 088 public CPUTF8[] nestname_RU; 089 private int caseI_KI_Index; 090 091 private int caseD_KD_Index; 092 093 private int caseF_KF_Index; 094 095 private int caseJ_KJ_Index; 096 097 private int casec_RS_Index; 098 099 private int caseet_RS_Index; 100 101 private int caseec_RU_Index; 102 103 private int cases_RU_Index; 104 105 private int casearray_N_Index; 106 107 private int T_index; 108 109 private int nesttype_RS_Index; 110 111 private int nestpair_N_Index; 112 113 private Iterator<CPUTF8> nestname_RU_Iterator; 114 115 private int anno_N_Index; 116 117 private int pair_N_Index; 118 119 public MetadataBandGroup(final String type, final CpBands cpBands) { 120 this.type = type; 121 this.cpBands = cpBands; 122 } 123 124 private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator<CPUTF8> namesIterator) { 125 final CPUTF8[] elementNames = new CPUTF8[pairCount]; 126 final ElementValue[] elementValues = new ElementValue[pairCount]; 127 for (int j = 0; j < elementNames.length; j++) { 128 elementNames[j] = namesIterator.next(); 129 final int t = T[T_index++]; 130 elementValues[j] = new ElementValue(t, getNextValue(t)); 131 } 132 return new Annotation(pairCount, type, elementNames, elementValues); 133 } 134 135 private Attribute getAttribute(final int numAnnotations, final CPUTF8[] types, final int[] pairCounts, final Iterator<CPUTF8> namesIterator) { 136 final Annotation[] annotations = new Annotation[numAnnotations]; 137 Arrays.setAll(annotations, i -> getAnnotation(types[i], pairCounts[i], namesIterator)); 138 return new RuntimeVisibleorInvisibleAnnotationsAttribute(type.equals("RVA") ? rvaUTF8 : riaUTF8, annotations); 139 } 140 141 public List<Attribute> getAttributes() { 142 // TODO: Optimize iterators! 143 if (attributes == null) { 144 attributes = new ArrayList<>(); 145 if (name_RU != null) { 146 final Iterator<CPUTF8> name_RU_Iterator = Arrays.asList(name_RU).iterator(); 147 if (!type.equals("AD")) { 148 T_index = 0; 149 } 150 caseI_KI_Index = 0; 151 caseD_KD_Index = 0; 152 caseF_KF_Index = 0; 153 caseJ_KJ_Index = 0; 154 casec_RS_Index = 0; 155 caseet_RS_Index = 0; 156 caseec_RU_Index = 0; 157 cases_RU_Index = 0; 158 casearray_N_Index = 0; 159 nesttype_RS_Index = 0; 160 nestpair_N_Index = 0; 161 nestname_RU_Iterator = Arrays.asList(nestname_RU).iterator(); 162 if (type.equals("RVA") || type.equals("RIA")) { 163 for (int i = 0; i < anno_N.length; i++) { 164 attributes.add(getAttribute(anno_N[i], type_RS[i], pair_N[i], name_RU_Iterator)); 165 } 166 } else if (type.equals("RVPA") || type.equals("RIPA")) { 167 anno_N_Index = 0; 168 pair_N_Index = 0; 169 for (final int element : param_NB) { 170 attributes.add(getParameterAttribute(element, name_RU_Iterator)); 171 } 172 } 173 } else if (type.equals("AD")) { 174 for (final int element : T) { 175 attributes.add(new AnnotationDefaultAttribute(new ElementValue(element, getNextValue(element)))); 176 } 177 } 178 } 179 return attributes; 180 } 181 182 private Object getNextValue(final int t) { 183 switch (t) { 184 case 'B': 185 case 'C': 186 case 'I': 187 case 'S': 188 case 'Z': 189 return caseI_KI[caseI_KI_Index++]; 190 case 'D': 191 return caseD_KD[caseD_KD_Index++]; 192 case 'F': 193 return caseF_KF[caseF_KF_Index++]; 194 case 'J': 195 return caseJ_KJ[caseJ_KJ_Index++]; 196 case 'c': 197 return casec_RS[casec_RS_Index++]; 198 case 'e': 199 // TODO: check this - it may not work if the first string already 200 // has a colon in it 201 final String enumString = caseet_RS[caseet_RS_Index++] + ":" + caseec_RU[caseec_RU_Index++]; 202 return cpBands.cpNameAndTypeValue(enumString); 203 case 's': 204 return cases_RU[cases_RU_Index++]; 205 case '[': 206 final int arraySize = casearray_N[casearray_N_Index++]; 207 final ElementValue[] nestedArray = new ElementValue[arraySize]; 208 for (int i = 0; i < arraySize; i++) { 209 final int nextT = T[T_index++]; 210 nestedArray[i] = new ElementValue(nextT, getNextValue(nextT)); 211 } 212 return nestedArray; 213 case '@': 214 final CPUTF8 type = nesttype_RS[nesttype_RS_Index++]; 215 final int numPairs = nestpair_N[nestpair_N_Index++]; 216 217 return getAnnotation(type, numPairs, nestname_RU_Iterator); 218 } 219 return null; 220 } 221 222 private Attribute getParameterAttribute(final int numParameters, final Iterator<CPUTF8> namesIterator) { 223 final ParameterAnnotation[] parameterAnnotations = new ParameterAnnotation[numParameters]; 224 for (int i = 0; i < numParameters; i++) { 225 final int numAnnotations = anno_N[anno_N_Index++]; 226 final int[] pairCounts = pair_N[pair_N_Index++]; 227 final Annotation[] annotations = new Annotation[numAnnotations]; 228 Arrays.setAll(annotations, j -> getAnnotation(type_RS[anno_N_Index - 1][j], pairCounts[j], namesIterator)); 229 parameterAnnotations[i] = new ParameterAnnotation(annotations); 230 } 231 return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type.equals("RVPA") ? rvpaUTF8 : ripaUTF8, parameterAnnotations); 232 } 233 234}