View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.compress.harmony.pack200;
20  
21  import org.objectweb.asm.Attribute;
22  import org.objectweb.asm.ClassReader;
23  import org.objectweb.asm.Label;
24  
25  /**
26   * NewAttribute extends {@code Attribute} and manages unknown attributes encountered by ASM that have had a layout definition given to pack200 (for example via
27   * one of the -C, -M, -F or -D command line options)
28   */
29  public class NewAttribute extends Attribute {
30      /**
31       * ErrorAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had an error action specified to pack200 (for example via
32       * one of the -C, -M, -F or -D command line options such as -Cattribute-name=error)
33       */
34      public static class ErrorAttribute extends NewAttribute {
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       * PassAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a pass action specified to pack200 (for example via
47       * one of the -C, -M, -F or -D command line options such as -Cattribute-name=pass)
48       */
49      public static class PassAttribute extends NewAttribute {
50          public PassAttribute(final String type, final int context) {
51              super(type, "", context);
52          }
53  
54          @Override
55          protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
56              throw new Segment.PassException();
57          }
58      }
59  
60      /**
61       * StripAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a strip action specified to pack200 (for example via
62       * one of the -C, -M, -F or -D command line options such as -Cattribute-name=strip)
63       */
64      public static class StripAttribute extends NewAttribute {
65          public StripAttribute(final String type, final int context) {
66              super(type, "", context);
67          }
68  
69          @Override
70          protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
71              // TODO Not sure if this works, can we really strip an attribute if we don't know the layout?
72              return null;
73          }
74      }
75  
76      private boolean contextClass;
77      private boolean contextMethod;
78      private boolean contextField;
79      private boolean contextCode;
80      private final String layout;
81      private byte[] contents;
82      private int codeOff;
83      private Label[] labels;
84      private ClassReader classReader;
85      private char[] buf;
86  
87      public NewAttribute(final ClassReader classReader, final String type, final String layout, final byte[] contents, final char[] buf, final int codeOff,
88              final Label[] labels) {
89          super(type);
90          this.classReader = classReader;
91          this.contents = contents;
92          this.layout = layout;
93          this.codeOff = codeOff;
94          this.labels = labels;
95          this.buf = buf;
96      }
97  
98      public NewAttribute(final String type, final String layout, final int context) {
99          super(type);
100         this.layout = layout;
101         addContext(context);
102     }
103 
104     public void addContext(final int context) {
105         switch (context) {
106         case AttributeDefinitionBands.CONTEXT_CLASS:
107             contextClass = true;
108             break;
109         case AttributeDefinitionBands.CONTEXT_METHOD:
110             contextMethod = true;
111             break;
112         case AttributeDefinitionBands.CONTEXT_FIELD:
113             contextField = true;
114             break;
115         case AttributeDefinitionBands.CONTEXT_CODE:
116             contextCode = true;
117             break;
118         }
119     }
120 
121     public byte[] getBytes() {
122         return contents;
123     }
124 
125     public Label getLabel(final int index) {
126         return labels[index];
127     }
128 
129     public String getLayout() {
130         return layout;
131     }
132 
133     @Override
134     public boolean isCodeAttribute() {
135         return codeOff != -1;
136     }
137 
138     public boolean isContextClass() {
139         return contextClass;
140     }
141 
142     public boolean isContextCode() {
143         return contextCode;
144     }
145 
146     public boolean isContextField() {
147         return contextField;
148     }
149 
150     public boolean isContextMethod() {
151         return contextMethod;
152     }
153 
154     @Override
155     public boolean isUnknown() {
156         return false;
157     }
158 
159     public boolean isUnknown(final int context) {
160         switch (context) {
161         case AttributeDefinitionBands.CONTEXT_CLASS:
162             return !contextClass;
163         case AttributeDefinitionBands.CONTEXT_METHOD:
164             return !contextMethod;
165         case AttributeDefinitionBands.CONTEXT_FIELD:
166             return !contextField;
167         case AttributeDefinitionBands.CONTEXT_CODE:
168             return !contextCode;
169         }
170         return false;
171     }
172 
173     @Override
174     protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) {
175         final byte[] attributeContents = new byte[len];
176         System.arraycopy(cr.b, off, attributeContents, 0, len);
177         return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff, labels);
178     }
179 
180     public String readClass(final int index) {
181         return classReader.readClass(index, buf);
182     }
183 
184     public Object readConst(final int index) {
185         return classReader.readConst(index, buf);
186     }
187 
188     public String readUTF8(final int index) {
189         return classReader.readUTF8(index, buf);
190     }
191 }