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