    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.pack200;
    018
    019import org.objectweb.asm.Attribute;
    020import org.objectweb.asm.ClassReader;
    021import org.objectweb.asm.Label;
    022
    023/**
    024 * NewAttribute extends <code>Attribute</code> and manages unknown attributes encountered by ASM that have had a layout
    025 * definition given to pack200 (e.g. via one of the -C, -M, -F or -D command line options)
    026 */
    027public class NewAttribute extends Attribute {
    028
    029    private boolean contextClass = false;
    030    private boolean contextMethod = false;
    031    private boolean contextField = false;
    032    private boolean contextCode = false;
    033
    034    private final String layout;
    035    private byte[] contents;
    036    private int codeOff;
    037    private Label[] labels;
    038    private ClassReader classReader;
    039    private char[] buf;
    040
    041    public NewAttribute(final String type, final String layout, final int context) {
    042        super(type);
    043        this.layout = layout;
    044        addContext(context);
    045    }
    046
    047    public NewAttribute(final ClassReader classReader, final String type, final String layout, final byte[] contents,
    048        final char[] buf, final int codeOff, final Label[] labels) {
    049        super(type);
    050        this.classReader = classReader;
    051        this.contents = contents;
    052        this.layout = layout;
    053        this.codeOff = codeOff;
    054        this.labels = labels;
    055        this.buf = buf;
    056    }
    057
    058    public void addContext(final int context) {
    059        switch (context) {
    060        case AttributeDefinitionBands.CONTEXT_CLASS:
    061            contextClass = true;
    062            break;
    063        case AttributeDefinitionBands.CONTEXT_METHOD:
    064            contextMethod = true;
    065            break;
    066        case AttributeDefinitionBands.CONTEXT_FIELD:
    067            contextField = true;
    068            break;
    069        case AttributeDefinitionBands.CONTEXT_CODE:
    070            contextCode = true;
    071            break;
    072        }
    073    }
    074
    075    public boolean isContextClass() {
    076        return contextClass;
    077    }
    078
    079    public boolean isContextMethod() {
    080        return contextMethod;
    081    }
    082
    083    public boolean isContextField() {
    084        return contextField;
    085    }
    086
    087    public boolean isContextCode() {
    088        return contextCode;
    089    }
    090
    091    public String getLayout() {
    092        return layout;
    093    }
    094
    095    @Override
    096    public boolean isUnknown() {
    097        return false;
    098    }
    099
    100    @Override
    101    public boolean isCodeAttribute() {
    102        return codeOff != -1;
    103    }
    104
    105    @Override
    106    protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff,
    107        final Label[] labels) {
    108        final byte[] attributeContents = new byte[len];
    109        System.arraycopy(cr.b, off, attributeContents, 0, len);
    110        return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff, labels);
    111    }
    112
    113    public boolean isUnknown(final int context) {
    114        switch (context) {
    115        case AttributeDefinitionBands.CONTEXT_CLASS:
    116            return !contextClass;
    117        case AttributeDefinitionBands.CONTEXT_METHOD:
    118            return !contextMethod;
    119        case AttributeDefinitionBands.CONTEXT_FIELD:
    120            return !contextField;
    121        case AttributeDefinitionBands.CONTEXT_CODE:
    122            return !contextCode;
    123        }
    124        return false;
    125    }
    126
    127    public String readUTF8(final int index) {
    128        return classReader.readUTF8(index, buf);
    129    }
    130
    131    public String readClass(final int index) {
    132        return classReader.readClass(index, buf);
    133    }
    134
    135    public Object readConst(final int index) {
    136        return classReader.readConst(index, buf);
    137    }
    138
    139    public byte[] getBytes() {
    140        return contents;
    141    }
    142
    143    public Label getLabel(final int index) {
    144        return labels[index];
    145    }
    146
    147    /**
    148     * ErrorAttribute extends <code>NewAttribute</code> and manages attributes encountered by ASM that have had an error
    149     * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as
    150     * -Cattribute-name=error)
    151     */
    152    public static class ErrorAttribute extends NewAttribute {
    153
    154        public ErrorAttribute(final String type, final int context) {
    155            super(type, "", context);
    156        }
    157
    158        @Override
    159        protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf,
    160            final int codeOff, final Label[] labels) {
    161            throw new Error("Attribute " + type + " was found");
    162        }
    163
    164    }
    165
    166    /**
    167     * StripAttribute extends <code>NewAttribute</code> and manages attributes encountered by ASM that have had an strip
    168     * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as
    169     * -Cattribute-name=strip)
    170     */
    171    public static class StripAttribute extends NewAttribute {
    172
    173        public StripAttribute(final String type, final int context) {
    174            super(type, "", context);
    175        }
    176
    177        @Override
    178        protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf,
    179            final int codeOff, final Label[] labels) {
    180            // TODO Not sure if this works, can we really strip an attribute if we don't know the layout?
    181            return null;
    182        }
    183    }
    184
    185    /**
    186     * PassAttribute extends <code>NewAttribute</code> and manages attributes encountered by ASM that have had an pass
    187     * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as
    188     * -Cattribute-name=pass)
    189     */
    190    public static class PassAttribute extends NewAttribute {
    191
    192        public PassAttribute(final String type, final int context) {
    193            super(type, "", context);
    194        }
    195
    196        @Override
    197        protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf,
    198            final int codeOff, final Label[] labels) {
    199            throw new Segment.PassException();
    200        }
    201
    202    }
    203}