View Javadoc
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.pack200;
18  
19  import org.objectweb.asm.Attribute;
20  import org.objectweb.asm.ClassReader;
21  import org.objectweb.asm.Label;
22  
23  /**
24   * NewAttribute extends {@code Attribute} and manages unknown attributes encountered by ASM that have had a layout definition given to pack200 (e.g. via one of
25   * the -C, -M, -F or -D command line options)
26   */
27  public class NewAttribute extends Attribute {
28  
29      /**
30       * ErrorAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had an error action specified to pack200 (e.g. via one of
31       * the -C, -M, -F or -D command line options such as -Cattribute-name=error)
32       */
33      public static class ErrorAttribute extends NewAttribute {
34  
35          public ErrorAttribute(final String type, final int context) {
36              super(type, "", context);
37          }
38  
39          @Override
40          protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
41              throw new Error("Attribute " + type + " was found");
42          }
43  
44      }
45  
46      /**
47       * PassAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a pass action specified to pack200 (e.g. via one of
48       * the -C, -M, -F or -D command line options such as -Cattribute-name=pass)
49       */
50      public static class PassAttribute extends NewAttribute {
51  
52          public PassAttribute(final String type, final int context) {
53              super(type, "", context);
54          }
55  
56          @Override
57          protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
58              throw new Segment.PassException();
59          }
60  
61      }
62  
63      /**
64       * StripAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a strip action specified to pack200 (e.g. via one of
65       * the -C, -M, -F or -D command line options such as -Cattribute-name=strip)
66       */
67      public static class StripAttribute extends NewAttribute {
68  
69          public StripAttribute(final String type, final int context) {
70              super(type, "", context);
71          }
72  
73          @Override
74          protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
75              // TODO Not sure if this works, can we really strip an attribute if we don't know the layout?
76              return null;
77          }
78      }
79  
80      private boolean contextClass;
81  
82      private boolean contextMethod;
83      private boolean contextField;
84      private boolean contextCode;
85      private final String layout;
86      private byte[] contents;
87      private int codeOff;
88  
89      private Label[] labels;
90  
91      private ClassReader classReader;
92  
93      private char[] buf;
94  
95      public NewAttribute(final ClassReader classReader, final String type, final String layout, final byte[] contents, final char[] buf, final int codeOff,
96              final Label[] labels) {
97          super(type);
98          this.classReader = classReader;
99          this.contents = contents;
100         this.layout = layout;
101         this.codeOff = codeOff;
102         this.labels = labels;
103         this.buf = buf;
104     }
105 
106     public NewAttribute(final String type, final String layout, final int context) {
107         super(type);
108         this.layout = layout;
109         addContext(context);
110     }
111 
112     public void addContext(final int context) {
113         switch (context) {
114         case AttributeDefinitionBands.CONTEXT_CLASS:
115             contextClass = true;
116             break;
117         case AttributeDefinitionBands.CONTEXT_METHOD:
118             contextMethod = true;
119             break;
120         case AttributeDefinitionBands.CONTEXT_FIELD:
121             contextField = true;
122             break;
123         case AttributeDefinitionBands.CONTEXT_CODE:
124             contextCode = true;
125             break;
126         }
127     }
128 
129     public byte[] getBytes() {
130         return contents;
131     }
132 
133     public Label getLabel(final int index) {
134         return labels[index];
135     }
136 
137     public String getLayout() {
138         return layout;
139     }
140 
141     @Override
142     public boolean isCodeAttribute() {
143         return codeOff != -1;
144     }
145 
146     public boolean isContextClass() {
147         return contextClass;
148     }
149 
150     public boolean isContextCode() {
151         return contextCode;
152     }
153 
154     public boolean isContextField() {
155         return contextField;
156     }
157 
158     public boolean isContextMethod() {
159         return contextMethod;
160     }
161 
162     @Override
163     public boolean isUnknown() {
164         return false;
165     }
166 
167     public boolean isUnknown(final int context) {
168         switch (context) {
169         case AttributeDefinitionBands.CONTEXT_CLASS:
170             return !contextClass;
171         case AttributeDefinitionBands.CONTEXT_METHOD:
172             return !contextMethod;
173         case AttributeDefinitionBands.CONTEXT_FIELD:
174             return !contextField;
175         case AttributeDefinitionBands.CONTEXT_CODE:
176             return !contextCode;
177         }
178         return false;
179     }
180 
181     @Override
182     protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
183         final byte[] attributeContents = new byte[len];
184         System.arraycopy(cr.b, off, attributeContents, 0, len);
185         return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff, labels);
186     }
187 
188     public String readClass(final int index) {
189         return classReader.readClass(index, buf);
190     }
191 
192     public Object readConst(final int index) {
193         return classReader.readConst(index, buf);
194     }
195 
196     public String readUTF8(final int index) {
197         return classReader.readUTF8(index, buf);
198     }
199 }