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.unpack200.bytecode;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  import java.util.Objects;
24  
25  /**
26   * Abstract superclass for class file attributes
27   */
28  public abstract class Attribute extends ClassFileEntry {
29  
30      /**
31       * The attribute name.
32       */
33      protected final CPUTF8 attributeName;
34  
35      private int attributeNameIndex;
36  
37      /**
38       * Constructs a new instance for an attribute name.
39       *
40       * @param attributeName an attribute name.
41       */
42      public Attribute(final CPUTF8 attributeName) {
43          this.attributeName = attributeName;
44      }
45  
46      @Override
47      protected void doWrite(final DataOutputStream dos) throws IOException {
48          dos.writeShort(attributeNameIndex);
49          dos.writeInt(getLength());
50          writeBody(dos);
51      }
52  
53      @Override
54      public boolean equals(final Object obj) {
55          if (this == obj) {
56              return true;
57          }
58          if (obj == null || this.getClass() != obj.getClass()) {
59              return false;
60          }
61          final Attribute other = (Attribute) obj;
62          return Objects.equals(attributeName, other.attributeName);
63      }
64  
65      /**
66       * Gets the attribute name.
67       *
68       * @return the attribute name.
69       */
70      protected CPUTF8 getAttributeName() {
71          return attributeName;
72      }
73  
74      /**
75       * Gets the length.
76       *
77       * @return the length.
78       */
79      protected abstract int getLength();
80  
81      /**
82       * Answer the length of the receiver including its header (the u2 for the attribute name and the u4 for the attribute length). This is relevant when
83       * attributes are nested within other attributes - the outer attribute needs to take the inner attribute headers into account when calculating its length.
84       *
85       * @return int adjusted length
86       */
87      protected int getLengthIncludingHeader() {
88          return getLength() + 2 + 4;
89      }
90  
91      @Override
92      protected ClassFileEntry[] getNestedClassFileEntries() {
93          return new ClassFileEntry[] { getAttributeName() };
94      }
95  
96      /**
97       * Answer true if the receiver needs to have BCI renumbering applied to it; otherwise answer false.
98       *
99       * @return boolean BCI renumbering required
100      */
101     public boolean hasBCIRenumbering() {
102         return false;
103     }
104 
105     @Override
106     public int hashCode() {
107         return Objects.hash(attributeName);
108     }
109 
110     /**
111      * Answer true if the receiver is a source file attribute (which gets special handling when the class is built); otherwise answer false.
112      *
113      * @return boolean source file attribute
114      */
115     public boolean isSourceFileAttribute() {
116         return false;
117     }
118 
119     @Override
120     protected void resolve(final ClassConstantPool pool) {
121         super.resolve(pool);
122         attributeNameIndex = pool.indexOf(attributeName);
123     }
124 
125     /**
126      * Writes this body to the given output stream.
127      *
128      * @param out the output stream.
129      * @throws IOException if an I/O error occurs.
130      */
131     protected abstract void writeBody(DataOutputStream out) throws IOException;
132 
133 }