    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}