001    /*
002     * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    
027    package com.sun.tools.classfile;
028    
029    import java.io.IOException;
030    
031    /**
032     * See JVMS3, section 4.4.
033     *
034     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
035     *  you write code that depends on this, you do so at your own risk.
036     *  This code and its internal interfaces are subject to change or
037     *  deletion without notice.</b>
038     */
039    public class Descriptor {
040        public class InvalidDescriptor extends DescriptorException {
041            private static final long serialVersionUID = 1L;
042            InvalidDescriptor(String desc) {
043                this.desc = desc;
044                this.index = -1;
045            }
046    
047            InvalidDescriptor(String desc, int index) {
048                this.desc = desc;
049                this.index = index;
050            }
051    
052            @Override
053            public String getMessage() {
054                // i18n
055                if (index == -1)
056                    return "invalid descriptor \"" + desc + "\"";
057                else
058                    return "descriptor is invalid at offset " + index + " in \"" + desc + "\"";
059            }
060    
061            public final String desc;
062            public final int index;
063    
064        }
065    
066        public Descriptor(ClassReader cr) throws IOException {
067            this(cr.readUnsignedShort());
068        }
069    
070        public Descriptor(int index) {
071            this.index = index;
072    
073        }
074    
075        public String getValue(ConstantPool constant_pool) throws ConstantPoolException {
076            return constant_pool.getUTF8Value(index);
077        }
078    
079        public int getParameterCount(ConstantPool constant_pool)
080                throws ConstantPoolException, InvalidDescriptor {
081            String desc = getValue(constant_pool);
082            int end = desc.indexOf(")");
083            if (end == -1)
084                throw new InvalidDescriptor(desc);
085            parse(desc, 0, end + 1);
086            return count;
087    
088        }
089    
090        public String getParameterTypes(ConstantPool constant_pool)
091                throws ConstantPoolException, InvalidDescriptor {
092            String desc = getValue(constant_pool);
093            int end = desc.indexOf(")");
094            if (end == -1)
095                throw new InvalidDescriptor(desc);
096            return parse(desc, 0, end + 1);
097        }
098    
099        public String getReturnType(ConstantPool constant_pool)
100                throws ConstantPoolException, InvalidDescriptor {
101            String desc = getValue(constant_pool);
102            int end = desc.indexOf(")");
103            if (end == -1)
104                throw new InvalidDescriptor(desc);
105            return parse(desc, end + 1, desc.length());
106        }
107    
108        public String getFieldType(ConstantPool constant_pool)
109                throws ConstantPoolException, InvalidDescriptor {
110            String desc = getValue(constant_pool);
111            return parse(desc, 0, desc.length());
112        }
113    
114        private String parse(String desc, int start, int end)
115                throws InvalidDescriptor {
116            int p = start;
117            StringBuffer sb = new StringBuffer();
118            int dims = 0;
119            count = 0;
120    
121            while (p < end) {
122                String type;
123                char ch;
124                switch (ch = desc.charAt(p++)) {
125                    case '(':
126                        sb.append('(');
127                        continue;
128    
129                    case ')':
130                        sb.append(')');
131                        continue;
132    
133                    case '[':
134                        dims++;
135                        continue;
136    
137                    case 'B':
138                        type = "byte";
139                        break;
140    
141                    case 'C':
142                        type = "char";
143                        break;
144    
145                    case 'D':
146                        type = "double";
147                        break;
148    
149                    case 'F':
150                        type = "float";
151                        break;
152    
153                    case 'I':
154                        type = "int";
155                        break;
156    
157                    case 'J':
158                        type = "long";
159                        break;
160    
161                    case 'L':
162                        int sep = desc.indexOf(';', p);
163                        if (sep == -1)
164                            throw new InvalidDescriptor(desc, p - 1);
165                        type = desc.substring(p, sep).replace('/', '.');
166                        p = sep + 1;
167                        break;
168    
169                    case 'S':
170                        type = "short";
171                        break;
172    
173                    case 'Z':
174                        type = "boolean";
175                        break;
176    
177                    case 'V':
178                        type = "void";
179                        break;
180    
181                    default:
182                        throw new InvalidDescriptor(desc, p - 1);
183                }
184    
185                if (sb.length() > 1 && sb.charAt(0) == '(')
186                    sb.append(", ");
187                sb.append(type);
188                for ( ; dims > 0; dims-- )
189                    sb.append("[]");
190    
191                count++;
192            }
193    
194            return sb.toString();
195        }
196    
197        public final int index;
198        private int count;
199    }