001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.ejb3unit.asm.signature;
030:
031: /**
032: * A signature visitor that generates signatures in string format.
033: *
034: * @author Thomas Hallgren
035: * @author Eric Bruneton
036: */
037: public class SignatureWriter implements SignatureVisitor {
038:
039: /**
040: * Buffer used to construct the signature.
041: */
042: private final StringBuffer buf = new StringBuffer();
043:
044: /**
045: * Indicates if the signature contains formal type parameters.
046: */
047: private boolean hasFormals;
048:
049: /**
050: * Indicates if the signature contains method parameter types.
051: */
052: private boolean hasParameters;
053:
054: /**
055: * Stack used to keep track of class types that have arguments. Each element
056: * of this stack is a boolean encoded in one bit. The top of the stack is
057: * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
058: * /2.
059: */
060: private int argumentStack;
061:
062: /**
063: * Constructs a new {@link SignatureWriter} object.
064: */
065: public SignatureWriter() {
066: }
067:
068: // ------------------------------------------------------------------------
069: // Implementation of the SignatureVisitor interface
070: // ------------------------------------------------------------------------
071:
072: public void visitFormalTypeParameter(final String name) {
073: if (!hasFormals) {
074: hasFormals = true;
075: buf.append('<');
076: }
077: buf.append(name);
078: buf.append(':');
079: }
080:
081: public SignatureVisitor visitClassBound() {
082: return this ;
083: }
084:
085: public SignatureVisitor visitInterfaceBound() {
086: buf.append(':');
087: return this ;
088: }
089:
090: public SignatureVisitor visitSuperclass() {
091: endFormals();
092: return this ;
093: }
094:
095: public SignatureVisitor visitInterface() {
096: return this ;
097: }
098:
099: public SignatureVisitor visitParameterType() {
100: endFormals();
101: if (!hasParameters) {
102: hasParameters = true;
103: buf.append('(');
104: }
105: return this ;
106: }
107:
108: public SignatureVisitor visitReturnType() {
109: endFormals();
110: if (!hasParameters) {
111: buf.append('(');
112: }
113: buf.append(')');
114: return this ;
115: }
116:
117: public SignatureVisitor visitExceptionType() {
118: buf.append('^');
119: return this ;
120: }
121:
122: public void visitBaseType(final char descriptor) {
123: buf.append(descriptor);
124: }
125:
126: public void visitTypeVariable(final String name) {
127: buf.append('T');
128: buf.append(name);
129: buf.append(';');
130: }
131:
132: public SignatureVisitor visitArrayType() {
133: buf.append('[');
134: return this ;
135: }
136:
137: public void visitClassType(final String name) {
138: buf.append('L');
139: buf.append(name);
140: argumentStack *= 2;
141: }
142:
143: public void visitInnerClassType(final String name) {
144: endArguments();
145: buf.append('.');
146: buf.append(name);
147: argumentStack *= 2;
148: }
149:
150: public void visitTypeArgument() {
151: if (argumentStack % 2 == 0) {
152: ++argumentStack;
153: buf.append('<');
154: }
155: buf.append('*');
156: }
157:
158: public SignatureVisitor visitTypeArgument(final char wildcard) {
159: if (argumentStack % 2 == 0) {
160: ++argumentStack;
161: buf.append('<');
162: }
163: if (wildcard != '=') {
164: buf.append(wildcard);
165: }
166: return this ;
167: }
168:
169: public void visitEnd() {
170: endArguments();
171: buf.append(';');
172: }
173:
174: /**
175: * Returns the signature that was built by this signature writer.
176: *
177: * @return the signature that was built by this signature writer.
178: */
179: public String toString() {
180: return buf.toString();
181: }
182:
183: // ------------------------------------------------------------------------
184: // Utility methods
185: // ------------------------------------------------------------------------
186:
187: /**
188: * Ends the formal type parameters section of the signature.
189: */
190: private void endFormals() {
191: if (hasFormals) {
192: hasFormals = false;
193: buf.append('>');
194: }
195: }
196:
197: /**
198: * Ends the type arguments of a class or inner class type.
199: */
200: private void endArguments() {
201: if (argumentStack % 2 != 0) {
202: buf.append('>');
203: }
204: argumentStack /= 2;
205: }
206: }
|