MetadataBandGroup.java

  1. /*
  2.  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3.  *  contributor license agreements.  See the NOTICE file distributed with
  4.  *  this work for additional information regarding copyright ownership.
  5.  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6.  *  (the "License"); you may not use this file except in compliance with
  7.  *  the License.  You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.commons.compress.harmony.unpack200;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Iterator;
  21. import java.util.List;

  22. import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationDefaultAttribute;
  23. import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation;
  24. import org.apache.commons.compress.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue;
  25. import org.apache.commons.compress.harmony.unpack200.bytecode.Attribute;
  26. import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble;
  27. import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat;
  28. import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger;
  29. import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong;
  30. import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
  31. import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute;
  32. import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute;
  33. import org.apache.commons.compress.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation;

  34. /**
  35.  * A group of metadata bands, such as class_RVA_bands, method_AD_bands etc.
  36.  */
  37. public class MetadataBandGroup {

  38.     private static CPUTF8 rvaUTF8;
  39.     private static CPUTF8 riaUTF8;

  40.     private static CPUTF8 rvpaUTF8;
  41.     private static CPUTF8 ripaUTF8;

  42.     public static void setRiaAttributeName(final CPUTF8 cpUTF8Value) {
  43.         riaUTF8 = cpUTF8Value;
  44.     }

  45.     public static void setRipaAttributeName(final CPUTF8 cpUTF8Value) {
  46.         ripaUTF8 = cpUTF8Value;
  47.     }

  48.     public static void setRvaAttributeName(final CPUTF8 cpUTF8Value) {
  49.         rvaUTF8 = cpUTF8Value;
  50.     }

  51.     public static void setRvpaAttributeName(final CPUTF8 cpUTF8Value) {
  52.         rvpaUTF8 = cpUTF8Value;
  53.     }

  54.     private final String type;

  55.     private final CpBands cpBands;

  56.     private List<Attribute> attributes;

  57.     public int[] param_NB;

  58.     public int[] anno_N;
  59.     public CPUTF8[][] type_RS;
  60.     public int[][] pair_N;
  61.     public CPUTF8[] name_RU;
  62.     public int[] T;
  63.     public CPInteger[] caseI_KI;
  64.     public CPDouble[] caseD_KD;
  65.     public CPFloat[] caseF_KF;
  66.     public CPLong[] caseJ_KJ;
  67.     public CPUTF8[] casec_RS;
  68.     public String[] caseet_RS;
  69.     public String[] caseec_RU;
  70.     public CPUTF8[] cases_RU;
  71.     public int[] casearray_N;
  72.     public CPUTF8[] nesttype_RS;
  73.     public int[] nestpair_N;
  74.     public CPUTF8[] nestname_RU;
  75.     private int caseI_KI_Index;

  76.     private int caseD_KD_Index;

  77.     private int caseF_KF_Index;

  78.     private int caseJ_KJ_Index;

  79.     private int casec_RS_Index;

  80.     private int caseet_RS_Index;

  81.     private int caseec_RU_Index;

  82.     private int cases_RU_Index;

  83.     private int casearray_N_Index;

  84.     private int T_index;

  85.     private int nesttype_RS_Index;

  86.     private int nestpair_N_Index;

  87.     private Iterator<CPUTF8> nestname_RU_Iterator;

  88.     private int anno_N_Index;

  89.     private int pair_N_Index;

  90.     public MetadataBandGroup(final String type, final CpBands cpBands) {
  91.         this.type = type;
  92.         this.cpBands = cpBands;
  93.     }

  94.     private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator<CPUTF8> namesIterator) {
  95.         final CPUTF8[] elementNames = new CPUTF8[pairCount];
  96.         final ElementValue[] elementValues = new ElementValue[pairCount];
  97.         for (int j = 0; j < elementNames.length; j++) {
  98.             elementNames[j] = namesIterator.next();
  99.             final int t = T[T_index++];
  100.             elementValues[j] = new ElementValue(t, getNextValue(t));
  101.         }
  102.         return new Annotation(pairCount, type, elementNames, elementValues);
  103.     }

  104.     private Attribute getAttribute(final int numAnnotations, final CPUTF8[] types, final int[] pairCounts, final Iterator<CPUTF8> namesIterator) {
  105.         final Annotation[] annotations = new Annotation[numAnnotations];
  106.         Arrays.setAll(annotations, i -> getAnnotation(types[i], pairCounts[i], namesIterator));
  107.         return new RuntimeVisibleorInvisibleAnnotationsAttribute(type.equals("RVA") ? rvaUTF8 : riaUTF8, annotations);
  108.     }

  109.     public List<Attribute> getAttributes() {
  110.         // TODO: Optimize iterators!
  111.         if (attributes == null) {
  112.             attributes = new ArrayList<>();
  113.             if (name_RU != null) {
  114.                 final Iterator<CPUTF8> name_RU_Iterator = Arrays.asList(name_RU).iterator();
  115.                 if (!type.equals("AD")) {
  116.                     T_index = 0;
  117.                 }
  118.                 caseI_KI_Index = 0;
  119.                 caseD_KD_Index = 0;
  120.                 caseF_KF_Index = 0;
  121.                 caseJ_KJ_Index = 0;
  122.                 casec_RS_Index = 0;
  123.                 caseet_RS_Index = 0;
  124.                 caseec_RU_Index = 0;
  125.                 cases_RU_Index = 0;
  126.                 casearray_N_Index = 0;
  127.                 nesttype_RS_Index = 0;
  128.                 nestpair_N_Index = 0;
  129.                 nestname_RU_Iterator = Arrays.asList(nestname_RU).iterator();
  130.                 if (type.equals("RVA") || type.equals("RIA")) {
  131.                     for (int i = 0; i < anno_N.length; i++) {
  132.                         attributes.add(getAttribute(anno_N[i], type_RS[i], pair_N[i], name_RU_Iterator));
  133.                     }
  134.                 } else if (type.equals("RVPA") || type.equals("RIPA")) {
  135.                     anno_N_Index = 0;
  136.                     pair_N_Index = 0;
  137.                     for (final int element : param_NB) {
  138.                         attributes.add(getParameterAttribute(element, name_RU_Iterator));
  139.                     }
  140.                 }
  141.             } else if (type.equals("AD")) {
  142.                 for (final int element : T) {
  143.                     attributes.add(new AnnotationDefaultAttribute(new ElementValue(element, getNextValue(element))));
  144.                 }
  145.             }
  146.         }
  147.         return attributes;
  148.     }

  149.     private Object getNextValue(final int t) {
  150.         switch (t) {
  151.         case 'B':
  152.         case 'C':
  153.         case 'I':
  154.         case 'S':
  155.         case 'Z':
  156.             return caseI_KI[caseI_KI_Index++];
  157.         case 'D':
  158.             return caseD_KD[caseD_KD_Index++];
  159.         case 'F':
  160.             return caseF_KF[caseF_KF_Index++];
  161.         case 'J':
  162.             return caseJ_KJ[caseJ_KJ_Index++];
  163.         case 'c':
  164.             return casec_RS[casec_RS_Index++];
  165.         case 'e':
  166.             // TODO: check this - it may not work if the first string already
  167.             // has a colon in it
  168.             final String enumString = caseet_RS[caseet_RS_Index++] + ":" + caseec_RU[caseec_RU_Index++];
  169.             return cpBands.cpNameAndTypeValue(enumString);
  170.         case 's':
  171.             return cases_RU[cases_RU_Index++];
  172.         case '[':
  173.             final int arraySize = casearray_N[casearray_N_Index++];
  174.             final ElementValue[] nestedArray = new ElementValue[arraySize];
  175.             for (int i = 0; i < arraySize; i++) {
  176.                 final int nextT = T[T_index++];
  177.                 nestedArray[i] = new ElementValue(nextT, getNextValue(nextT));
  178.             }
  179.             return nestedArray;
  180.         case '@':
  181.             final CPUTF8 type = nesttype_RS[nesttype_RS_Index++];
  182.             final int numPairs = nestpair_N[nestpair_N_Index++];

  183.             return getAnnotation(type, numPairs, nestname_RU_Iterator);
  184.         }
  185.         return null;
  186.     }

  187.     private Attribute getParameterAttribute(final int numParameters, final Iterator<CPUTF8> namesIterator) {
  188.         final ParameterAnnotation[] parameterAnnotations = new ParameterAnnotation[numParameters];
  189.         for (int i = 0; i < numParameters; i++) {
  190.             final int numAnnotations = anno_N[anno_N_Index++];
  191.             final int[] pairCounts = pair_N[pair_N_Index++];
  192.             final Annotation[] annotations = new Annotation[numAnnotations];
  193.             Arrays.setAll(annotations, j -> getAnnotation(type_RS[anno_N_Index - 1][j], pairCounts[j], namesIterator));
  194.             parameterAnnotations[i] = new ParameterAnnotation(annotations);
  195.         }
  196.         return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type.equals("RVPA") ? rvpaUTF8 : ripaUTF8, parameterAnnotations);
  197.     }

  198. }