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