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}