001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200.bytecode;
018:
019: import java.io.DataOutputStream;
020: import java.io.IOException;
021:
022: import org.apache.harmony.pack200.SegmentUtils;
023:
024: public class CPNameAndType extends ConstantPoolEntry {
025:
026: CPUTF8 descriptor;
027:
028: transient int descriptorIndex;
029:
030: CPUTF8 name;
031:
032: transient int nameIndex;
033:
034: public CPNameAndType(String descriptor) {
035: super (ConstantPoolEntry.CP_NameAndType);
036: int descriptorDomain = ClassConstantPool.DOMAIN_UNDEFINED;
037: int colon = descriptor.indexOf(':');
038: String nameString = descriptor.substring(0, colon);
039: String descriptorString = descriptor.substring(colon + 1);
040: // For some reason, descriptors which have just plain
041: // native types are stored in DOMAIN_NORMALASCIIZ rather
042: // than in DOMAIN_SIGNATUREASCIIZ. This might indicate
043: // that DOMAIN_SIGNATUREASCIIZ is poorly named.
044: boolean nativeDescriptor = true;
045: for (int index = 0; index < descriptorString.length(); index++) {
046: char currentChar = descriptorString.charAt(index);
047: if (Character.isLetter(currentChar)) {
048: if (currentChar == 'L') {
049: nativeDescriptor = false;
050: }
051: break;
052: }
053: }
054: this .domain = ClassConstantPool.DOMAIN_NAMEANDTYPE;
055: this .name = new CPUTF8(nameString,
056: ClassConstantPool.DOMAIN_NORMALASCIIZ);
057: if (nativeDescriptor) {
058: // Native signatures are stored in DOMAIN_NORMALASCIIZ, not
059: // DOMAIN_SIGNATUREASCIIZ for some reason.
060: descriptorDomain = ClassConstantPool.DOMAIN_NORMALASCIIZ;
061: } else {
062: descriptorDomain = ClassConstantPool.DOMAIN_SIGNATUREASCIIZ;
063: }
064: this .descriptor = new CPUTF8(descriptorString, descriptorDomain);
065: }
066:
067: protected ClassFileEntry[] getNestedClassFileEntries() {
068: return new ClassFileEntry[] { name, descriptor };
069: }
070:
071: protected void resolve(ClassConstantPool pool) {
072: super .resolve(pool);
073: descriptorIndex = pool.indexOf(descriptor);
074: nameIndex = pool.indexOf(name);
075: }
076:
077: /*
078: * field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2
079: * attributes_count; attribute_info attributes[attributes_count]; }
080: */
081:
082: protected void writeBody(DataOutputStream dos) throws IOException {
083: dos.writeShort(nameIndex);
084: dos.writeShort(descriptorIndex);
085: }
086:
087: public String toString() {
088: return "NameAndType: " + name + "(" + descriptor + ")";
089: }
090:
091: public int hashCode() {
092: final int PRIME = 31;
093: int result = 1;
094: result = PRIME * result
095: + ((descriptor == null) ? 0 : descriptor.hashCode());
096: result = PRIME * result
097: + ((name == null) ? 0 : name.hashCode());
098: return result;
099: }
100:
101: public boolean equals(Object obj) {
102: if (this == obj)
103: return true;
104: if (obj == null)
105: return false;
106: if (getClass() != obj.getClass())
107: return false;
108: final CPNameAndType other = (CPNameAndType) obj;
109: if (descriptor == null) {
110: if (other.descriptor != null)
111: return false;
112: } else if (!descriptor.equals(other.descriptor))
113: return false;
114: if (name == null) {
115: if (other.name != null)
116: return false;
117: } else if (!name.equals(other.name))
118: return false;
119: return true;
120: }
121:
122: /**
123: * Answers the invokeinterface count argument when the
124: * receiver is treated as an invokeinterface target.
125: * This value is not meaningful if the receiver is not
126: * an invokeinterface target.
127: * @return count
128: */
129: public int invokeInterfaceCount() {
130: return 1 + SegmentUtils.countInvokeInterfaceArgs(descriptor
131: .underlyingString());
132: }
133:
134: /* (non-Javadoc)
135: * @see org.apache.harmony.pack200.bytecode.ConstantPoolEntry#comparisonString()
136: */
137: public String comparisonString() {
138: // First come those things which don't have an
139: // associated signature. Then come the native signatures,
140: // then finally the class signatures.
141: // TODO: I think Character.MAX_VALUE is no longer the
142: // biggest character, what with the weird codepage thing
143: // going on. How to sort these things so that even if
144: // they're in some oddball codepage they'll still end
145: // up sorted correctly?
146: String descriptorString = descriptor.underlyingString();
147: StringBuffer comparisonBuffer = new StringBuffer();
148: if ((descriptorString.indexOf("(")) == -1) {
149: // it's a variable reference
150: comparisonBuffer.append(descriptor.underlyingString());
151: } else {
152: // it's a signature. Append something that will
153: // make the comparison buffer bigger than all
154: // non-signature references.
155: comparisonBuffer.append(Character.MAX_VALUE);
156: // do the natives first
157: if (descriptorString.length() <= 4) {
158: // it's a native signature
159: comparisonBuffer.append(descriptor.underlyingString());
160: } else {
161: // it's a non-native signature. Append something
162: // that will make the comparison buffer bigger
163: // than all native signature references.
164: comparisonBuffer.append(Character.MAX_VALUE);
165: comparisonBuffer.append(descriptor.underlyingString());
166: }
167: }
168: comparisonBuffer.append(name.underlyingString());
169: return comparisonBuffer.toString();
170: }
171: }
|