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  import org.apache.commons.compress.harmony.unpack200.SegmentUtils;
26  
27  /**
28   * Name and Type pair constant pool entry.
29   */
30  public class CPNameAndType extends ConstantPoolEntry {
31  
32      CPUTF8 descriptor;
33  
34      transient int descriptorIndex;
35  
36      CPUTF8 name;
37  
38      transient int nameIndex;
39  
40      private boolean hashCodeComputed;
41  
42      private int cachedHashCode;
43  
44      /**
45       * Constructs a new CPNameAndType.
46       *
47       * @param name        TODO
48       * @param descriptor  TODO
49       * @param globalIndex index in CpBands
50       * @throws NullPointerException if name or descriptor is null
51       */
52      public CPNameAndType(final CPUTF8 name, final CPUTF8 descriptor, final int globalIndex) {
53          super(CP_NameAndType, globalIndex);
54          this.name = Objects.requireNonNull(name, "name");
55          this.descriptor = Objects.requireNonNull(descriptor, "descriptor");
56      }
57  
58      /*
59       * field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }
60       */
61  
62      @Override
63      public boolean equals(final Object obj) {
64          if (this == obj) {
65              return true;
66          }
67          if (obj == null || getClass() != obj.getClass()) {
68              return false;
69          }
70          final CPNameAndType other = (CPNameAndType) obj;
71          return Objects.equals(descriptor, other.descriptor)
72                  && Objects.equals(name, other.name);
73      }
74  
75      private void generateHashCode() {
76          hashCodeComputed = true;
77          final int PRIME = 31;
78          int result = 1;
79          result = PRIME * result + descriptor.hashCode();
80          result = PRIME * result + name.hashCode();
81          cachedHashCode = result;
82      }
83  
84      @Override
85      protected ClassFileEntry[] getNestedClassFileEntries() {
86          return new ClassFileEntry[] { name, descriptor };
87      }
88  
89      @Override
90      public int hashCode() {
91          if (!hashCodeComputed) {
92              generateHashCode();
93          }
94          return cachedHashCode;
95      }
96  
97      /**
98       * Answers the invokeinterface count argument when the receiver is treated as an invokeinterface target. This value is not meaningful if the receiver is not
99       * an invokeinterface target.
100      *
101      * @return count
102      */
103     public int invokeInterfaceCount() {
104         return 1 + SegmentUtils.countInvokeInterfaceArgs(descriptor.underlyingString());
105     }
106 
107     @Override
108     protected void resolve(final ClassConstantPool pool) {
109         super.resolve(pool);
110         descriptorIndex = pool.indexOf(descriptor);
111         nameIndex = pool.indexOf(name);
112     }
113 
114     @Override
115     public String toString() {
116         return "NameAndType: " + name + "(" + descriptor + ")";
117     }
118 
119     @Override
120     protected void writeBody(final DataOutputStream dos) throws IOException {
121         dos.writeShort(nameIndex);
122         dos.writeShort(descriptorIndex);
123     }
124 }