001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.bytecode;
031:
032: import java.util.ArrayList;
033:
034: /**
035: * Manages an introspected java classes.
036: */
037: public class TypeSignatureParser {
038: private final JClassLoader _loader;
039: private final String _sig;
040: private final int _length;
041: private int _index;
042:
043: public TypeSignatureParser(JClassLoader loader, String sig) {
044: this (loader, sig, 0);
045: }
046:
047: public TypeSignatureParser(JClassLoader loader, String sig,
048: int index) {
049: _loader = loader;
050: _sig = sig;
051: _length = sig.length();
052: _index = index;
053: }
054:
055: JType nextType() {
056: int ch = read();
057:
058: switch (ch) {
059: case -1:
060: return null;
061:
062: case '>':
063: case ')':
064: _index--;
065: return null;
066:
067: case 'V':
068: return JClass.VOID;
069: case 'Z':
070: return JClass.BOOLEAN;
071: case 'B':
072: return JClass.BYTE;
073: case 'S':
074: return JClass.SHORT;
075: case 'I':
076: return JClass.INT;
077: case 'J':
078: return JClass.LONG;
079: case 'F':
080: return JClass.FLOAT;
081: case 'D':
082: return JClass.DOUBLE;
083: case 'C':
084: return JClass.CHAR;
085:
086: case 'L':
087: return parseClass();
088:
089: default:
090: throw new IllegalStateException("Can't parse: " + _sig);
091: }
092: }
093:
094: private JType parseClass() {
095: int begin = _index;
096: int end = begin;
097:
098: int ch;
099:
100: for (ch = read(); ch >= 0 && ch != ';' && ch != ')'
101: && ch != ',' && ch != '<' && ch != '>'; ch = read()) {
102: end = _index;
103: }
104:
105: String className = _sig.substring(begin, end).replace('/', '.');
106: JClass rawClass = _loader.forName(className);
107:
108: if (ch == '<')
109: return parseParameterizedType(rawClass);
110: else
111: return rawClass;
112: }
113:
114: private JType parseParameterizedType(JClass rawClass) {
115: ArrayList<JType> argList = new ArrayList<JType>();
116:
117: JType type;
118: while ((type = nextType()) != null) {
119: argList.add(type);
120: }
121:
122: int ch = read();
123: if (ch != '>')
124: throw new IllegalStateException("expected '>' at "
125: + (char) ch);
126:
127: JType[] args = new JType[argList.size()];
128: argList.toArray(args);
129:
130: return new JavaParameterizedType(_loader, rawClass, args);
131: }
132:
133: /**
134: * Reads the next character.
135: */
136: private int read() {
137: if (_index < _length)
138: return _sig.charAt(_index++);
139: else
140: return -1;
141: }
142: }
|