001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal;
011:
012: import com.sun.jdi.ClassLoaderReference;
013: import com.sun.jdi.ClassNotLoadedException;
014: import com.sun.jdi.ClassNotPreparedException;
015: import com.sun.jdi.Type;
016: import com.sun.jdi.Value;
017:
018: /**
019: * this class implements the corresponding interfaces
020: * declared by the JDI specification. See the com.sun.jdi package
021: * for more information.
022: *
023: */
024: public abstract class TypeImpl extends AccessibleImpl implements Type {
025: /** Text representation of this type. */
026: protected String fName = null;
027: /** JNI-style signature for this type. */
028: protected String fSignature = null;
029:
030: /**
031: * Creates new instance, used for REFERENCE types.
032: */
033: protected TypeImpl(String description, VirtualMachineImpl vmImpl) {
034: super (description, vmImpl);
035: }
036:
037: /**
038: * Creates new instance, used for PRIMITIVE types or VOID.
039: */
040: protected TypeImpl(String description, VirtualMachineImpl vmImpl,
041: String name, String signature) {
042: super (description, vmImpl);
043: setName(name);
044: setSignature(signature);
045: }
046:
047: /**
048: * @return Returns new instance based on signature and (if it is a ReferenceType) classLoader.
049: * @throws ClassNotLoadedException when type is a ReferenceType and it has not been loaded
050: * by the specified class loader.
051: */
052: public static TypeImpl create(VirtualMachineImpl vmImpl,
053: String signature, ClassLoaderReference classLoader)
054: throws ClassNotLoadedException {
055: // For void values, a VoidType is always returned.
056: if (isVoidSignature(signature))
057: return new VoidTypeImpl(vmImpl);
058:
059: // For primitive variables, an appropriate PrimitiveType is always returned.
060: if (isPrimitiveSignature(signature))
061: return PrimitiveTypeImpl.create(vmImpl, signature);
062:
063: // For object variables, the appropriate ReferenceType is returned if it has
064: // been loaded through the enclosing type's class loader.
065: return ReferenceTypeImpl.create(vmImpl, signature, classLoader);
066: }
067:
068: /**
069: * Assigns name.
070: */
071: public void setName(String name) {
072: fName = name;
073: }
074:
075: /**
076: * Assigns signature.
077: */
078: public void setSignature(String signature) {
079: fSignature = signature;
080: }
081:
082: /**
083: * @return Returns description of Mirror object.
084: */
085: public String toString() {
086: try {
087: return name();
088: } catch (ClassNotPreparedException e) {
089: return JDIMessages.TypeImpl__Unloaded_Type__1;
090: } catch (Exception e) {
091: return fDescription;
092: }
093: }
094:
095: /**
096: * @return Create a null value instance of the type.
097: */
098: public abstract Value createNullValue();
099:
100: /**
101: * @return Returns text representation of this type.
102: */
103: public String name() {
104: return fName;
105: }
106:
107: /**
108: * @return JNI-style signature for this type.
109: */
110: public String signature() {
111: return fSignature;
112: }
113:
114: /**
115: * @return Returns modifier bits.
116: */
117: public abstract int modifiers();
118:
119: /**
120: * Converts a class name to a JNI signature.
121: */
122: public static String classNameToSignature(String qualifiedName) {
123: // L<classname>; : fully-qualified-class
124: /* JNI signature examples:
125: * int[][] -> [[I
126: * long[] -> [J
127: * java.lang.String -> Ljava/lang/String;
128: * java.lang.String[] -> [Ljava/lang/String;
129: */
130: StringBuffer signature = new StringBuffer();
131:
132: int firstBrace = qualifiedName.indexOf('[');
133: if (firstBrace < 0) {
134: // Not an array type. Must be class type.
135: signature.append('L');
136: signature.append(qualifiedName.replace('.', '/'));
137: signature.append(';');
138: return signature.toString();
139: }
140:
141: int index = 0;
142: while ((index = (qualifiedName.indexOf('[', index) + 1)) > 0) {
143: signature.append('[');
144: }
145:
146: String name = qualifiedName.substring(0, firstBrace);
147: switch (name.charAt(0)) {
148: // Check for primitive array type
149: case 'b':
150: if (name.equals("byte")) { //$NON-NLS-1$
151: signature.append('B');
152: return signature.toString();
153: } else if (name.equals("boolean")) { //$NON-NLS-1$
154: signature.append('Z');
155: return signature.toString();
156: }
157: break;
158: case 'i':
159: if (name.equals("int")) { //$NON-NLS-1$
160: signature.append('I');
161: return signature.toString();
162: }
163: break;
164: case 'd':
165: if (name.equals("double")) { //$NON-NLS-1$
166: signature.append('D');
167: return signature.toString();
168: }
169: break;
170: case 's':
171: if (name.equals("short")) { //$NON-NLS-1$
172: signature.append('S');
173: return signature.toString();
174: }
175: break;
176: case 'c':
177: if (name.equals("char")) { //$NON-NLS-1$
178: signature.append('C');
179: return signature.toString();
180: }
181: break;
182: case 'l':
183: if (name.equals("long")) { //$NON-NLS-1$
184: signature.append('J');
185: return signature.toString();
186: }
187: break;
188: case 'f':
189: if (name.equals("float")) { //$NON-NLS-1$
190: signature.append('F');
191: return signature.toString();
192: }
193: break;
194: }
195: // Class type array
196: signature.append('L');
197: signature.append(name.replace('.', '/'));
198: signature.append(';');
199: return signature.toString();
200: }
201:
202: /**
203: * Converts a JNI class signature to a name.
204: */
205: public static String classSignatureToName(String signature) {
206: // L<classname>; : fully-qualified-class
207: return signature.substring(1, signature.length() - 1).replace(
208: '/', '.');
209: }
210:
211: /**
212: * Converts a JNI array signature to a name.
213: */
214: public static String arraySignatureToName(String signature) {
215: // [<type> : array of type <type>
216: if (signature.indexOf('[') < 0) {
217: return signature;
218: }
219: StringBuffer name = new StringBuffer();
220: String type = signature
221: .substring(signature.lastIndexOf('[') + 1);
222: if (type.length() == 1 && isPrimitiveSignature(type)) {
223: name.append(getPrimitiveSignatureToName(type.charAt(0)));
224: } else {
225: name.append(classSignatureToName(type));
226: }
227: int index = 0;
228: while ((index = (signature.indexOf('[', index) + 1)) > 0) {
229: name.append('[').append(']');
230: }
231: return signatureToName(signature.substring(1)) + "[]"; //$NON-NLS-1$
232: }
233:
234: /**
235: * @returns Returns Type Name, converted from a JNI signature.
236: */
237: public static String signatureToName(String signature) {
238: // See JNI 1.1 Specification, Table 3-2 Java VM Type Signatures.
239: String primitive = getPrimitiveSignatureToName(signature
240: .charAt(0));
241: if (primitive != null) {
242: return primitive;
243: }
244: switch (signature.charAt(0)) {
245: case 'V':
246: return "void"; //$NON-NLS-1$
247: case 'L':
248: return classSignatureToName(signature);
249: case '[':
250: return arraySignatureToName(signature);
251: case '(':
252: throw new InternalError(
253: JDIMessages.TypeImpl_Can__t_convert_method_signature_to_name_2);
254: }
255: throw new InternalError(
256: JDIMessages.TypeImpl_Invalid_signature____10
257: + signature + JDIMessages.TypeImpl___11); //
258: }
259:
260: private static String getPrimitiveSignatureToName(char signature) {
261: switch (signature) {
262: case 'Z':
263: return "boolean"; //$NON-NLS-1$
264: case 'B':
265: return "byte"; //$NON-NLS-1$
266: case 'C':
267: return "char"; //$NON-NLS-1$
268: case 'S':
269: return "short"; //$NON-NLS-1$
270: case 'I':
271: return "int"; //$NON-NLS-1$
272: case 'J':
273: return "long"; //$NON-NLS-1$
274: case 'F':
275: return "float"; //$NON-NLS-1$
276: case 'D':
277: return "double"; //$NON-NLS-1$
278: default:
279: return null;
280: }
281: }
282:
283: /**
284: * @returns Returns Jdwp Tag, converted from a JNI signature.
285: */
286: public static byte signatureToTag(String signature) {
287: switch (signature.charAt(0)) {
288: case 'Z':
289: return BooleanValueImpl.tag;
290: case 'B':
291: return ByteValueImpl.tag;
292: case 'C':
293: return CharValueImpl.tag;
294: case 'S':
295: return ShortValueImpl.tag;
296: case 'I':
297: return IntegerValueImpl.tag;
298: case 'J':
299: return LongValueImpl.tag;
300: case 'F':
301: return FloatValueImpl.tag;
302: case 'D':
303: return DoubleValueImpl.tag;
304: case 'V':
305: return VoidValueImpl.tag;
306: case 'L':
307: return ObjectReferenceImpl.tag;
308: case '[':
309: return ArrayReferenceImpl.tag;
310: case '(':
311: throw new InternalError(
312: JDIMessages.TypeImpl_Can__t_covert_method_signature_to_tag___9
313: + signature);
314: }
315: throw new InternalError(
316: JDIMessages.TypeImpl_Invalid_signature____10
317: + signature + JDIMessages.TypeImpl___11); //
318: }
319:
320: /**
321: * @returns Returns true if signature is an primitive signature.
322: */
323: public static boolean isPrimitiveSignature(String signature) {
324: switch (signature.charAt(0)) {
325: case 'Z':
326: case 'B':
327: case 'C':
328: case 'S':
329: case 'I':
330: case 'J':
331: case 'F':
332: case 'D':
333: return true;
334: }
335: return false;
336: }
337:
338: /**
339: * @returns Returns true if signature is void signature.
340: */
341: public static boolean isVoidSignature(String signature) {
342: return (signature.charAt(0) == 'V');
343: }
344:
345: }
|