1. package com.sun.org.apache.bcel.internal.classfile;
  2. /* ====================================================================
  3. * The Apache Software License, Version 1.1
  4. *
  5. * Copyright (c) 2001 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Apache" and "Apache Software Foundation" and
  28. * "Apache BCEL" must not be used to endorse or promote products
  29. * derived from this software without prior written permission. For
  30. * written permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * "Apache BCEL", nor may "Apache" appear in their name, without
  34. * prior written permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation. For more
  52. * information on the Apache Software Foundation, please see
  53. * <http://www.apache.org/>.
  54. */
  55. import com.sun.org.apache.bcel.internal.Constants;
  56. import java.io.*;
  57. /**
  58. * This class is derived from <em>Attribute</em> and represents a reference
  59. * to a <href="http://wwwipd.ira.uka.de/~pizza/gj/">GJ</a> attribute.
  60. *
  61. * @version $Id: Signature.java,v 1.1.1.1 2001/10/29 20:00:03 jvanzyl Exp $
  62. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  63. * @see Attribute
  64. */
  65. public final class Signature extends Attribute {
  66. private int signature_index;
  67. /**
  68. * Initialize from another object. Note that both objects use the same
  69. * references (shallow copy). Use clone() for a physical copy.
  70. */
  71. public Signature(Signature c) {
  72. this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
  73. }
  74. /**
  75. * Construct object from file stream.
  76. * @param name_index Index in constant pool to CONSTANT_Utf8
  77. * @param length Content length in bytes
  78. * @param file Input stream
  79. * @param constant_pool Array of constants
  80. * @throw IOException
  81. */
  82. Signature(int name_index, int length, DataInputStream file,
  83. ConstantPool constant_pool) throws IOException
  84. {
  85. this(name_index, length, file.readUnsignedShort(), constant_pool);
  86. }
  87. /**
  88. * @param name_index Index in constant pool to CONSTANT_Utf8
  89. * @param length Content length in bytes
  90. * @param constant_pool Array of constants
  91. * @param Signature_index Index in constant pool to CONSTANT_Utf8
  92. */
  93. public Signature(int name_index, int length, int signature_index,
  94. ConstantPool constant_pool)
  95. {
  96. super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool);
  97. this.signature_index = signature_index;
  98. }
  99. /**
  100. * Called by objects that are traversing the nodes of the tree implicitely
  101. * defined by the contents of a Java class. I.e., the hierarchy of methods,
  102. * fields, attributes, etc. spawns a tree of objects.
  103. *
  104. * @param v Visitor object
  105. */
  106. public void accept(Visitor v) {
  107. System.err.println("Visiting non-standard Signature object");
  108. }
  109. /**
  110. * Dump source file attribute to file stream in binary format.
  111. *
  112. * @param file Output file stream
  113. * @throw IOException
  114. */
  115. public final void dump(DataOutputStream file) throws IOException
  116. {
  117. super.dump(file);
  118. file.writeShort(signature_index);
  119. }
  120. /**
  121. * @return Index in constant pool of source file name.
  122. */
  123. public final int getSignatureIndex() { return signature_index; }
  124. /**
  125. * @param Signature_index.
  126. */
  127. public final void setSignatureIndex(int signature_index) {
  128. this.signature_index = signature_index;
  129. }
  130. /**
  131. * @return GJ signature.
  132. */
  133. public final String getSignature() {
  134. ConstantUtf8 c = (ConstantUtf8)constant_pool.getConstant(signature_index,
  135. Constants.CONSTANT_Utf8);
  136. return c.getBytes();
  137. }
  138. /**
  139. * Extends ByteArrayInputStream to make 'unreading' chars possible.
  140. */
  141. private static final class MyByteArrayInputStream extends ByteArrayInputStream {
  142. MyByteArrayInputStream(String data) { super(data.getBytes()); }
  143. final int mark() { return pos; }
  144. final String getData() { return new String(buf); }
  145. final void reset(int p) { pos = p; }
  146. final void unread() { if(pos > 0) pos--; }
  147. }
  148. private static boolean identStart(int ch) {
  149. return ch == 'T' || ch == 'L';
  150. }
  151. private static boolean identPart(int ch) {
  152. return ch == '/' || ch == ';';
  153. }
  154. private static final void matchIdent(MyByteArrayInputStream in, StringBuffer buf) {
  155. int ch;
  156. if((ch = in.read()) == -1)
  157. throw new RuntimeException("Illegal signature: " + in.getData() +
  158. " no ident, reaching EOF");
  159. //System.out.println("return from ident:" + (char)ch);
  160. if(!identStart(ch)) {
  161. StringBuffer buf2 = new StringBuffer();
  162. int count = 1;
  163. while(Character.isJavaIdentifierPart((char)ch)) {
  164. buf2.append((char)ch);
  165. count++;
  166. ch = in.read();
  167. }
  168. if(ch == ':') { // Ok, formal parameter
  169. in.skip("Ljava/lang/Object".length());
  170. buf.append(buf2);
  171. ch = in.read();
  172. in.unread();
  173. //System.out.println("so far:" + buf2 + ":next:" +(char)ch);
  174. } else {
  175. for(int i=0; i < count; i++)
  176. in.unread();
  177. }
  178. return;
  179. }
  180. StringBuffer buf2 = new StringBuffer();
  181. ch = in.read();
  182. do {
  183. buf2.append((char)ch);
  184. ch = in.read();
  185. //System.out.println("within ident:"+ (char)ch);
  186. } while((ch != -1) && (Character.isJavaIdentifierPart((char)ch) || (ch == '/')));
  187. buf.append(buf2.toString().replace('/', '.'));
  188. //System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
  189. if(ch != -1)
  190. in.unread();
  191. }
  192. private static final void matchGJIdent(MyByteArrayInputStream in,
  193. StringBuffer buf)
  194. {
  195. int ch;
  196. matchIdent(in, buf);
  197. ch = in.read();
  198. if((ch == '<') || ch == '(') { // Parameterized or method
  199. //System.out.println("Enter <");
  200. buf.append((char)ch);
  201. matchGJIdent(in, buf);
  202. while(((ch = in.read()) != '>') && (ch != ')')) { // List of parameters
  203. if(ch == -1)
  204. throw new RuntimeException("Illegal signature: " + in.getData() +
  205. " reaching EOF");
  206. //System.out.println("Still no >");
  207. buf.append(", ");
  208. in.unread();
  209. matchGJIdent(in, buf); // Recursive call
  210. }
  211. //System.out.println("Exit >");
  212. buf.append((char)ch);
  213. } else
  214. in.unread();
  215. ch = in.read();
  216. if(identStart(ch)) {
  217. in.unread();
  218. matchGJIdent(in, buf);
  219. } else if(ch == ')') {
  220. in.unread();
  221. return;
  222. } else if(ch != ';')
  223. throw new RuntimeException("Illegal signature: " + in.getData() + " read " +
  224. (char)ch);
  225. }
  226. public static String translate(String s) {
  227. //System.out.println("Sig:" + s);
  228. StringBuffer buf = new StringBuffer();
  229. matchGJIdent(new MyByteArrayInputStream(s), buf);
  230. return buf.toString();
  231. }
  232. public static final boolean isFormalParameterList(String s) {
  233. return s.startsWith("<") && (s.indexOf(':') > 0);
  234. }
  235. public static final boolean isActualParameterList(String s) {
  236. return s.startsWith("L") && s.endsWith(">");
  237. }
  238. /**
  239. * @return String representation
  240. */
  241. public final String toString() {
  242. String s = getSignature();
  243. return "Signature(" + s + ")";
  244. }
  245. /**
  246. * @return deep copy of this attribute
  247. */
  248. public Attribute copy(ConstantPool constant_pool) {
  249. return (Signature)clone();
  250. }
  251. }