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 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 nestname_RU_Iterator; 117 118 private int anno_N_Index; 119 120 private int pair_N_Index; 121 122 public List getAttributes() { 123 // TODO: Optimize iterators! 124 if (attributes == null) { 125 attributes = new ArrayList(); 126 if (name_RU != null) { 127 final Iterator 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 i = 0; i < param_NB.length; i++) { 151 attributes.add(getParameterAttribute(param_NB[i], name_RU_Iterator)); 152 } 153 } 154 } else if (type.equals("AD")) { 155 for (int i = 0; i < T.length; i++) { 156 attributes.add(new AnnotationDefaultAttribute(new ElementValue(T[i], getNextValue(T[i])))); 157 } 158 } 159 } 160 return attributes; 161 } 162 163 private Attribute getAttribute(final int numAnnotations, final CPUTF8[] types, final int[] pairCounts, 164 final Iterator namesIterator) { 165 final Annotation[] annotations = new Annotation[numAnnotations]; 166 for (int i = 0; i < numAnnotations; i++) { 167 annotations[i] = getAnnotation(types[i], pairCounts[i], namesIterator); 168 } 169 return new RuntimeVisibleorInvisibleAnnotationsAttribute(type.equals("RVA") ? rvaUTF8 : riaUTF8, annotations); 170 } 171 172 private Attribute getParameterAttribute(final int numParameters, final Iterator namesIterator) { 173 final ParameterAnnotation[] parameter_annotations = new ParameterAnnotation[numParameters]; 174 for (int i = 0; i < numParameters; i++) { 175 final int numAnnotations = anno_N[anno_N_Index++]; 176 final int[] pairCounts = pair_N[pair_N_Index++]; 177 final Annotation[] annotations = new Annotation[numAnnotations]; 178 for (int j = 0; j < annotations.length; j++) { 179 annotations[j] = getAnnotation(type_RS[anno_N_Index - 1][j], pairCounts[j], namesIterator); 180 } 181 parameter_annotations[i] = new ParameterAnnotation(annotations); 182 } 183 return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type.equals("RVPA") ? rvpaUTF8 : ripaUTF8, 184 parameter_annotations); 185 } 186 187 private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator namesIterator) { 188 final CPUTF8[] elementNames = new CPUTF8[pairCount]; 189 final ElementValue[] elementValues = new ElementValue[pairCount]; 190 for (int j = 0; j < elementNames.length; j++) { 191 elementNames[j] = (CPUTF8) namesIterator.next(); 192 final int t = T[T_index++]; 193 elementValues[j] = new ElementValue(t, getNextValue(t)); 194 } 195 return new Annotation(pairCount, type, elementNames, elementValues); 196 } 197 198 private Object getNextValue(final int t) { 199 switch (t) { 200 case 'B': 201 case 'C': 202 case 'I': 203 case 'S': 204 case 'Z': 205 return caseI_KI[caseI_KI_Index++]; 206 case 'D': 207 return caseD_KD[caseD_KD_Index++]; 208 case 'F': 209 return caseF_KF[caseF_KF_Index++]; 210 case 'J': 211 return caseJ_KJ[caseJ_KJ_Index++]; 212 case 'c': 213 return casec_RS[casec_RS_Index++]; 214 case 'e': 215 // TODO: check this - it may not work if the first string already 216 // has a colon in it 217 final String enumString = caseet_RS[caseet_RS_Index++] + ":" + caseec_RU[caseec_RU_Index++]; 218 return cpBands.cpNameAndTypeValue(enumString); 219 case 's': 220 return cases_RU[cases_RU_Index++]; 221 case '[': 222 final int arraySize = casearray_N[casearray_N_Index++]; 223 final ElementValue[] nestedArray = new ElementValue[arraySize]; 224 for (int i = 0; i < arraySize; i++) { 225 final int nextT = T[T_index++]; 226 nestedArray[i] = new ElementValue(nextT, getNextValue(nextT)); 227 } 228 return nestedArray; 229 case '@': 230 final CPUTF8 type = nesttype_RS[nesttype_RS_Index++]; 231 final int numPairs = nestpair_N[nestpair_N_Index++]; 232 233 return getAnnotation(type, numPairs, nestname_RU_Iterator); 234 } 235 return null; 236 } 237 238}