    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.Collection;
    021import java.util.HashMap;
    022import java.util.Iterator;
    023import java.util.List;
    024import java.util.Map;
    025
    026import org.apache.commons.compress.harmony.pack200.Pack200Exception;
    027
    028/**
    029 * Stores a mapping from attribute names to their corresponding layout types. Note that names of attribute layouts and
    030 * their formats are <em>not</em> internationalized, and should not be translated.
    031 */
    032public class AttributeLayoutMap {
    033
    034    // Create all the default AttributeLayouts here
    035    private static AttributeLayout[] getDefaultAttributeLayouts() throws Pack200Exception {
    036        return new AttributeLayout[] {
    037            new AttributeLayout(AttributeLayout.ACC_PUBLIC, AttributeLayout.CONTEXT_CLASS, "", 0),
    038            new AttributeLayout(AttributeLayout.ACC_PUBLIC, AttributeLayout.CONTEXT_FIELD, "", 0),
    039            new AttributeLayout(AttributeLayout.ACC_PUBLIC, AttributeLayout.CONTEXT_METHOD, "", 0),
    040            new AttributeLayout(AttributeLayout.ACC_PRIVATE, AttributeLayout.CONTEXT_CLASS, "", 1),
    041            new AttributeLayout(AttributeLayout.ACC_PRIVATE, AttributeLayout.CONTEXT_FIELD, "", 1),
    042            new AttributeLayout(AttributeLayout.ACC_PRIVATE, AttributeLayout.CONTEXT_METHOD, "", 1),
    043            new AttributeLayout(AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE, AttributeLayout.CONTEXT_CODE, "NH[PHH]",
    044                1),
    045
    046            new AttributeLayout(AttributeLayout.ACC_PROTECTED, AttributeLayout.CONTEXT_CLASS, "", 2),
    047            new AttributeLayout(AttributeLayout.ACC_PROTECTED, AttributeLayout.CONTEXT_FIELD, "", 2),
    048            new AttributeLayout(AttributeLayout.ACC_PROTECTED, AttributeLayout.CONTEXT_METHOD, "", 2),
    049            new AttributeLayout(AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE, AttributeLayout.CONTEXT_CODE,
    050                "NH[PHOHRUHRSHH]", 2),
    051
    052            new AttributeLayout(AttributeLayout.ACC_STATIC, AttributeLayout.CONTEXT_CLASS, "", 3),
    053            new AttributeLayout(AttributeLayout.ACC_STATIC, AttributeLayout.CONTEXT_FIELD, "", 3),
    054            new AttributeLayout(AttributeLayout.ACC_STATIC, AttributeLayout.CONTEXT_METHOD, "", 3),
    055            new AttributeLayout(AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE, AttributeLayout.CONTEXT_CODE,
    056                "NH[PHOHRUHRSHH]", 3),
    057
    058            new AttributeLayout(AttributeLayout.ACC_FINAL, AttributeLayout.CONTEXT_CLASS, "", 4),
    059            new AttributeLayout(AttributeLayout.ACC_FINAL, AttributeLayout.CONTEXT_FIELD, "", 4),
    060            new AttributeLayout(AttributeLayout.ACC_FINAL, AttributeLayout.CONTEXT_METHOD, "", 4),
    061            new AttributeLayout(AttributeLayout.ACC_SYNCHRONIZED, AttributeLayout.CONTEXT_CLASS, "", 5),
    062            new AttributeLayout(AttributeLayout.ACC_SYNCHRONIZED, AttributeLayout.CONTEXT_FIELD, "", 5),
    063            new AttributeLayout(AttributeLayout.ACC_SYNCHRONIZED, AttributeLayout.CONTEXT_METHOD, "", 5),
    064            new AttributeLayout(AttributeLayout.ACC_VOLATILE, AttributeLayout.CONTEXT_CLASS, "", 6),
    065            new AttributeLayout(AttributeLayout.ACC_VOLATILE, AttributeLayout.CONTEXT_FIELD, "", 6),
    066            new AttributeLayout(AttributeLayout.ACC_VOLATILE, AttributeLayout.CONTEXT_METHOD, "", 6),
    067            new AttributeLayout(AttributeLayout.ACC_TRANSIENT, AttributeLayout.CONTEXT_CLASS, "", 7),
    068            new AttributeLayout(AttributeLayout.ACC_TRANSIENT, AttributeLayout.CONTEXT_FIELD, "", 7),
    069            new AttributeLayout(AttributeLayout.ACC_TRANSIENT, AttributeLayout.CONTEXT_METHOD, "", 7),
    070            new AttributeLayout(AttributeLayout.ACC_NATIVE, AttributeLayout.CONTEXT_CLASS, "", 8),
    071            new AttributeLayout(AttributeLayout.ACC_NATIVE, AttributeLayout.CONTEXT_FIELD, "", 8),
    072            new AttributeLayout(AttributeLayout.ACC_NATIVE, AttributeLayout.CONTEXT_METHOD, "", 8),
    073            new AttributeLayout(AttributeLayout.ACC_INTERFACE, AttributeLayout.CONTEXT_CLASS, "", 9),
    074            new AttributeLayout(AttributeLayout.ACC_INTERFACE, AttributeLayout.CONTEXT_FIELD, "", 9),
    075            new AttributeLayout(AttributeLayout.ACC_INTERFACE, AttributeLayout.CONTEXT_METHOD, "", 9),
    076            new AttributeLayout(AttributeLayout.ACC_ABSTRACT, AttributeLayout.CONTEXT_CLASS, "", 10),
    077            new AttributeLayout(AttributeLayout.ACC_ABSTRACT, AttributeLayout.CONTEXT_FIELD, "", 10),
    078            new AttributeLayout(AttributeLayout.ACC_ABSTRACT, AttributeLayout.CONTEXT_METHOD, "", 10),
    079            new AttributeLayout(AttributeLayout.ACC_STRICT, AttributeLayout.CONTEXT_CLASS, "", 11),
    080            new AttributeLayout(AttributeLayout.ACC_STRICT, AttributeLayout.CONTEXT_FIELD, "", 11),
    081            new AttributeLayout(AttributeLayout.ACC_STRICT, AttributeLayout.CONTEXT_METHOD, "", 11),
    082            new AttributeLayout(AttributeLayout.ACC_SYNTHETIC, AttributeLayout.CONTEXT_CLASS, "", 12),
    083            new AttributeLayout(AttributeLayout.ACC_SYNTHETIC, AttributeLayout.CONTEXT_FIELD, "", 12),
    084            new AttributeLayout(AttributeLayout.ACC_SYNTHETIC, AttributeLayout.CONTEXT_METHOD, "", 12),
    085            new AttributeLayout(AttributeLayout.ACC_ANNOTATION, AttributeLayout.CONTEXT_CLASS, "", 13),
    086            new AttributeLayout(AttributeLayout.ACC_ANNOTATION, AttributeLayout.CONTEXT_FIELD, "", 13),
    087            new AttributeLayout(AttributeLayout.ACC_ANNOTATION, AttributeLayout.CONTEXT_METHOD, "", 13),
    088            new AttributeLayout(AttributeLayout.ACC_ENUM, AttributeLayout.CONTEXT_CLASS, "", 14),
    089            new AttributeLayout(AttributeLayout.ACC_ENUM, AttributeLayout.CONTEXT_FIELD, "", 14),
    090            new AttributeLayout(AttributeLayout.ACC_ENUM, AttributeLayout.CONTEXT_METHOD, "", 14),
    091            new AttributeLayout(AttributeLayout.ATTRIBUTE_SOURCE_FILE, AttributeLayout.CONTEXT_CLASS, "RUNH", 17),
    092            new AttributeLayout(AttributeLayout.ATTRIBUTE_CONSTANT_VALUE, AttributeLayout.CONTEXT_FIELD, "KQH", 17),
    093            new AttributeLayout(AttributeLayout.ATTRIBUTE_CODE, AttributeLayout.CONTEXT_METHOD, "", 17),
    094            new AttributeLayout(AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD, AttributeLayout.CONTEXT_CLASS, "RCHRDNH",
    095                18),
    096            new AttributeLayout(AttributeLayout.ATTRIBUTE_EXCEPTIONS, AttributeLayout.CONTEXT_METHOD, "NH[RCH]", 18),
    097            new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_CLASS, "RSH", 19),
    098            new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_FIELD, "RSH", 19),
    099            new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_METHOD, "RSH", 19),
    100            new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED, AttributeLayout.CONTEXT_CLASS, "", 20),
    101            new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED, AttributeLayout.CONTEXT_FIELD, "", 20),
    102            new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED, AttributeLayout.CONTEXT_METHOD, "", 20),
    103            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_CLASS,
    104                "*", 21),
    105            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_FIELD,
    106                "*", 21),
    107            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_METHOD,
    108                "*", 21),
    109            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_CLASS,
    110                "*", 22),
    111            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_FIELD,
    112                "*", 22),
    113            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_METHOD,
    114                "*", 22),
    115            new AttributeLayout(AttributeLayout.ATTRIBUTE_INNER_CLASSES, AttributeLayout.CONTEXT_CLASS, "", 23),
    116            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
    117                AttributeLayout.CONTEXT_METHOD, "*", 23),
    118            new AttributeLayout(AttributeLayout.ATTRIBUTE_CLASS_FILE_VERSION, AttributeLayout.CONTEXT_CLASS, "", 24),
    119            new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
    120                AttributeLayout.CONTEXT_METHOD, "*", 24),
    121            new AttributeLayout(AttributeLayout.ATTRIBUTE_ANNOTATION_DEFAULT, AttributeLayout.CONTEXT_METHOD, "*", 25)};
    122    }
    123
    124    private final Map classLayouts = new HashMap();
    125    private final Map fieldLayouts = new HashMap();
    126    private final Map methodLayouts = new HashMap();
    127    private final Map codeLayouts = new HashMap();
    128
    129    // The order of the maps in this array should not be changed as their
    130    // indices correspond to
    131    // the value of their context constants (AttributeLayout.CONTEXT_CLASS etc.)
    132    private final Map[] layouts = {classLayouts, fieldLayouts, methodLayouts, codeLayouts};
    133
    134    private final Map layoutsToBands = new HashMap();
    135
    136    public AttributeLayoutMap() throws Pack200Exception {
    137        final AttributeLayout[] defaultAttributeLayouts = getDefaultAttributeLayouts();
    138        for (int i = 0; i < defaultAttributeLayouts.length; i++) {
    139            add(defaultAttributeLayouts[i]);
    140        }
    141    }
    142
    143    public void add(final AttributeLayout layout) {
    144        layouts[layout.getContext()].put(Integer.valueOf(layout.getIndex()), layout);
    145    }
    146
    147    public void add(final AttributeLayout layout, final NewAttributeBands newBands) {
    148        add(layout);
    149        layoutsToBands.put(layout, newBands);
    150    }
    151
    152    public AttributeLayout getAttributeLayout(final String name, final int context) throws Pack200Exception {
    153        final Map map = layouts[context];
    154        for (final Iterator iter = map.values().iterator(); iter.hasNext();) {
    155            final AttributeLayout layout = (AttributeLayout) iter.next();
    156            if (layout.getName().equals(name)) {
    157                return layout;
    158            }
    159        }
    160        return null;
    161    }
    162
    163    public AttributeLayout getAttributeLayout(final int index, final int context) throws Pack200Exception {
    164        final Map map = layouts[context];
    165        return (AttributeLayout) map.get(Integer.valueOf(index));
    166    }
    167
    168    /**
    169     * The map should not contain the same layout and name combination more than once for each context.
    170     *
    171     * @throws Pack200Exception Thrown when the name layout/name combination exists twice for a context.
    172     */
    173    public void checkMap() throws Pack200Exception {
    174        for (int i = 0; i < layouts.length; i++) {
    175            final Map map = layouts[i];
    176            Collection c = map.values();
    177            if (!(c instanceof List)) {
    178                c = new ArrayList(c);
    179            }
    180            final List l = (List) c;
    181            for (int j = 0; j < l.size(); j++) {
    182                final AttributeLayout layout1 = (AttributeLayout) l.get(j);
    183                for (int j2 = j + 1; j2 < l.size(); j2++) {
    184                    final AttributeLayout layout2 = (AttributeLayout) l.get(j2);
    185                    if (layout1.getName().equals(layout2.getName())
    186                        && layout1.getLayout().equals(layout2.getLayout())) {
    187                        throw new Pack200Exception(
    188                            "Same layout/name combination: " + layout1.getLayout() + "/" + layout1.getName()
    189                                + " exists twice for context: " + AttributeLayout.contextNames[layout1.getContext()]);
    190                    }
    191                }
    192            }
    193        }
    194    }
    195
    196    public NewAttributeBands getAttributeBands(final AttributeLayout layout) {
    197        return (NewAttributeBands) layoutsToBands.get(layout);
    198    }
    199
    200}