AttributeDefinitionBands.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.compress.harmony.pack200;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.objectweb.asm.Attribute;
- /**
- * Attribute Definition bands define how any unknown attributes should be read by the decompressor.
- */
- public class AttributeDefinitionBands extends BandSet {
- public static class AttributeDefinition {
- public int index;
- public int contextType;
- public CPUTF8 name;
- public CPUTF8 layout;
- public AttributeDefinition(final int index, final int contextType, final CPUTF8 name, final CPUTF8 layout) {
- this.index = index;
- this.contextType = contextType;
- this.name = name;
- this.layout = layout;
- }
- }
- /**
- * {@value}
- */
- public static final int CONTEXT_CLASS = 0;
- /**
- * {@value}
- */
- public static final int CONTEXT_CODE = 3;
- /**
- * {@value}
- */
- public static final int CONTEXT_FIELD = 1;
- /**
- * {@value}
- */
- public static final int CONTEXT_METHOD = 2;
- private final List<AttributeDefinition> classAttributeLayouts = new ArrayList<>();
- private final List<AttributeDefinition> methodAttributeLayouts = new ArrayList<>();
- private final List<AttributeDefinition> fieldAttributeLayouts = new ArrayList<>();
- private final List<AttributeDefinition> codeAttributeLayouts = new ArrayList<>();
- private final List<AttributeDefinition> attributeDefinitions = new ArrayList<>();
- private final CpBands cpBands;
- private final Segment segment;
- public AttributeDefinitionBands(final Segment segment, final int effort, final Attribute[] attributePrototypes) {
- super(effort, segment.getSegmentHeader());
- this.cpBands = segment.getCpBands();
- this.segment = segment;
- final Map<String, String> classLayouts = new HashMap<>();
- final Map<String, String> methodLayouts = new HashMap<>();
- final Map<String, String> fieldLayouts = new HashMap<>();
- final Map<String, String> codeLayouts = new HashMap<>();
- for (final Attribute attributePrototype : attributePrototypes) {
- final NewAttribute newAttribute = (NewAttribute) attributePrototype;
- if (!(newAttribute instanceof NewAttribute.ErrorAttribute) && !(newAttribute instanceof NewAttribute.PassAttribute)
- && !(newAttribute instanceof NewAttribute.StripAttribute)) {
- if (newAttribute.isContextClass()) {
- classLayouts.put(newAttribute.type, newAttribute.getLayout());
- }
- if (newAttribute.isContextMethod()) {
- methodLayouts.put(newAttribute.type, newAttribute.getLayout());
- }
- if (newAttribute.isContextField()) {
- fieldLayouts.put(newAttribute.type, newAttribute.getLayout());
- }
- if (newAttribute.isContextCode()) {
- codeLayouts.put(newAttribute.type, newAttribute.getLayout());
- }
- }
- }
- if (classLayouts.size() > 7) {
- segmentHeader.setHave_class_flags_hi(true);
- }
- if (methodLayouts.size() > 6) {
- segmentHeader.setHave_method_flags_hi(true);
- }
- if (fieldLayouts.size() > 10) {
- segmentHeader.setHave_field_flags_hi(true);
- }
- if (codeLayouts.size() > 15) {
- segmentHeader.setHave_code_flags_hi(true);
- }
- int[] availableClassIndices = { 25, 26, 27, 28, 29, 30, 31 };
- if (classLayouts.size() > 7) {
- availableClassIndices = addHighIndices(availableClassIndices);
- }
- addAttributeDefinitions(classLayouts, availableClassIndices, CONTEXT_CLASS);
- int[] availableMethodIndices = { 26, 27, 28, 29, 30, 31 };
- if (methodAttributeLayouts.size() > 6) {
- availableMethodIndices = addHighIndices(availableMethodIndices);
- }
- addAttributeDefinitions(methodLayouts, availableMethodIndices, CONTEXT_METHOD);
- int[] availableFieldIndices = { 18, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
- if (fieldAttributeLayouts.size() > 10) {
- availableFieldIndices = addHighIndices(availableFieldIndices);
- }
- addAttributeDefinitions(fieldLayouts, availableFieldIndices, CONTEXT_FIELD);
- int[] availableCodeIndices = { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
- if (codeAttributeLayouts.size() > 15) {
- availableCodeIndices = addHighIndices(availableCodeIndices);
- }
- addAttributeDefinitions(codeLayouts, availableCodeIndices, CONTEXT_CODE);
- }
- private void addAttributeDefinitions(final Map<String, String> layoutMap, final int[] availableIndices, final int contextType) {
- final int i = 0;
- layoutMap.forEach((name, layout) -> {
- final int index = availableIndices[i];
- final AttributeDefinition definition = new AttributeDefinition(index, contextType, cpBands.getCPUtf8(name), cpBands.getCPUtf8(layout));
- attributeDefinitions.add(definition);
- switch (contextType) {
- case CONTEXT_CLASS:
- classAttributeLayouts.add(definition);
- break;
- case CONTEXT_METHOD:
- methodAttributeLayouts.add(definition);
- break;
- case CONTEXT_FIELD:
- fieldAttributeLayouts.add(definition);
- break;
- case CONTEXT_CODE:
- codeAttributeLayouts.add(definition);
- }
- });
- }
- private int[] addHighIndices(final int[] availableIndices) {
- final int[] temp = Arrays.copyOf(availableIndices, availableIndices.length + 32);
- int j = 32;
- for (int i = availableIndices.length; i < temp.length; i++) {
- temp[i] = j;
- j++;
- }
- return temp;
- }
- private void addSyntheticDefinitions() {
- final boolean anySytheticClasses = segment.getClassBands().isAnySyntheticClasses();
- final boolean anySyntheticMethods = segment.getClassBands().isAnySyntheticMethods();
- final boolean anySyntheticFields = segment.getClassBands().isAnySyntheticFields();
- if (anySytheticClasses || anySyntheticMethods || anySyntheticFields) {
- final CPUTF8 syntheticUTF = cpBands.getCPUtf8("Synthetic");
- final CPUTF8 emptyUTF = cpBands.getCPUtf8("");
- if (anySytheticClasses) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_CLASS, syntheticUTF, emptyUTF));
- }
- if (anySyntheticMethods) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_METHOD, syntheticUTF, emptyUTF));
- }
- if (anySyntheticFields) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_FIELD, syntheticUTF, emptyUTF));
- }
- }
- }
- /**
- * All input classes for the segment have now been read in, so this method is called so that this class can calculate/complete anything it could not do
- * while classes were being read.
- */
- public void finaliseBands() {
- addSyntheticDefinitions();
- segmentHeader.setAttribute_definition_count(attributeDefinitions.size());
- }
- public List<AttributeDefinition> getClassAttributeLayouts() {
- return classAttributeLayouts;
- }
- public List<AttributeDefinition> getCodeAttributeLayouts() {
- return codeAttributeLayouts;
- }
- public List<AttributeDefinition> getFieldAttributeLayouts() {
- return fieldAttributeLayouts;
- }
- public List<AttributeDefinition> getMethodAttributeLayouts() {
- return methodAttributeLayouts;
- }
- @Override
- public void pack(final OutputStream out) throws IOException, Pack200Exception {
- PackingUtils.log("Writing attribute definition bands...");
- final int[] attributeDefinitionHeader = new int[attributeDefinitions.size()];
- final int[] attributeDefinitionName = new int[attributeDefinitions.size()];
- final int[] attributeDefinitionLayout = new int[attributeDefinitions.size()];
- for (int i = 0; i < attributeDefinitionLayout.length; i++) {
- final AttributeDefinition def = attributeDefinitions.get(i);
- attributeDefinitionHeader[i] = def.contextType | def.index + 1 << 2;
- attributeDefinitionName[i] = def.name.getIndex();
- attributeDefinitionLayout[i] = def.layout.getIndex();
- }
- byte[] encodedBand = encodeBandInt("attributeDefinitionHeader", attributeDefinitionHeader, Codec.BYTE1);
- out.write(encodedBand);
- PackingUtils.log("Wrote " + encodedBand.length + " bytes from attributeDefinitionHeader[" + attributeDefinitionHeader.length + "]");
- encodedBand = encodeBandInt("attributeDefinitionName", attributeDefinitionName, Codec.UNSIGNED5);
- out.write(encodedBand);
- PackingUtils.log("Wrote " + encodedBand.length + " bytes from attributeDefinitionName[" + attributeDefinitionName.length + "]");
- encodedBand = encodeBandInt("attributeDefinitionLayout", attributeDefinitionLayout, Codec.UNSIGNED5);
- out.write(encodedBand);
- PackingUtils.log("Wrote " + encodedBand.length + " bytes from attributeDefinitionLayout[" + attributeDefinitionLayout.length + "]");
- }
- }