Source Code Cross Referenced for ClassFile.java in  » Scripting » jacl » org » codehaus » janino » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » org.codehaus.janino.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Janino - An embedded Java[TM] compiler
0003:         *
0004:         * Copyright (c) 2006, Arno Unkrig
0005:         * All rights reserved.
0006:         *
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met:
0010:         *
0011:         *    1. Redistributions of source code must retain the above copyright
0012:         *       notice, this list of conditions and the following disclaimer.
0013:         *    2. Redistributions in binary form must reproduce the above
0014:         *       copyright notice, this list of conditions and the following
0015:         *       disclaimer in the documentation and/or other materials
0016:         *       provided with the distribution.
0017:         *    3. The name of the author may not be used to endorse or promote
0018:         *       products derived from this software without specific prior
0019:         *       written permission.
0020:         *
0021:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0022:         * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0023:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024:         * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0025:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0026:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0027:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0029:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0030:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0031:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0032:         */
0033:
0034:        package org.codehaus.janino.util;
0035:
0036:        import java.io.*;
0037:        import java.util.*;
0038:
0039:        import org.codehaus.janino.Descriptor;
0040:
0041:        /**
0042:         * An object that represents the Java<sup>TM</sup> "class file" format.
0043:         * <p>
0044:         * {@link #ClassFile(InputStream)} creates a {@link ClassFile} object from the bytecode
0045:         * read from the given {@link InputStream}.
0046:         * <p>
0047:         * {@link #store(OutputStream)} generates Java<sup>TM</sup> bytecode
0048:         * which is suitable for being processed by a Java<sup>TM</sup> virtual
0049:         * machine.
0050:         */
0051:        public class ClassFile {
0052:
0053:            /**
0054:             * Construct from parsed components.
0055:             * @param accessFlags as defined by {@link org.codehaus.janino.Mod}
0056:             * @param thisClassFD the field descriptor for this class
0057:             * @param superclassFD the field descriptor for the extended class (e.g. "Ljava/lang/Object;")
0058:             * @param interfaceFDs the field descriptors for the implemented interfaces
0059:             */
0060:            public ClassFile(short accessFlags, String this ClassFD,
0061:                    String super classFD, String[] interfaceFDs) {
0062:                this .majorVersion = ClassFile.MAJOR_VERSION_JDK_1_1;
0063:                this .minorVersion = ClassFile.MINOR_VERSION_JDK_1_1;
0064:
0065:                this .constantPool = new ArrayList();
0066:                this .constantPool.add(null); // Add fake "0" index entry.
0067:                this .constantPoolMap = new HashMap();
0068:
0069:                this .accessFlags = accessFlags;
0070:                this .this Class = this .addConstantClassInfo(this ClassFD);
0071:                this .super class = this .addConstantClassInfo(super classFD);
0072:                this .interfaces = new short[interfaceFDs.length];
0073:                for (int i = 0; i < interfaceFDs.length; ++i) {
0074:                    this .interfaces[i] = this 
0075:                            .addConstantClassInfo(interfaceFDs[i]);
0076:                }
0077:
0078:                this .fieldInfos = new ArrayList();
0079:                this .methodInfos = new ArrayList();
0080:                this .attributes = new ArrayList();
0081:            }
0082:
0083:            /**
0084:             * Adds a "SourceFile" attribute to this class file. (Does not check whether one exists already.)
0085:             * @param sourceFileName
0086:             */
0087:            public void addSourceFileAttribute(String sourceFileName) {
0088:                this .attributes.add(new SourceFileAttribute(this 
0089:                        .addConstantUtf8Info("SourceFile"), // attributeNameIndex
0090:                        this .addConstantUtf8Info(sourceFileName) // sourceFileIndex
0091:                        ));
0092:            }
0093:
0094:            public void addDeprecatedAttribute() {
0095:                this .attributes.add(new DeprecatedAttribute(this 
0096:                        .addConstantUtf8Info("Deprecated")));
0097:            }
0098:
0099:            /**
0100:             * Find the "InnerClasses" attribute of this class file
0101:             * @return <code>null</code> if this class has no "InnerClasses" attribute
0102:             */
0103:            public InnerClassesAttribute getInnerClassesAttribute() {
0104:                Short ni = (Short) this .constantPoolMap
0105:                        .get(new ConstantUtf8Info("InnerClasses"));
0106:                if (ni == null)
0107:                    return null;
0108:
0109:                for (Iterator it = this .attributes.iterator(); it.hasNext();) {
0110:                    AttributeInfo ai = (AttributeInfo) it.next();
0111:                    if (ai.nameIndex == ni.shortValue()
0112:                            && ai instanceof  InnerClassesAttribute)
0113:                        return (InnerClassesAttribute) ai;
0114:                }
0115:                return null;
0116:            }
0117:
0118:            /**
0119:             * Create an "InnerClasses" attribute if it does not exist, then add the given entry
0120:             * to the "InnerClasses" attribute.
0121:             * @param e
0122:             */
0123:            public void addInnerClassesAttributeEntry(
0124:                    InnerClassesAttribute.Entry e) {
0125:                InnerClassesAttribute ica = this .getInnerClassesAttribute();
0126:                if (ica == null) {
0127:                    ica = new InnerClassesAttribute(this 
0128:                            .addConstantUtf8Info("InnerClasses"));
0129:                    this .attributes.add(ica);
0130:                }
0131:                ica.getEntries().add(e);
0132:                return;
0133:            }
0134:
0135:            /**
0136:             * Read "class file" data from a {@link InputStream} and construct a
0137:             * {@link ClassFile} object from it.
0138:             * <p>
0139:             * If the {@link ClassFile} is created with this constructor, then most modifying operations
0140:             * lead to a {@link UnsupportedOperationException}; only fields, methods and
0141:             * attributes can be added. 
0142:             * @param inputStream
0143:             * @throws IOException
0144:             * @throws ClassFormatError
0145:             */
0146:            public ClassFile(InputStream inputStream) throws IOException,
0147:                    ClassFormatError {
0148:                DataInputStream dis = inputStream instanceof  DataInputStream ? (DataInputStream) inputStream
0149:                        : new DataInputStream(inputStream);
0150:
0151:                int magic = dis.readInt(); // magic
0152:                if (magic != ClassFile.CLASS_FILE_MAGIC)
0153:                    throw new ClassFormatError("Invalid magic number");
0154:
0155:                this .minorVersion = dis.readShort(); // minor_version
0156:                this .majorVersion = dis.readShort(); // major_version
0157:                if (!ClassFile.isRecognizedVersion(this .majorVersion,
0158:                        this .minorVersion))
0159:                    throw new ClassFormatError(
0160:                            "Unrecognized class file format version "
0161:                                    + this .majorVersion + "/"
0162:                                    + this .minorVersion);
0163:
0164:                this .constantPool = new ArrayList();
0165:                this .constantPoolMap = new HashMap();
0166:                this .loadConstantPool(dis); // constant_pool_count, constant_pool
0167:
0168:                this .accessFlags = dis.readShort(); // access_flags
0169:                this .this Class = dis.readShort(); // this_class
0170:                this .super class = dis.readShort(); // super_class
0171:                this .interfaces = ClassFile.readShortArray(dis); // interfaces_count, interfaces
0172:
0173:                this .fieldInfos = Collections.unmodifiableList(this 
0174:                        .loadFields(dis)); // fields_count, fields
0175:                this .methodInfos = Collections.unmodifiableList(this 
0176:                        .loadMethods(dis)); // methods_count, methods
0177:                this .attributes = Collections.unmodifiableList(this 
0178:                        .loadAttributes(dis)); // attributes_count, attributes
0179:            }
0180:
0181:            /**
0182:             * @return The fully qualified name of this class, e.g. "pkg1.pkg2.Outer$Inner"
0183:             */
0184:            public String getThisClassName() {
0185:                return this .getConstantClassName(this .this Class).replace('/',
0186:                        '.');
0187:            }
0188:
0189:            /**
0190:             * Sets the major and minor class file version numbers (JVMS 4.1). The class file version
0191:             * defaults to the JDK 1.1 values (45.3) which execute on virtually every JVM.
0192:             * @param majorVersion
0193:             * @param minorVersion
0194:             */
0195:            public void setVersion(short majorVersion, short minorVersion) {
0196:                this .majorVersion = majorVersion;
0197:                this .minorVersion = minorVersion;
0198:            }
0199:
0200:            /**
0201:             * Returns the current major class file version number.
0202:             */
0203:            public short getMajorVersion() {
0204:                return this .majorVersion;
0205:            }
0206:
0207:            /**
0208:             * Returns the current minor class file version number.
0209:             */
0210:            public short getMinorVersion() {
0211:                return this .minorVersion;
0212:            }
0213:
0214:            public static boolean isRecognizedVersion(short majorVersion,
0215:                    short minorVersion) {
0216:                return ((majorVersion == ClassFile.MAJOR_VERSION_JDK_1_1 && minorVersion == ClassFile.MINOR_VERSION_JDK_1_1)
0217:                        || (majorVersion == ClassFile.MAJOR_VERSION_JDK_1_2 && minorVersion == ClassFile.MINOR_VERSION_JDK_1_2)
0218:                        || (majorVersion == ClassFile.MAJOR_VERSION_JDK_1_3 && minorVersion == ClassFile.MINOR_VERSION_JDK_1_3)
0219:                        || (majorVersion == ClassFile.MAJOR_VERSION_JDK_1_4 && minorVersion == ClassFile.MINOR_VERSION_JDK_1_4) || (majorVersion == ClassFile.MAJOR_VERSION_JDK_1_5 && minorVersion == ClassFile.MINOR_VERSION_JDK_1_5));
0220:            }
0221:
0222:            /**
0223:             * Add a "CONSTANT_Class_info" structure to the class file.
0224:             * 
0225:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1221">JVM specification, section 4.4.1</a>
0226:             */
0227:            public short addConstantClassInfo(String typeFD) {
0228:                String s;
0229:                if (Descriptor.isClassOrInterfaceReference(typeFD)) {
0230:                    s = Descriptor.toInternalForm(typeFD);
0231:                } else if (Descriptor.isArrayReference(typeFD)) {
0232:                    s = typeFD;
0233:                } else {
0234:                    throw new RuntimeException("\""
0235:                            + Descriptor.toString(typeFD)
0236:                            + "\" is neither a class nor an array");
0237:                }
0238:
0239:                return this .addToConstantPool(new ConstantClassInfo(this 
0240:                        .addConstantUtf8Info(s)));
0241:            }
0242:
0243:            /**
0244:             * Add a "CONSTANT_Fieldref_info" structure to the class file.
0245:             * 
0246:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#42041">JVM specification, section 4.4.2</a>
0247:             */
0248:            public short addConstantFieldrefInfo(String classFD,
0249:                    String fieldName, String fieldFD) {
0250:                return this .addToConstantPool(new ConstantFieldrefInfo(this 
0251:                        .addConstantClassInfo(classFD), this 
0252:                        .addConstantNameAndTypeInfo(fieldName, fieldFD)));
0253:            }
0254:
0255:            /**
0256:             * Add a "CONSTANT_Methodref_info" structure to the class file.
0257:             * 
0258:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#42041">JVM specification, section 4.4.2</a>
0259:             */
0260:            public short addConstantMethodrefInfo(String classFD,
0261:                    String methodName, String methodMD) {
0262:                return this .addToConstantPool(new ConstantMethodrefInfo(this 
0263:                        .addConstantClassInfo(classFD), this 
0264:                        .addConstantNameAndTypeInfo(methodName, methodMD)));
0265:            }
0266:
0267:            /**
0268:             * Add a "CONSTANT_InterfaceMethodref_info" structure to the class file.
0269:             * 
0270:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#42041">JVM specification, section 4.4.2</a>
0271:             */
0272:            public short addConstantInterfaceMethodrefInfo(String classFD,
0273:                    String methodName, String methodMD) {
0274:                return this 
0275:                        .addToConstantPool(new ConstantInterfaceMethodrefInfo(
0276:                                this .addConstantClassInfo(classFD), this 
0277:                                        .addConstantNameAndTypeInfo(methodName,
0278:                                                methodMD)));
0279:            }
0280:
0281:            /**
0282:             * Add a "CONSTANT_String_info" structure to the class file.
0283:             * 
0284:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#29297">JVM specification, section 4.4.3</a>
0285:             */
0286:            public short addConstantStringInfo(String string) {
0287:                return this .addToConstantPool(new ConstantStringInfo(this 
0288:                        .addConstantUtf8Info(string)));
0289:            }
0290:
0291:            /**
0292:             * Add a "CONSTANT_Integer_info" structure to the class file.
0293:             * 
0294:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#21942">JVM specification, section 4.4.4</a>
0295:             */
0296:            public short addConstantIntegerInfo(final int value) {
0297:                return this .addToConstantPool(new ConstantIntegerInfo(value));
0298:            }
0299:
0300:            /**
0301:             * Add a "CONSTANT_Float_info" structure to the class file.
0302:             * 
0303:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#21942">JVM specification, section 4.4.4</a>
0304:             */
0305:            public short addConstantFloatInfo(final float value) {
0306:                return this .addToConstantPool(new ConstantFloatInfo(value));
0307:            }
0308:
0309:            /**
0310:             * Add a "CONSTANT_Long_info" structure to the class file.
0311:             * 
0312:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1348">JVM specification, section 4.4.5</a>
0313:             */
0314:            public short addConstantLongInfo(final long value) {
0315:                return this .addToConstantPool(new ConstantLongInfo(value));
0316:            }
0317:
0318:            /**
0319:             * Add a "CONSTANT_Double_info" structure to the class file.
0320:             * 
0321:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1348">JVM specification, section 4.4.5</a>
0322:             */
0323:            public short addConstantDoubleInfo(final double value) {
0324:                return this .addToConstantPool(new ConstantDoubleInfo(value));
0325:            }
0326:
0327:            /**
0328:             * Add a "CONSTANT_NameAndType_info" structure to the class file.
0329:             * 
0330:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1327">JVM specification, section 4.4.6</a>
0331:             */
0332:            private short addConstantNameAndTypeInfo(String name,
0333:                    String descriptor) {
0334:                return this .addToConstantPool(new ConstantNameAndTypeInfo(this 
0335:                        .addConstantUtf8Info(name), this 
0336:                        .addConstantUtf8Info(descriptor)));
0337:            }
0338:
0339:            /**
0340:             * Add a "CONSTANT_Utf8_info" structure to the class file.
0341:             * 
0342:             * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#7963">JVM specification, section 4.4.7</a>
0343:             */
0344:            public short addConstantUtf8Info(final String s) {
0345:                return this .addToConstantPool(new ConstantUtf8Info(s));
0346:            }
0347:
0348:            /**
0349:             * Convenience method that adds a String, Integer, Float, Long or Double ConstantInfo.
0350:             */
0351:            private short addConstantSIFLDInfo(Object cv) {
0352:                if (cv instanceof  String) {
0353:                    return this .addConstantStringInfo((String) cv);
0354:                } else if (cv instanceof  Byte || cv instanceof  Short
0355:                        || cv instanceof  Integer) {
0356:                    return this 
0357:                            .addConstantIntegerInfo(((Number) cv).intValue());
0358:                } else if (cv instanceof  Boolean) {
0359:                    return this .addConstantIntegerInfo(((Boolean) cv)
0360:                            .booleanValue() ? 1 : 0);
0361:                } else if (cv instanceof  Character) {
0362:                    return this .addConstantIntegerInfo(((Character) cv)
0363:                            .charValue());
0364:                } else if (cv instanceof  Float) {
0365:                    return this .addConstantFloatInfo(((Float) cv).floatValue());
0366:                } else if (cv instanceof  Long) {
0367:                    return this .addConstantLongInfo(((Long) cv).longValue());
0368:                } else if (cv instanceof  Double) {
0369:                    return this .addConstantDoubleInfo(((Double) cv)
0370:                            .doubleValue());
0371:                } else {
0372:                    throw new RuntimeException(
0373:                            "Unexpected constant value type \""
0374:                                    + cv.getClass().getName() + "\"");
0375:                }
0376:            }
0377:
0378:            private short addToConstantPool(ConstantPoolInfo cpi) {
0379:                Short index = (Short) this .constantPoolMap.get(cpi);
0380:                if (index != null)
0381:                    return index.shortValue();
0382:
0383:                short res = (short) this .constantPool.size();
0384:                this .constantPool.add(cpi);
0385:                if (cpi.isWide())
0386:                    this .constantPool.add(null);
0387:
0388:                this .constantPoolMap.put(cpi, new Short(res));
0389:                return res;
0390:            }
0391:
0392:            public FieldInfo addFieldInfo(short accessFlags, String fieldName,
0393:                    String fieldTypeFD, Object optionalConstantValue) {
0394:                List attributes = new ArrayList();
0395:                if (optionalConstantValue != null) {
0396:                    attributes.add(new ConstantValueAttribute(this 
0397:                            .addConstantUtf8Info("ConstantValue"), this 
0398:                            .addConstantSIFLDInfo(optionalConstantValue)));
0399:                }
0400:                FieldInfo fi = new FieldInfo(accessFlags, // accessFlags
0401:                        this .addConstantUtf8Info(fieldName), // nameIndex
0402:                        this .addConstantUtf8Info(fieldTypeFD), // descriptorIndex
0403:                        attributes // attributes
0404:                );
0405:                this .fieldInfos.add(fi);
0406:                return fi;
0407:            }
0408:
0409:            public MethodInfo addMethodInfo(short accessFlags,
0410:                    String methodName, String methodMD) {
0411:                MethodInfo mi = new MethodInfo(accessFlags, // accessFlags
0412:                        this .addConstantUtf8Info(methodName), // nameIndex
0413:                        this .addConstantUtf8Info(methodMD), // desriptorIndex
0414:                        new ArrayList() // attributes
0415:                );
0416:                this .methodInfos.add(mi);
0417:                return mi;
0418:            }
0419:
0420:            public ConstantPoolInfo getConstantPoolInfo(short index) {
0421:                return (ConstantPoolInfo) this .constantPool.get(index);
0422:            }
0423:
0424:            /**
0425:             * @param index Index to a <code>CONSTANT_Class_info</code> in the constant pool
0426:             * @return The name of the denoted class in "internal form" (see JVMS 4.2)
0427:             */
0428:            public String getConstantClassName(short index) {
0429:                ConstantClassInfo cci = (ConstantClassInfo) this 
0430:                        .getConstantPoolInfo(index);
0431:                ConstantUtf8Info cui = (ConstantUtf8Info) this 
0432:                        .getConstantPoolInfo(cci.nameIndex);
0433:                return cui.s;
0434:            }
0435:
0436:            /**
0437:             * @param index Index to a <code>CONSTANT_Utf8_info</code> in the constant pool
0438:             * @return The string represented by the structure
0439:             */
0440:            public String getConstantUtf8(short index) {
0441:                ConstantUtf8Info cui = (ConstantUtf8Info) this 
0442:                        .getConstantPoolInfo(index);
0443:                return cui.s;
0444:            }
0445:
0446:            /**
0447:             * u4 length, u1[length]
0448:             */
0449:            private static byte[] readLengthAndBytes(DataInputStream dis)
0450:                    throws IOException {
0451:                byte[] ba = new byte[dis.readInt()];
0452:                dis.readFully(ba);
0453:                return ba;
0454:            }
0455:
0456:            /**
0457:             * u2 length, u2[length]
0458:             */
0459:            private static short[] readShortArray(DataInputStream dis)
0460:                    throws IOException {
0461:                short count = dis.readShort();
0462:                short[] result = new short[count];
0463:                for (int i = 0; i < count; ++i)
0464:                    result[i] = dis.readShort();
0465:                return result;
0466:            }
0467:
0468:            /**
0469:             * u2 constant_pool_count, constant_pool[constant_pool_count]
0470:             */
0471:            private void loadConstantPool(DataInputStream dis)
0472:                    throws IOException {
0473:                this .constantPool.clear();
0474:                this .constantPoolMap.clear();
0475:
0476:                short constantPoolCount = dis.readShort(); // constant_pool_count
0477:                this .constantPool.add(null);
0478:                for (short i = 1; i < constantPoolCount; ++i) {
0479:                    ConstantPoolInfo cpi = ConstantPoolInfo
0480:                            .loadConstantPoolInfo(dis);
0481:                    this .constantPool.add(cpi);
0482:                    this .constantPoolMap.put(cpi, new Short(i));
0483:                    if (cpi instanceof  ConstantLongInfo
0484:                            || cpi instanceof  ConstantDoubleInfo) {
0485:                        this .constantPool.add(null);
0486:                        ++i;
0487:                    }
0488:                }
0489:            }
0490:
0491:            /**
0492:             * u2 fields_count, fields[fields_count]
0493:             */
0494:            private List loadFields(DataInputStream dis) throws IOException {
0495:                short fieldsCount = dis.readShort();
0496:                List fields = new ArrayList(fieldsCount);
0497:                for (int i = 0; i < fieldsCount; ++i) {
0498:                    fields.add(new FieldInfo(dis.readShort(), // accessFlags
0499:                            dis.readShort(), // nameIndex
0500:                            dis.readShort(), // descriptorIndex
0501:                            this .loadAttributes(dis) // attributes
0502:                            ));
0503:                }
0504:                return fields;
0505:            }
0506:
0507:            /**
0508:             * u2 methods_count, methods[methods_count]
0509:             */
0510:            private List loadMethods(DataInputStream dis) throws IOException {
0511:                short methodsCount = dis.readShort();
0512:                List methods = new ArrayList(methodsCount);
0513:                for (int i = 0; i < methodsCount; ++i)
0514:                    methods.add(this .loadMethodInfo(dis));
0515:                return methods;
0516:            }
0517:
0518:            /**
0519:             * u2 attributes_count, attributes[attributes_count]
0520:             */
0521:            private List loadAttributes(DataInputStream dis) throws IOException {
0522:                short attributesCount = dis.readShort();
0523:                List attributes = new ArrayList(attributesCount);
0524:                for (int i = 0; i < attributesCount; ++i)
0525:                    attributes.add(this .loadAttribute(dis));
0526:                return attributes;
0527:            }
0528:
0529:            /**
0530:             * Write {@link ClassFile} to an {@link OutputStream}, in "class file" format.
0531:             * <p>
0532:             * Notice that if an {@link IOException} is thrown, the class file is
0533:             * probably written incompletely and thus invalid. The calling method must take
0534:             * care of this situation, e.g. by closing the output stream and then deleting the
0535:             * file.
0536:             * @param os
0537:             * @throws IOException
0538:             */
0539:            public void store(OutputStream os) throws IOException {
0540:                DataOutputStream dos = os instanceof  DataOutputStream ? (DataOutputStream) os
0541:                        : new DataOutputStream(os);
0542:
0543:                dos.writeInt(ClassFile.CLASS_FILE_MAGIC); // magic
0544:                dos.writeShort(this .minorVersion); // minor_version
0545:                dos.writeShort(this .majorVersion); // major_version
0546:                ClassFile.storeConstantPool(dos, this .constantPool); // constant_pool_count, constant_pool
0547:                dos.writeShort(this .accessFlags); // access_flags
0548:                dos.writeShort(this .this Class); // this_class
0549:                dos.writeShort(this .super class); // super_class
0550:                ClassFile.storeShortArray(dos, this .interfaces); // interfaces_count, interfaces
0551:                ClassFile.storeFields(dos, this .fieldInfos); // fields_count, fields
0552:                ClassFile.storeMethods(dos, this .methodInfos); // methods_count, methods
0553:                ClassFile.storeAttributes(dos, this .attributes); // attributes_count, attributes
0554:            }
0555:
0556:            /**
0557:             * u2 constant_pool_count, constant_pool[constant_pool_count - 1]
0558:             */
0559:            private static void storeConstantPool(DataOutputStream dos,
0560:                    List constantPool) throws IOException {
0561:                dos.writeShort(constantPool.size());
0562:                for (int i = 1; i < constantPool.size(); ++i) {
0563:                    ConstantPoolInfo cpi = (ConstantPoolInfo) constantPool
0564:                            .get(i);
0565:                    if (cpi == null)
0566:                        continue; // (Double or Long CPI.)
0567:                    cpi.store(dos);
0568:                }
0569:            }
0570:
0571:            /**
0572:             * u2 count, u2[count]
0573:             */
0574:            private static void storeShortArray(DataOutputStream dos, short[] sa)
0575:                    throws IOException {
0576:                dos.writeShort(sa.length);
0577:                for (int i = 0; i < sa.length; ++i)
0578:                    dos.writeShort(sa[i]);
0579:            }
0580:
0581:            /**
0582:             * u2 fields_count, fields[fields_count]
0583:             */
0584:            private static void storeFields(DataOutputStream dos,
0585:                    List fieldInfos) throws IOException {
0586:                dos.writeShort(fieldInfos.size());
0587:                for (int i = 0; i < fieldInfos.size(); ++i)
0588:                    ((FieldInfo) fieldInfos.get(i)).store(dos);
0589:            }
0590:
0591:            /**
0592:             * u2 methods_count, methods[methods_count]
0593:             */
0594:            private static void storeMethods(DataOutputStream dos,
0595:                    List methodInfos) throws IOException {
0596:                dos.writeShort(methodInfos.size());
0597:                for (int i = 0; i < methodInfos.size(); ++i)
0598:                    ((MethodInfo) methodInfos.get(i)).store(dos);
0599:            }
0600:
0601:            /**
0602:             * u2 attributes_count, attributes[attributes_count]
0603:             */
0604:            private static void storeAttributes(DataOutputStream dos,
0605:                    List attributeInfos) throws IOException {
0606:                dos.writeShort(attributeInfos.size());
0607:                for (int i = 0; i < attributeInfos.size(); ++i)
0608:                    ((AttributeInfo) attributeInfos.get(i)).store(dos);
0609:            }
0610:
0611:            /**
0612:             * Construct the name of a resource that could contain the source code of
0613:             * the class with the given name.
0614:             * <p>
0615:             * Notice that member types are declared inside a different type, so the relevant source file
0616:             * is that of the outermost declaring class.
0617:             * 
0618:             * @param className Fully qualified class name, e.g. "pkg1.pkg2.Outer$Inner"
0619:             * @return the name of the resource, e.g. "pkg1/pkg2/Outer.java"
0620:             */
0621:            public static String getSourceResourceName(String className) {
0622:
0623:                // Strip nested type suffixes.
0624:                {
0625:                    int idx = className.lastIndexOf('.') + 1;
0626:                    idx = className.indexOf('$', idx);
0627:                    if (idx != -1)
0628:                        className = className.substring(0, idx);
0629:                }
0630:
0631:                return className.replace('.', '/') + ".java";
0632:            }
0633:
0634:            /**
0635:             * Construct the name of a resource that could contain the class file of the
0636:             * class with the given name.
0637:             * 
0638:             * @param className Fully qualified class name, e.g. "pkg1.pkg2.Outer$Inner"
0639:             * @return the name of the resource, e.g. "pkg1/pkg2/Outer$Inner.class"
0640:             */
0641:            public static String getClassFileResourceName(String className) {
0642:                return className.replace('.', '/') + ".class";
0643:            }
0644:
0645:            /**
0646:             * Return the byte code of this {@link ClassFile} as a byte array.
0647:             */
0648:            public byte[] toByteArray() {
0649:                ByteArrayOutputStream baos = new ByteArrayOutputStream();
0650:                try {
0651:                    this .store(baos);
0652:                } catch (IOException ex) {
0653:                    // ByteArrayOutputStream should never throw IOExceptions.
0654:                    throw new RuntimeException(ex.toString());
0655:                }
0656:                return baos.toByteArray();
0657:            }
0658:
0659:            private static final int CLASS_FILE_MAGIC = 0xcafebabe;
0660:
0661:            public final static short MAJOR_VERSION_JDK_1_1 = 45;
0662:            public final static short MINOR_VERSION_JDK_1_1 = 3;
0663:            public final static short MAJOR_VERSION_JDK_1_2 = 46;
0664:            public final static short MINOR_VERSION_JDK_1_2 = 0;
0665:            public final static short MAJOR_VERSION_JDK_1_3 = 47;
0666:            public final static short MINOR_VERSION_JDK_1_3 = 0;
0667:            public final static short MAJOR_VERSION_JDK_1_4 = 48;
0668:            public final static short MINOR_VERSION_JDK_1_4 = 0;
0669:            public final static short MAJOR_VERSION_JDK_1_5 = 49;
0670:            public final static short MINOR_VERSION_JDK_1_5 = 0;
0671:
0672:            private short majorVersion;
0673:            private short minorVersion;
0674:            public/*final*/List constantPool; // ConstantPoolInfo
0675:            public/*final*/short accessFlags;
0676:            public/*final*/short this Class;
0677:            public/*final*/short super class;
0678:            public/*final*/short[] interfaces;
0679:            public/*final*/List fieldInfos; // FieldInfo
0680:            public/*final*/List methodInfos; // MethodInfo
0681:            private/*final*/List attributes; // AttributeInfo
0682:
0683:            // Convenience.
0684:            private/*final*/Map constantPoolMap; // ConstantPoolInfo => Short
0685:
0686:            public static abstract class ConstantPoolInfo {
0687:                abstract public void store(DataOutputStream dos)
0688:                        throws IOException;
0689:
0690:                abstract public boolean isWide();
0691:
0692:                private static ConstantPoolInfo loadConstantPoolInfo(
0693:                        DataInputStream dis) throws IOException {
0694:                    byte tag = dis.readByte();
0695:                    //System.out.println("tag=" + tag);
0696:                    switch (tag) {
0697:
0698:                    case 7:
0699:                        return new ConstantClassInfo(dis.readShort());
0700:
0701:                    case 9:
0702:                        return new ConstantFieldrefInfo(dis.readShort(), dis
0703:                                .readShort());
0704:
0705:                    case 10:
0706:                        return new ConstantMethodrefInfo(dis.readShort(), dis
0707:                                .readShort());
0708:
0709:                    case 11:
0710:                        return new ConstantInterfaceMethodrefInfo(dis
0711:                                .readShort(), dis.readShort());
0712:
0713:                    case 8:
0714:                        return new ConstantStringInfo(dis.readShort());
0715:
0716:                    case 3:
0717:                        return new ConstantIntegerInfo(dis.readInt());
0718:
0719:                    case 4:
0720:                        return new ConstantFloatInfo(dis.readFloat());
0721:
0722:                    case 5:
0723:                        return new ConstantLongInfo(dis.readLong());
0724:
0725:                    case 6:
0726:                        return new ConstantDoubleInfo(dis.readDouble());
0727:
0728:                    case 12:
0729:                        return new ConstantNameAndTypeInfo(dis.readShort(), dis
0730:                                .readShort());
0731:
0732:                    case 1:
0733:                        return new ConstantUtf8Info(dis.readUTF());
0734:
0735:                    default:
0736:                        throw new ClassFormatError("Invalid constant pool tag "
0737:                                + tag);
0738:                    }
0739:                }
0740:            }
0741:
0742:            public static abstract class ConstantValuePoolInfo extends
0743:                    ConstantPoolInfo {
0744:                public abstract Object getValue(ClassFile classFile);
0745:            }
0746:
0747:            public static class ConstantClassInfo extends ConstantPoolInfo {
0748:                private final short nameIndex;
0749:
0750:                public ConstantClassInfo(short nameIndex) {
0751:                    this .nameIndex = nameIndex;
0752:                }
0753:
0754:                // Implement ConstantPoolInfo.
0755:                public boolean isWide() {
0756:                    return false;
0757:                }
0758:
0759:                public void store(DataOutputStream dos) throws IOException {
0760:                    dos.writeByte(7);
0761:                    dos.writeShort(this .nameIndex);
0762:                }
0763:
0764:                public boolean equals(Object o) {
0765:                    return o instanceof  ConstantClassInfo
0766:                            && ((ConstantClassInfo) o).nameIndex == this .nameIndex;
0767:                }
0768:
0769:                public int hashCode() {
0770:                    return this .nameIndex;
0771:                }
0772:            }
0773:
0774:            public static class ConstantFieldrefInfo extends ConstantPoolInfo {
0775:                private final short classIndex;
0776:                private final short nameAndTypeIndex;
0777:
0778:                public ConstantFieldrefInfo(short classIndex,
0779:                        short nameAndTypeIndex) {
0780:                    this .classIndex = classIndex;
0781:                    this .nameAndTypeIndex = nameAndTypeIndex;
0782:                }
0783:
0784:                public short getNameAndTypeIndex() {
0785:                    return this .nameAndTypeIndex;
0786:                }
0787:
0788:                // Implement ConstantPoolInfo.
0789:                public boolean isWide() {
0790:                    return false;
0791:                }
0792:
0793:                public void store(DataOutputStream dos) throws IOException {
0794:                    dos.writeByte(9);
0795:                    dos.writeShort(this .classIndex);
0796:                    dos.writeShort(this .nameAndTypeIndex);
0797:                }
0798:
0799:                public boolean equals(Object o) {
0800:                    return (o instanceof  ConstantFieldrefInfo
0801:                            && ((ConstantFieldrefInfo) o).classIndex == this .classIndex && ((ConstantFieldrefInfo) o).nameAndTypeIndex == this .nameAndTypeIndex);
0802:                }
0803:
0804:                public int hashCode() {
0805:                    return this .classIndex + (this .nameAndTypeIndex << 16);
0806:                }
0807:            }
0808:
0809:            public static class ConstantMethodrefInfo extends ConstantPoolInfo {
0810:                private final short classIndex;
0811:                private final short nameAndTypeIndex;
0812:
0813:                public ConstantMethodrefInfo(short classIndex,
0814:                        short nameAndTypeIndex) {
0815:                    this .classIndex = classIndex;
0816:                    this .nameAndTypeIndex = nameAndTypeIndex;
0817:                }
0818:
0819:                public short getNameAndTypeIndex() {
0820:                    return this .nameAndTypeIndex;
0821:                }
0822:
0823:                // Implement ConstantPoolInfo.
0824:                public boolean isWide() {
0825:                    return false;
0826:                }
0827:
0828:                public void store(DataOutputStream dos) throws IOException {
0829:                    dos.writeByte(10);
0830:                    dos.writeShort(this .classIndex);
0831:                    dos.writeShort(this .nameAndTypeIndex);
0832:                }
0833:
0834:                public boolean equals(Object o) {
0835:                    return (o instanceof  ConstantMethodrefInfo
0836:                            && ((ConstantMethodrefInfo) o).classIndex == this .classIndex && ((ConstantMethodrefInfo) o).nameAndTypeIndex == this .nameAndTypeIndex);
0837:                }
0838:
0839:                public int hashCode() {
0840:                    return this .classIndex + (this .nameAndTypeIndex << 16);
0841:                }
0842:            }
0843:
0844:            public static class ConstantInterfaceMethodrefInfo extends
0845:                    ConstantPoolInfo {
0846:                private final short classIndex;
0847:                private final short nameAndTypeIndex;
0848:
0849:                public ConstantInterfaceMethodrefInfo(short classIndex,
0850:                        short nameAndTypeIndex) {
0851:                    this .classIndex = classIndex;
0852:                    this .nameAndTypeIndex = nameAndTypeIndex;
0853:                }
0854:
0855:                public short getNameAndTypeIndex() {
0856:                    return this .nameAndTypeIndex;
0857:                }
0858:
0859:                // Implement ConstantPoolInfo.
0860:                public boolean isWide() {
0861:                    return false;
0862:                }
0863:
0864:                public void store(DataOutputStream dos) throws IOException {
0865:                    dos.writeByte(11);
0866:                    dos.writeShort(this .classIndex);
0867:                    dos.writeShort(this .nameAndTypeIndex);
0868:                }
0869:
0870:                public boolean equals(Object o) {
0871:                    return (o instanceof  ConstantInterfaceMethodrefInfo
0872:                            && ((ConstantInterfaceMethodrefInfo) o).classIndex == this .classIndex && ((ConstantInterfaceMethodrefInfo) o).nameAndTypeIndex == this .nameAndTypeIndex);
0873:                }
0874:
0875:                public int hashCode() {
0876:                    return this .classIndex + (this .nameAndTypeIndex << 16);
0877:                }
0878:            }
0879:
0880:            static class ConstantStringInfo extends ConstantValuePoolInfo {
0881:                private final short stringIndex;
0882:
0883:                public ConstantStringInfo(short stringIndex) {
0884:                    this .stringIndex = stringIndex;
0885:                }
0886:
0887:                // Implement ConstantValuePoolInfo.
0888:                public Object getValue(ClassFile classFile) {
0889:                    return classFile.getConstantUtf8(this .stringIndex);
0890:                }
0891:
0892:                // Implement ConstantPoolInfo.
0893:                public boolean isWide() {
0894:                    return false;
0895:                }
0896:
0897:                public void store(DataOutputStream dos) throws IOException {
0898:                    dos.writeByte(8);
0899:                    dos.writeShort(this .stringIndex);
0900:                }
0901:
0902:                public boolean equals(Object o) {
0903:                    return o instanceof  ConstantStringInfo
0904:                            && ((ConstantStringInfo) o).stringIndex == this .stringIndex;
0905:                }
0906:
0907:                public int hashCode() {
0908:                    return this .stringIndex;
0909:                }
0910:            }
0911:
0912:            private static class ConstantIntegerInfo extends
0913:                    ConstantValuePoolInfo {
0914:                private final int value;
0915:
0916:                public ConstantIntegerInfo(int value) {
0917:                    this .value = value;
0918:                }
0919:
0920:                // Implement ConstantValuePoolInfo.
0921:                public Object getValue(ClassFile classFile) {
0922:                    return new Integer(this .value);
0923:                }
0924:
0925:                // Implement ConstantPoolInfo.
0926:                public boolean isWide() {
0927:                    return false;
0928:                }
0929:
0930:                public void store(DataOutputStream dos) throws IOException {
0931:                    dos.writeByte(3);
0932:                    dos.writeInt(this .value);
0933:                }
0934:
0935:                public boolean equals(Object o) {
0936:                    return o instanceof  ConstantIntegerInfo
0937:                            && ((ConstantIntegerInfo) o).value == this .value;
0938:                }
0939:
0940:                public int hashCode() {
0941:                    return this .value;
0942:                }
0943:            }
0944:
0945:            private static class ConstantFloatInfo extends
0946:                    ConstantValuePoolInfo {
0947:                private final float value;
0948:
0949:                public ConstantFloatInfo(float value) {
0950:                    this .value = value;
0951:                }
0952:
0953:                // Implement ConstantValuePoolInfo.
0954:                public Object getValue(ClassFile classFile) {
0955:                    return new Float(this .value);
0956:                }
0957:
0958:                // Implement ConstantPoolInfo.
0959:                public boolean isWide() {
0960:                    return false;
0961:                }
0962:
0963:                public void store(DataOutputStream dos) throws IOException {
0964:                    dos.writeByte(4);
0965:                    dos.writeFloat(this .value);
0966:                }
0967:
0968:                public boolean equals(Object o) {
0969:                    return o instanceof  ConstantFloatInfo
0970:                            && ((ConstantFloatInfo) o).value == this .value;
0971:                }
0972:
0973:                public int hashCode() {
0974:                    return Float.floatToIntBits(this .value);
0975:                }
0976:            }
0977:
0978:            private static class ConstantLongInfo extends ConstantValuePoolInfo {
0979:                private final long value;
0980:
0981:                public ConstantLongInfo(long value) {
0982:                    this .value = value;
0983:                }
0984:
0985:                // Implement ConstantValuePoolInfo.
0986:                public Object getValue(ClassFile classFile) {
0987:                    return new Long(this .value);
0988:                }
0989:
0990:                // Implement ConstantPoolInfo.
0991:                public boolean isWide() {
0992:                    return true;
0993:                }
0994:
0995:                public void store(DataOutputStream dos) throws IOException {
0996:                    dos.writeByte(5);
0997:                    dos.writeLong(this .value);
0998:                }
0999:
1000:                public boolean equals(Object o) {
1001:                    return o instanceof  ConstantLongInfo
1002:                            && ((ConstantLongInfo) o).value == this .value;
1003:                }
1004:
1005:                public int hashCode() {
1006:                    return (int) this .value ^ (int) (this .value >> 32);
1007:                }
1008:            }
1009:
1010:            private static class ConstantDoubleInfo extends
1011:                    ConstantValuePoolInfo {
1012:                private final double value;
1013:
1014:                public ConstantDoubleInfo(double value) {
1015:                    this .value = value;
1016:                }
1017:
1018:                // Implement ConstantValuePoolInfo.
1019:                public Object getValue(ClassFile classFile) {
1020:                    return new Double(this .value);
1021:                }
1022:
1023:                // Implement ConstantPoolInfo.
1024:                public boolean isWide() {
1025:                    return true;
1026:                }
1027:
1028:                public void store(DataOutputStream dos) throws IOException {
1029:                    dos.writeByte(6);
1030:                    dos.writeDouble(this .value);
1031:                }
1032:
1033:                public boolean equals(Object o) {
1034:                    return o instanceof  ConstantDoubleInfo
1035:                            && ((ConstantDoubleInfo) o).value == this .value;
1036:                }
1037:
1038:                public int hashCode() {
1039:                    long bits = Double.doubleToLongBits(this .value);
1040:                    return (int) bits ^ (int) (bits >> 32);
1041:                }
1042:            }
1043:
1044:            public static class ConstantNameAndTypeInfo extends
1045:                    ConstantPoolInfo {
1046:                private final short nameIndex;
1047:                private final short descriptorIndex;
1048:
1049:                public ConstantNameAndTypeInfo(short nameIndex,
1050:                        short descriptorIndex) {
1051:                    this .nameIndex = nameIndex;
1052:                    this .descriptorIndex = descriptorIndex;
1053:                }
1054:
1055:                public short getDescriptorIndex() {
1056:                    return this .descriptorIndex;
1057:                }
1058:
1059:                // Implement ConstantPoolInfo.
1060:                public boolean isWide() {
1061:                    return false;
1062:                }
1063:
1064:                public void store(DataOutputStream dos) throws IOException {
1065:                    dos.writeByte(12);
1066:                    dos.writeShort(this .nameIndex);
1067:                    dos.writeShort(this .descriptorIndex);
1068:                }
1069:
1070:                public boolean equals(Object o) {
1071:                    return (o instanceof  ConstantNameAndTypeInfo
1072:                            && ((ConstantNameAndTypeInfo) o).nameIndex == this .nameIndex && ((ConstantNameAndTypeInfo) o).descriptorIndex == this .descriptorIndex);
1073:                }
1074:
1075:                public int hashCode() {
1076:                    return this .nameIndex + (this .descriptorIndex << 16);
1077:                }
1078:            }
1079:
1080:            public static class ConstantUtf8Info extends ConstantPoolInfo {
1081:                private final String s;
1082:
1083:                public ConstantUtf8Info(String s) {
1084:                    if (s == null)
1085:                        throw new RuntimeException();
1086:                    this .s = s;
1087:                }
1088:
1089:                public String getString() {
1090:                    return this .s;
1091:                }
1092:
1093:                // Implement ConstantPoolInfo.
1094:                public boolean isWide() {
1095:                    return false;
1096:                }
1097:
1098:                public void store(DataOutputStream dos) throws IOException {
1099:                    dos.writeByte(1);
1100:                    try {
1101:                        dos.writeUTF(this .s);
1102:                    } catch (UTFDataFormatException e) {
1103:                        throw new ClassFormatError(
1104:                                "String constant too long to store in class file");
1105:                    }
1106:                }
1107:
1108:                public boolean equals(Object o) {
1109:                    return o instanceof  ConstantUtf8Info
1110:                            && ((ConstantUtf8Info) o).s.equals(this .s);
1111:                }
1112:
1113:                public int hashCode() {
1114:                    return this .s.hashCode();
1115:                }
1116:            }
1117:
1118:            /**
1119:             * This class represents a "method_info" structure, as defined by the
1120:             * JVM specification.
1121:             */
1122:            public class MethodInfo {
1123:                private final short accessFlags;
1124:                private final short nameIndex;
1125:                private final short descriptorIndex;
1126:                private final List attributes; // AttributeInfo
1127:
1128:                /**
1129:                 * Initialize the "method_info" structure.
1130:                 */
1131:                public MethodInfo(short accessFlags, short nameIndex,
1132:                        short descriptorIndex, List attributes) {
1133:                    this .accessFlags = accessFlags;
1134:                    this .nameIndex = nameIndex;
1135:                    this .descriptorIndex = descriptorIndex;
1136:                    this .attributes = attributes;
1137:                }
1138:
1139:                public ClassFile getClassFile() {
1140:                    return ClassFile.this ;
1141:                }
1142:
1143:                public short getAccessFlags() {
1144:                    return this .accessFlags;
1145:                }
1146:
1147:                public short getNameIndex() {
1148:                    return this .nameIndex;
1149:                }
1150:
1151:                public short getDescriptorIndex() {
1152:                    return this .descriptorIndex;
1153:                }
1154:
1155:                public AttributeInfo[] getAttributes() {
1156:                    return (AttributeInfo[]) this .attributes
1157:                            .toArray(new AttributeInfo[this .attributes.size()]);
1158:                }
1159:
1160:                public void addAttribute(AttributeInfo attribute) {
1161:                    this .attributes.add(attribute);
1162:                }
1163:
1164:                /**
1165:                 * Write this object to a {@link DataOutputStream}, in the format
1166:                 * defined by the JVM specification.
1167:                 */
1168:                public void store(DataOutputStream dos) throws IOException {
1169:                    dos.writeShort(this .accessFlags); // access_flags
1170:                    dos.writeShort(this .nameIndex); // name_index
1171:                    dos.writeShort(this .descriptorIndex); // descriptor_index
1172:                    ClassFile.storeAttributes(dos, this .attributes); // attributes_count, attributes
1173:                }
1174:            }
1175:
1176:            private MethodInfo loadMethodInfo(DataInputStream dis)
1177:                    throws IOException {
1178:                return new MethodInfo(dis.readShort(), // accessFlags
1179:                        dis.readShort(), // nameIndex
1180:                        dis.readShort(), // descriptorIndex
1181:                        this .loadAttributes(dis) // attributes
1182:                );
1183:            }
1184:
1185:            public static class FieldInfo {
1186:                public FieldInfo(short accessFlags, short nameIndex,
1187:                        short descriptorIndex, List attributes) {
1188:                    this .accessFlags = accessFlags;
1189:                    this .nameIndex = nameIndex;
1190:                    this .descriptorIndex = descriptorIndex;
1191:                    this .attributes = attributes;
1192:                }
1193:
1194:                public short getAccessFlags() {
1195:                    return this .accessFlags;
1196:                }
1197:
1198:                public short getNameIndex() {
1199:                    return this .nameIndex;
1200:                }
1201:
1202:                public short getDescriptorIndex() {
1203:                    return this .descriptorIndex;
1204:                }
1205:
1206:                public AttributeInfo[] getAttributes() {
1207:                    return (AttributeInfo[]) this .attributes
1208:                            .toArray(new AttributeInfo[this .attributes.size()]);
1209:                }
1210:
1211:                public void addAttribute(AttributeInfo attribute) {
1212:                    this .attributes.add(attribute);
1213:                }
1214:
1215:                public void store(DataOutputStream dos) throws IOException {
1216:                    dos.writeShort(this .accessFlags); // access_flags
1217:                    dos.writeShort(this .nameIndex); // name_index
1218:                    dos.writeShort(this .descriptorIndex); // descriptor_index
1219:                    ClassFile.storeAttributes(dos, this .attributes); // attibutes_count, attributes
1220:                }
1221:
1222:                private final short accessFlags;
1223:                private final short nameIndex;
1224:                private final short descriptorIndex;
1225:                private final List attributes; // AttributeInfo
1226:            }
1227:
1228:            /**
1229:             * Representation of a class file attribute (see JVMS 4.7).
1230:             */
1231:            public abstract static class AttributeInfo {
1232:                public AttributeInfo(short nameIndex) {
1233:                    this .nameIndex = nameIndex;
1234:                }
1235:
1236:                public void store(DataOutputStream dos) throws IOException {
1237:                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
1238:                    this .storeBody(new DataOutputStream(baos));
1239:
1240:                    dos.writeShort(this .nameIndex); // attribute_name_index;
1241:                    dos.writeInt(baos.size()); // attribute_length
1242:                    baos.writeTo(dos); // info
1243:                }
1244:
1245:                protected abstract void storeBody(DataOutputStream dos)
1246:                        throws IOException;
1247:
1248:                private final short nameIndex;
1249:            }
1250:
1251:            /**
1252:             * Load one class file attribute. The returned object will be of
1253:             * {@link AttributeInfo}-derived type, depending on the attribute's name; e.g. if the
1254:             * name of the attribute is "SourceFile", then the returned object will be of type
1255:             * {@link SourceFileAttribute}.
1256:             */
1257:            private AttributeInfo loadAttribute(DataInputStream dis)
1258:                    throws IOException {
1259:                short attributeNameIndex = dis.readShort(); // attribute_name_index
1260:                int attributeLength = dis.readInt(); // attribute_length
1261:
1262:                final byte[] ba = new byte[attributeLength];
1263:                dis.readFully(ba);
1264:                ByteArrayInputStream bais = new ByteArrayInputStream(ba);
1265:                DataInputStream bdis = new DataInputStream(bais);
1266:
1267:                String attributeName = this .getConstantUtf8(attributeNameIndex);
1268:                AttributeInfo result;
1269:                if ("ConstantValue".equals(attributeName)) {
1270:                    result = ConstantValueAttribute.loadBody(
1271:                            attributeNameIndex, bdis);
1272:                } else if ("Code".equals(attributeName)) {
1273:                    result = CodeAttribute.loadBody(attributeNameIndex, this ,
1274:                            bdis);
1275:                } else if ("Exceptions".equals(attributeName)) {
1276:                    result = ExceptionsAttribute.loadBody(attributeNameIndex,
1277:                            bdis);
1278:                } else if ("InnerClasses".equals(attributeName)) {
1279:                    result = InnerClassesAttribute.loadBody(attributeNameIndex,
1280:                            bdis);
1281:                } else if ("Synthetic".equals(attributeName)) {
1282:                    result = SyntheticAttribute.loadBody(attributeNameIndex,
1283:                            bdis);
1284:                } else if ("SourceFile".equals(attributeName)) {
1285:                    result = SourceFileAttribute.loadBody(attributeNameIndex,
1286:                            bdis);
1287:                } else if ("LineNumberTable".equals(attributeName)) {
1288:                    result = LineNumberTableAttribute.loadBody(
1289:                            attributeNameIndex, bdis);
1290:                } else if ("LocalVariableTable".equals(attributeName)) {
1291:                    result = LocalVariableTableAttribute.loadBody(
1292:                            attributeNameIndex, bdis);
1293:                } else if ("Deprecated".equals(attributeName)) {
1294:                    result = DeprecatedAttribute.loadBody(attributeNameIndex,
1295:                            bdis);
1296:                } else {
1297:                    return new AttributeInfo(attributeNameIndex) {
1298:                        protected void storeBody(DataOutputStream dos)
1299:                                throws IOException {
1300:                            dos.write(ba);
1301:                        }
1302:                    };
1303:                }
1304:
1305:                if (bais.available() > 0)
1306:                    throw new ClassFormatError(
1307:                            (ba.length - bais.available())
1308:                                    + " bytes of trailing garbage in body of attribute \""
1309:                                    + attributeName + "\"");
1310:
1311:                return result;
1312:            }
1313:
1314:            /**
1315:             * Representation of a "ConstantValue" attribute (see JVMS 4.7.2).
1316:             */
1317:            public static class ConstantValueAttribute extends AttributeInfo {
1318:                private final short constantValueIndex;
1319:
1320:                ConstantValueAttribute(short attributeNameIndex,
1321:                        short constantValueIndex) {
1322:                    super (attributeNameIndex);
1323:                    this .constantValueIndex = constantValueIndex;
1324:                }
1325:
1326:                public short getConstantValueIndex() {
1327:                    return this .constantValueIndex;
1328:                }
1329:
1330:                private static AttributeInfo loadBody(short attributeNameIndex,
1331:                        DataInputStream dis) throws IOException {
1332:                    return new ConstantValueAttribute(attributeNameIndex, // attributeNameIndex
1333:                            dis.readShort() // constantValueIndex
1334:                    );
1335:                }
1336:
1337:                // Implement "AttributeInfo".
1338:                protected void storeBody(DataOutputStream dos)
1339:                        throws IOException {
1340:                    dos.writeShort(this .constantValueIndex);
1341:                }
1342:            }
1343:
1344:            /**
1345:             * Representation of an "Exceptions" attribute (see JVMS 4.7.4).
1346:             */
1347:            public static class ExceptionsAttribute extends AttributeInfo {
1348:                private final short[] exceptionIndexes;
1349:
1350:                public ExceptionsAttribute(short attributeNameIndex,
1351:                        short[] exceptionIndexes) {
1352:                    super (attributeNameIndex);
1353:                    this .exceptionIndexes = exceptionIndexes;
1354:                }
1355:
1356:                public short[] getExceptionIndexes() {
1357:                    short[] eis = new short[this .exceptionIndexes.length];
1358:                    System.arraycopy(this .exceptionIndexes, 0, eis, 0,
1359:                            eis.length);
1360:                    return eis;
1361:                }
1362:
1363:                private static AttributeInfo loadBody(short attributeNameIndex,
1364:                        DataInputStream dis) throws IOException {
1365:                    return new ExceptionsAttribute(attributeNameIndex, // attributeNameIndex
1366:                            ClassFile.readShortArray(dis) // exceptionIndexes
1367:                    );
1368:                }
1369:
1370:                // Implement "AttributeInfo".
1371:                protected void storeBody(DataOutputStream dos)
1372:                        throws IOException {
1373:                    ClassFile.storeShortArray(dos, this .exceptionIndexes);
1374:                }
1375:            }
1376:
1377:            /**
1378:             * Representation of an "InnerClasses" attribute (see JVMS 4.7.5).
1379:             */
1380:            public static class InnerClassesAttribute extends AttributeInfo {
1381:                private final List entries; // InnerClassesAttribute.Entry
1382:
1383:                InnerClassesAttribute(short attributeNameIndex) {
1384:                    super (attributeNameIndex);
1385:                    this .entries = new ArrayList();
1386:                }
1387:
1388:                InnerClassesAttribute(short attributeNameIndex, Entry[] entries) {
1389:                    super (attributeNameIndex);
1390:                    this .entries = new ArrayList(Arrays.asList(entries));
1391:                }
1392:
1393:                public List getEntries() {
1394:                    return this .entries;
1395:                }
1396:
1397:                private static AttributeInfo loadBody(short attributeNameIndex,
1398:                        DataInputStream dis) throws IOException {
1399:                    Entry[] ics = new Entry[dis.readShort()]; // number_of_classes
1400:                    for (short i = 0; i < ics.length; ++i) { // classes
1401:                        ics[i] = new InnerClassesAttribute.Entry(dis
1402:                                .readShort(), // innerClassInfoIndex
1403:                                dis.readShort(), // outerClassInfoIndex
1404:                                dis.readShort(), // innerNameIndex
1405:                                dis.readShort() // innerClassAccessFlags
1406:                        );
1407:                    }
1408:                    return new InnerClassesAttribute(attributeNameIndex, ics);
1409:                }
1410:
1411:                // Implement "AttributeInfo".
1412:                protected void storeBody(DataOutputStream dos)
1413:                        throws IOException {
1414:                    dos.writeShort(this .entries.size());
1415:                    for (Iterator it = this .entries.iterator(); it.hasNext();) {
1416:                        Entry e = (Entry) it.next();
1417:                        dos.writeShort(e.innerClassInfoIndex);
1418:                        dos.writeShort(e.outerClassInfoIndex);
1419:                        dos.writeShort(e.innerNameIndex);
1420:                        dos.writeShort(e.innerClassAccessFlags);
1421:                    }
1422:                }
1423:
1424:                public static class Entry {
1425:                    public final short innerClassInfoIndex,
1426:                            outerClassInfoIndex, innerNameIndex,
1427:                            innerClassAccessFlags;
1428:
1429:                    public Entry(short innerClassInfoIndex,
1430:                            short outerClassInfoIndex, short innerNameIndex,
1431:                            short innerClassAccessFlags) {
1432:                        this .innerClassInfoIndex = innerClassInfoIndex;
1433:                        this .outerClassInfoIndex = outerClassInfoIndex;
1434:                        this .innerNameIndex = innerNameIndex;
1435:                        this .innerClassAccessFlags = innerClassAccessFlags;
1436:                    }
1437:                }
1438:            }
1439:
1440:            /**
1441:             * Representation of a "Synthetic" attribute (see JVMS 4.7.6).
1442:             */
1443:            public static class SyntheticAttribute extends AttributeInfo {
1444:                SyntheticAttribute(short attributeNameIndex) {
1445:                    super (attributeNameIndex);
1446:                }
1447:
1448:                private static AttributeInfo loadBody(short attributeNameIndex,
1449:                        DataInputStream dis) {
1450:                    return new SyntheticAttribute(attributeNameIndex // attributeNameIndex
1451:                    );
1452:                }
1453:
1454:                // Implement "AttributeInfo".
1455:                protected void storeBody(DataOutputStream dos)
1456:                        throws IOException {
1457:                }
1458:            }
1459:
1460:            /**
1461:             * Representation of a "SourceFile" attribute (see JVMS 4.7.7).
1462:             */
1463:            public static class SourceFileAttribute extends AttributeInfo {
1464:                private final short sourceFileIndex;
1465:
1466:                public SourceFileAttribute(short attributeNameIndex,
1467:                        short sourceFileIndex) {
1468:                    super (attributeNameIndex);
1469:                    this .sourceFileIndex = sourceFileIndex;
1470:                }
1471:
1472:                private static AttributeInfo loadBody(short attributeNameIndex,
1473:                        DataInputStream dis) throws IOException {
1474:                    return new SourceFileAttribute(attributeNameIndex, // attributeNameIndex
1475:                            dis.readShort() // sourceFileNameIndex
1476:                    );
1477:                }
1478:
1479:                // Implement "AttributeInfo".
1480:                protected void storeBody(DataOutputStream dos)
1481:                        throws IOException {
1482:                    dos.writeShort(this .sourceFileIndex);
1483:                }
1484:            }
1485:
1486:            /**
1487:             * Representation of a "LineNumberTable" attribute (see JVMS 4.7.8).
1488:             */
1489:            public static class LineNumberTableAttribute extends AttributeInfo {
1490:                private final Entry[] entries;
1491:
1492:                public LineNumberTableAttribute(short attributeNameIndex,
1493:                        Entry[] entries) {
1494:                    super (attributeNameIndex);
1495:                    this .entries = entries;
1496:                }
1497:
1498:                private static AttributeInfo loadBody(short attributeNameIndex,
1499:                        DataInputStream dis) throws IOException {
1500:                    Entry[] lntes = new Entry[dis.readShort()]; // line_number_table_length
1501:                    for (short i = 0; i < lntes.length; ++i) { // line_number_table
1502:                        lntes[i] = new LineNumberTableAttribute.Entry(dis
1503:                                .readShort(), // startPC
1504:                                dis.readShort() // lineNumber
1505:                        );
1506:                    }
1507:                    return new LineNumberTableAttribute(attributeNameIndex,
1508:                            lntes);
1509:                }
1510:
1511:                // Implement "AttributeInfo".
1512:                protected void storeBody(DataOutputStream dos)
1513:                        throws IOException {
1514:                    dos.writeShort(this .entries.length); // line_number_table_length
1515:                    for (int i = 0; i < this .entries.length; ++i) {
1516:                        dos.writeShort(this .entries[i].startPC);
1517:                        dos.writeShort(this .entries[i].lineNumber);
1518:                    }
1519:                }
1520:
1521:                public static class Entry {
1522:                    public final short startPC, lineNumber;
1523:
1524:                    public Entry(short startPC, short lineNumber) {
1525:                        this .startPC = startPC;
1526:                        this .lineNumber = lineNumber;
1527:                    }
1528:                }
1529:            }
1530:
1531:            /**
1532:             * Representation of a "LocalVariableTable" attribute (see JVMS 4.7.9).
1533:             */
1534:            public static class LocalVariableTableAttribute extends
1535:                    AttributeInfo {
1536:                private final Entry[] entries;
1537:
1538:                LocalVariableTableAttribute(short attributeNameIndex,
1539:                        Entry[] entries) {
1540:                    super (attributeNameIndex);
1541:                    this .entries = entries;
1542:                }
1543:
1544:                private static AttributeInfo loadBody(short attributeNameIndex,
1545:                        DataInputStream dis) throws IOException {
1546:                    short localVariableTableLength = dis.readShort();
1547:                    Entry[] lvtes = new Entry[localVariableTableLength]; // local_variable_table_length
1548:                    for (short i = 0; i < localVariableTableLength; ++i) { // local_variable_table
1549:                        lvtes[i] = new LocalVariableTableAttribute.Entry(dis
1550:                                .readShort(), // startPC
1551:                                dis.readShort(), // length
1552:                                dis.readShort(), // nameIndex
1553:                                dis.readShort(), // descriptorIndex
1554:                                dis.readShort() // index
1555:                        );
1556:                    }
1557:                    return new LocalVariableTableAttribute(attributeNameIndex,
1558:                            lvtes);
1559:                }
1560:
1561:                // Implement "AttributeInfo".
1562:                protected void storeBody(DataOutputStream dos)
1563:                        throws IOException {
1564:                    dos.writeShort(this .entries.length); // local_variable_table_length
1565:                    for (int i = 0; i < this .entries.length; ++i) { // local_variable_table
1566:                        Entry lnte = this .entries[i];
1567:                        dos.writeShort(lnte.startPC); // start_pc;
1568:                        dos.writeShort(lnte.length); // length
1569:                        dos.writeShort(lnte.nameIndex); // name_index
1570:                        dos.writeShort(lnte.descriptorIndex); // descriptor_index
1571:                        dos.writeShort(lnte.index); // index
1572:                    }
1573:                }
1574:
1575:                public static class Entry {
1576:                    public final short startPC, length, nameIndex,
1577:                            descriptorIndex, index;
1578:
1579:                    public Entry(short startPC, short length, short nameIndex,
1580:                            short descriptorIndex, short index) {
1581:                        this .startPC = startPC;
1582:                        this .length = length;
1583:                        this .nameIndex = nameIndex;
1584:                        this .descriptorIndex = descriptorIndex;
1585:                        this .index = index;
1586:                    }
1587:                }
1588:            }
1589:
1590:            /**
1591:             * Representation of a "Deprecated" attribute (see JVMS 4.7.10).
1592:             */
1593:            public static class DeprecatedAttribute extends AttributeInfo {
1594:                public DeprecatedAttribute(short attributeNameIndex) {
1595:                    super (attributeNameIndex);
1596:                }
1597:
1598:                private static AttributeInfo loadBody(short attributeNameIndex,
1599:                        DataInputStream dis) {
1600:                    return new DeprecatedAttribute(attributeNameIndex);
1601:                }
1602:
1603:                // Implement "AttributeInfo".
1604:                protected void storeBody(DataOutputStream dos)
1605:                        throws IOException {
1606:                }
1607:            }
1608:
1609:            /**
1610:             * Representation of an unmodifiable "Code" attribute, as read from a class file.
1611:             */
1612:            private static class CodeAttribute extends AttributeInfo {
1613:                private final short maxStack;
1614:                private final short maxLocals;
1615:                private final byte[] code;
1616:                private final ExceptionTableEntry[] exceptionTableEntries;
1617:                private final AttributeInfo[] attributes;
1618:
1619:                private CodeAttribute(short attributeNameIndex, short maxStack,
1620:                        short maxLocals, byte[] code,
1621:                        ExceptionTableEntry[] exceptionTableEntries,
1622:                        AttributeInfo[] attributes) {
1623:                    super (attributeNameIndex);
1624:                    this .maxStack = maxStack;
1625:                    this .maxLocals = maxLocals;
1626:                    this .code = code;
1627:                    this .exceptionTableEntries = exceptionTableEntries;
1628:                    this .attributes = attributes;
1629:                }
1630:
1631:                public static AttributeInfo loadBody(short attributeNameIndex,
1632:                        ClassFile classFile, DataInputStream dis)
1633:                        throws IOException {
1634:                    short maxStack = dis.readShort(); // max_stack
1635:                    short maxLocals = dis.readShort(); // max_locals
1636:                    byte[] code = ClassFile.readLengthAndBytes(dis); // code_length, code
1637:
1638:                    ExceptionTableEntry[] etes = new ExceptionTableEntry[dis
1639:                            .readShort()]; // exception_table_length
1640:                    for (int i = 0; i < etes.length; ++i) { // exception_table
1641:                        etes[i] = new ExceptionTableEntry(dis.readShort(), // startPC
1642:                                dis.readShort(), // endPC
1643:                                dis.readShort(), // handlerPC
1644:                                dis.readShort() // catchType
1645:                        );
1646:                    }
1647:
1648:                    AttributeInfo[] attributes = new AttributeInfo[dis
1649:                            .readShort()]; // attributes_count
1650:                    for (int i = 0; i < attributes.length; ++i) { // attributes
1651:                        attributes[i] = classFile.loadAttribute(dis);
1652:                    }
1653:
1654:                    return new CodeAttribute(attributeNameIndex, // attributeNameIndex
1655:                            maxStack, // maxStack
1656:                            maxLocals, // maxLocals
1657:                            code, // code
1658:                            etes, // exceptionTableEntries
1659:                            attributes // attributes
1660:                    );
1661:                }
1662:
1663:                protected void storeBody(DataOutputStream dos)
1664:                        throws IOException {
1665:                    dos.writeShort(this .maxStack); // max_stack
1666:                    dos.writeShort(this .maxLocals); // max_locals
1667:                    dos.writeInt(this .code.length); // code_length
1668:                    dos.write(this .code); // code
1669:                    dos.writeShort(this .exceptionTableEntries.length); // exception_table_length
1670:                    for (int i = 0; i < this .exceptionTableEntries.length; ++i) { // exception_table
1671:                        ExceptionTableEntry ete = this .exceptionTableEntries[i];
1672:                        dos.writeShort(ete.startPC); // start_pc
1673:                        dos.writeShort(ete.endPC); // end_pc
1674:                        dos.writeShort(ete.handlerPC); // handler_pc
1675:                        dos.writeShort(ete.catchType); // catch_type
1676:                    }
1677:                    dos.writeShort(this .attributes.length); // attributes_count
1678:                    for (int i = 0; i < this .attributes.length; ++i) { // attributes
1679:                        this .attributes[i].store(dos);
1680:                    }
1681:                }
1682:
1683:                /**
1684:                 * Representation of an entry in the "exception_table" of a "Code" attribute (see JVMS
1685:                 * 4.7.3).
1686:                 */
1687:                private static class ExceptionTableEntry {
1688:                    private final short startPC, endPC, handlerPC, catchType;
1689:
1690:                    public ExceptionTableEntry(short startPC, short endPC,
1691:                            short handlerPC, short catchType) {
1692:                        this.startPC = startPC;
1693:                        this.endPC = endPC;
1694:                        this.handlerPC = handlerPC;
1695:                        this.catchType = catchType;
1696:                    }
1697:                }
1698:            }
1699:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.