Source Code Cross Referenced for ClassFile.java in  » Byte-Code » Cojen » org » cojen » classfile » 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 » Byte Code » Cojen » org.cojen.classfile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Copyright 2004 Brian S O'Neill
0003:         *
0004:         *  Licensed under the Apache License, Version 2.0 (the "License");
0005:         *  you may not use this file except in compliance with the License.
0006:         *  You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         *  Unless required by applicable law or agreed to in writing, software
0011:         *  distributed under the License is distributed on an "AS IS" BASIS,
0012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         *  See the License for the specific language governing permissions and
0014:         *  limitations under the License.
0015:         */
0016:
0017:        package org.cojen.classfile;
0018:
0019:        import java.lang.reflect.Method;
0020:        import java.lang.reflect.Modifier;
0021:        import java.util.Set;
0022:        import java.util.HashSet;
0023:        import java.util.List;
0024:        import java.util.ArrayList;
0025:        import java.util.Map;
0026:        import java.util.HashMap;
0027:        import java.io.DataInput;
0028:        import java.io.DataInputStream;
0029:        import java.io.DataOutput;
0030:        import java.io.DataOutputStream;
0031:        import java.io.InputStream;
0032:        import java.io.IOException;
0033:        import java.io.OutputStream;
0034:        import org.cojen.classfile.attribute.Annotation;
0035:        import org.cojen.classfile.attribute.AnnotationsAttr;
0036:        import org.cojen.classfile.attribute.DeprecatedAttr;
0037:        import org.cojen.classfile.attribute.InnerClassesAttr;
0038:        import org.cojen.classfile.attribute.RuntimeInvisibleAnnotationsAttr;
0039:        import org.cojen.classfile.attribute.RuntimeVisibleAnnotationsAttr;
0040:        import org.cojen.classfile.attribute.SignatureAttr;
0041:        import org.cojen.classfile.attribute.SourceFileAttr;
0042:        import org.cojen.classfile.attribute.SyntheticAttr;
0043:        import org.cojen.classfile.constant.ConstantClassInfo;
0044:
0045:        /**
0046:         * A class used to create Java class files. Call the writeTo method
0047:         * to produce a class file.
0048:         *
0049:         * <p>See <i>The Java Virtual Machine Specification</i> (ISBN 0-201-63452-X)
0050:         * for information on how class files are structured. Section 4.1 describes
0051:         * the ClassFile structure.
0052:         * 
0053:         * @author Brian S O'Neill
0054:         */
0055:        public class ClassFile {
0056:            private static final int MAGIC = 0xCAFEBABE;
0057:
0058:            /**
0059:             * Reads a ClassFile from the given InputStream. With this method, inner
0060:             * classes cannot be loaded, and custom attributes cannot be defined.
0061:             *
0062:             * @param in source of class file data
0063:             * @throws IOException for I/O error or if classfile is invalid.
0064:             * @throws ArrayIndexOutOfBoundsException if a constant pool index is out
0065:             * of range.
0066:             * @throws ClassCastException if a constant pool index references the
0067:             * wrong type.
0068:             */
0069:            public static ClassFile readFrom(InputStream in) throws IOException {
0070:                return readFrom(in, null, null);
0071:            }
0072:
0073:            /**
0074:             * Reads a ClassFile from the given DataInput. With this method, inner
0075:             * classes cannot be loaded, and custom attributes cannot be defined.
0076:             *
0077:             * @param din source of class file data
0078:             * @throws IOException for I/O error or if classfile is invalid.
0079:             * @throws ArrayIndexOutOfBoundsException if a constant pool index is out
0080:             * of range.
0081:             * @throws ClassCastException if a constant pool index references the
0082:             * wrong type.
0083:             */
0084:            public static ClassFile readFrom(DataInput din) throws IOException {
0085:                return readFrom(din, null, null);
0086:            }
0087:
0088:            /**
0089:             * Reads a ClassFile from the given InputStream. A
0090:             * {@link ClassFileDataLoader} may be provided, which allows inner class
0091:             * definitions to be loaded. Also, an {@link AttributeFactory} may be
0092:             * provided, which allows non-standard attributes to be read. All
0093:             * remaining unknown attribute types are captured, but are not decoded.
0094:             *
0095:             * @param in source of class file data
0096:             * @param loader optional loader for reading inner class definitions
0097:             * @param attrFactory optional factory for reading custom attributes
0098:             * @throws IOException for I/O error or if classfile is invalid.
0099:             * @throws ArrayIndexOutOfBoundsException if a constant pool index is out
0100:             * of range.
0101:             * @throws ClassCastException if a constant pool index references the
0102:             * wrong type.
0103:             */
0104:            public static ClassFile readFrom(InputStream in,
0105:                    ClassFileDataLoader loader, AttributeFactory attrFactory)
0106:                    throws IOException {
0107:                if (!(in instanceof  DataInput)) {
0108:                    in = new DataInputStream(in);
0109:                }
0110:                return readFrom((DataInput) in, loader, attrFactory);
0111:            }
0112:
0113:            /**
0114:             * Reads a ClassFile from the given DataInput. A
0115:             * {@link ClassFileDataLoader} may be provided, which allows inner class
0116:             * definitions to be loaded. Also, an {@link AttributeFactory} may be
0117:             * provided, which allows non-standard attributes to be read. All
0118:             * remaining unknown attribute types are captured, but are not decoded.
0119:             *
0120:             * @param din source of class file data
0121:             * @param loader optional loader for reading inner class definitions
0122:             * @param attrFactory optional factory for reading custom attributes
0123:             * @throws IOException for I/O error or if classfile is invalid.
0124:             * @throws ArrayIndexOutOfBoundsException if a constant pool index is out
0125:             * of range.
0126:             * @throws ClassCastException if a constant pool index references the
0127:             * wrong type.
0128:             */
0129:            public static ClassFile readFrom(DataInput din,
0130:                    ClassFileDataLoader loader, AttributeFactory attrFactory)
0131:                    throws IOException {
0132:                return readFrom(din, loader, attrFactory, new HashMap(11), null);
0133:            }
0134:
0135:            /**
0136:             * @param loadedClassFiles Maps name to ClassFiles for classes already
0137:             * loaded. This prevents infinite loop: inner loads outer loads inner...
0138:             */
0139:            private static ClassFile readFrom(DataInput din,
0140:                    ClassFileDataLoader loader, AttributeFactory attrFactory,
0141:                    Map loadedClassFiles, ClassFile outerClass)
0142:                    throws IOException {
0143:                int magic = din.readInt();
0144:                if (magic != MAGIC) {
0145:                    throw new IOException("Incorrect magic number: 0x"
0146:                            + Integer.toHexString(magic));
0147:                }
0148:
0149:                short minor = din.readShort();
0150:                short major = din.readShort();
0151:
0152:                ConstantPool cp = ConstantPool.readFrom(din);
0153:                Modifiers modifiers = Modifiers.getInstance(
0154:                        din.readUnsignedShort()).toSynchronized(false);
0155:
0156:                int index = din.readUnsignedShort();
0157:                ConstantClassInfo this Class = (ConstantClassInfo) cp
0158:                        .getConstant(index);
0159:
0160:                index = din.readUnsignedShort();
0161:                ConstantClassInfo super Class = null;
0162:                if (index > 0) {
0163:                    super Class = (ConstantClassInfo) cp.getConstant(index);
0164:                }
0165:
0166:                ClassFile cf = new ClassFile(cp, modifiers, this Class,
0167:                        super Class, outerClass);
0168:                cf.setVersion(major, minor);
0169:                loadedClassFiles.put(cf.getClassName(), cf);
0170:
0171:                // Read interfaces.
0172:                int size = din.readUnsignedShort();
0173:                for (int i = 0; i < size; i++) {
0174:                    index = din.readUnsignedShort();
0175:                    ConstantClassInfo info = (ConstantClassInfo) cp
0176:                            .getConstant(index);
0177:                    cf.addInterface(info.getType().getRootName());
0178:                }
0179:
0180:                // Read fields.
0181:                size = din.readUnsignedShort();
0182:                for (int i = 0; i < size; i++) {
0183:                    cf.mFields.add(FieldInfo.readFrom(cf, din, attrFactory));
0184:                }
0185:
0186:                // Read methods.
0187:                size = din.readUnsignedShort();
0188:                for (int i = 0; i < size; i++) {
0189:                    cf.mMethods.add(MethodInfo.readFrom(cf, din, attrFactory));
0190:                }
0191:
0192:                // Read attributes.
0193:                size = din.readUnsignedShort();
0194:                for (int i = 0; i < size; i++) {
0195:                    Attribute attr = Attribute.readFrom(cp, din, attrFactory);
0196:                    cf.addAttribute(attr);
0197:                    if (attr instanceof  InnerClassesAttr) {
0198:                        cf.mInnerClassesAttr = (InnerClassesAttr) attr;
0199:                    }
0200:                }
0201:
0202:                // Load inner and outer classes.
0203:                if (cf.mInnerClassesAttr != null && loader != null) {
0204:                    InnerClassesAttr.Info[] infos = cf.mInnerClassesAttr
0205:                            .getInnerClassesInfo();
0206:                    for (int i = 0; i < infos.length; i++) {
0207:                        InnerClassesAttr.Info info = infos[i];
0208:
0209:                        if (this Class.equals(info.getInnerClass())) {
0210:                            // This class is an inner class.
0211:                            if (info.getInnerClassName() != null) {
0212:                                cf.mInnerClassName = info.getInnerClassName()
0213:                                        .getValue();
0214:                            }
0215:                            ConstantClassInfo outer = info.getOuterClass();
0216:                            if (cf.mOuterClass == null && outer != null) {
0217:                                cf.mOuterClass = readOuterClass(outer, loader,
0218:                                        attrFactory, loadedClassFiles);
0219:                            }
0220:                            Modifiers innerFlags = info.getModifiers();
0221:                            cf.mModifiers = cf.mModifiers.toStatic(
0222:                                    innerFlags.isStatic()).toPrivate(
0223:                                    innerFlags.isPrivate()).toProtected(
0224:                                    innerFlags.isProtected()).toPublic(
0225:                                    innerFlags.isPublic());
0226:                        } else if (info.getOuterClass() == null
0227:                                || this Class.equals(info.getOuterClass())) {
0228:
0229:                            // This class is an outer class.
0230:                            ConstantClassInfo inner = info.getInnerClass();
0231:                            if (inner != null) {
0232:                                ClassFile innerClass = readInnerClass(inner,
0233:                                        loader, attrFactory, loadedClassFiles,
0234:                                        cf);
0235:
0236:                                if (innerClass != null) {
0237:                                    if (innerClass.getInnerClassName() != null) {
0238:                                        innerClass.mInnerClassName = info
0239:                                                .getInnerClassName().getValue();
0240:                                    }
0241:                                    if (cf.mInnerClasses == null) {
0242:                                        cf.mInnerClasses = new ArrayList();
0243:                                    }
0244:                                    cf.mInnerClasses.add(innerClass);
0245:                                }
0246:                            }
0247:                        }
0248:                    }
0249:                }
0250:
0251:                return cf;
0252:            }
0253:
0254:            private static ClassFile readOuterClass(ConstantClassInfo outer,
0255:                    ClassFileDataLoader loader, AttributeFactory attrFactory,
0256:                    Map loadedClassFiles) throws IOException {
0257:                String name = outer.getType().getRootName();
0258:
0259:                ClassFile outerClass = (ClassFile) loadedClassFiles.get(name);
0260:                if (outerClass != null) {
0261:                    return outerClass;
0262:                }
0263:
0264:                InputStream in = loader.getClassData(name);
0265:                if (in == null) {
0266:                    return null;
0267:                }
0268:
0269:                if (!(in instanceof  DataInput)) {
0270:                    in = new DataInputStream(in);
0271:                }
0272:
0273:                return readFrom((DataInput) in, loader, attrFactory,
0274:                        loadedClassFiles, null);
0275:            }
0276:
0277:            private static ClassFile readInnerClass(ConstantClassInfo inner,
0278:                    ClassFileDataLoader loader, AttributeFactory attrFactory,
0279:                    Map loadedClassFiles, ClassFile outerClass)
0280:                    throws IOException {
0281:                String name = inner.getType().getRootName();
0282:
0283:                // Prevent cycles in inner class structure.
0284:                for (ClassFile outer = outerClass; outer != null; outer = outer
0285:                        .getOuterClass()) {
0286:                    if (name.equals(outer.getClassName())) {
0287:                        // Cycle prevented.
0288:                        return null;
0289:                    }
0290:                }
0291:
0292:                // Prevent classes from being loaded multiple times.
0293:                ClassFile innerClass = (ClassFile) loadedClassFiles.get(name);
0294:                if (innerClass != null) {
0295:                    return innerClass;
0296:                }
0297:
0298:                InputStream in = loader.getClassData(name);
0299:                if (in == null) {
0300:                    return null;
0301:                }
0302:
0303:                if (!(in instanceof  DataInput)) {
0304:                    in = new DataInputStream(in);
0305:                }
0306:
0307:                return readFrom((DataInput) in, loader, attrFactory,
0308:                        loadedClassFiles, outerClass);
0309:            }
0310:
0311:            private int mVersion;
0312:            private String mTarget;
0313:            {
0314:                setTarget(null);
0315:            }
0316:
0317:            private final String mClassName;
0318:            private final String mSuperClassName;
0319:            private String mInnerClassName;
0320:            private TypeDesc mType;
0321:
0322:            private ConstantPool mCp;
0323:
0324:            private Modifiers mModifiers;
0325:
0326:            private ConstantClassInfo mThisClass;
0327:            private ConstantClassInfo mSuperClass;
0328:
0329:            // Holds ConstantInfo objects.
0330:            private List mInterfaces = new ArrayList(2);
0331:            private Set mInterfaceSet = new HashSet(7);
0332:
0333:            // Holds objects.
0334:            private List mFields = new ArrayList();
0335:            private List mMethods = new ArrayList();
0336:            private List mAttributes = new ArrayList();
0337:
0338:            private SourceFileAttr mSource;
0339:
0340:            private List mInnerClasses;
0341:            private int mAnonymousInnerClassCount = 0;
0342:            private InnerClassesAttr mInnerClassesAttr;
0343:
0344:            // Is non-null for inner classes.
0345:            private ClassFile mOuterClass;
0346:
0347:            /** 
0348:             * By default, the ClassFile defines public, non-final, concrete classes.
0349:             * This constructor creates a ClassFile for a class that extends
0350:             * java.lang.Object.
0351:             * <p>
0352:             * Use the {@link #setModifiers} method to change the access modifiers of
0353:             * this class or to turn it into an interface.
0354:             *
0355:             * @param className Full class name of the form ex: "java.lang.String".
0356:             */
0357:            public ClassFile(String className) {
0358:                this (className, (String) null);
0359:            }
0360:
0361:            /** 
0362:             * By default, the ClassFile defines public, non-final, concrete classes.
0363:             * <p>
0364:             * Use the {@link #setModifiers} method to change the access modifiers of
0365:             * this class or to turn it into an interface.
0366:             *
0367:             * @param className Full class name of the form ex: "java.lang.String".
0368:             * @param superClass Super class or interface.
0369:             */
0370:            public ClassFile(String className, Class super Class) {
0371:                this (className, super Class.isInterface() ? null : super Class
0372:                        .getName());
0373:                if (super Class.isInterface()) {
0374:                    addInterface(super Class);
0375:                }
0376:            }
0377:
0378:            /** 
0379:             * By default, the ClassFile defines public, non-final, concrete classes.
0380:             * <p>
0381:             * Use the {@link #setModifiers} method to change the access modifiers of
0382:             * this class or to turn it into an interface.
0383:             *
0384:             * @param className Full class name of the form ex: "java.lang.String".
0385:             * @param superClassName Full super class name.
0386:             */
0387:            public ClassFile(String className, String super ClassName) {
0388:                if (super ClassName == null) {
0389:                    if (!className.equals(Object.class.getName())) {
0390:                        super ClassName = Object.class.getName();
0391:                    }
0392:                }
0393:
0394:                mCp = new ConstantPool();
0395:
0396:                // public, non-final, concrete class
0397:                mModifiers = Modifiers.PUBLIC;
0398:
0399:                mThisClass = mCp.addConstantClass(className);
0400:                mSuperClass = mCp.addConstantClass(super ClassName);
0401:
0402:                mClassName = className;
0403:                mSuperClassName = super ClassName;
0404:            }
0405:
0406:            /**
0407:             * Used to construct a ClassFile when read from a stream.
0408:             */
0409:            private ClassFile(ConstantPool cp, Modifiers modifiers,
0410:                    ConstantClassInfo this Class, ConstantClassInfo super Class,
0411:                    ClassFile outerClass) {
0412:
0413:                mCp = cp;
0414:
0415:                mModifiers = modifiers;
0416:
0417:                mThisClass = this Class;
0418:                mSuperClass = super Class;
0419:
0420:                mClassName = this Class.getType().getRootName();
0421:                if (super Class == null) {
0422:                    mSuperClassName = null;
0423:                } else {
0424:                    mSuperClassName = super Class.getType().getRootName();
0425:                }
0426:
0427:                mOuterClass = outerClass;
0428:            }
0429:
0430:            public String getClassName() {
0431:                return mClassName;
0432:            }
0433:
0434:            public String getSuperClassName() {
0435:                return mSuperClassName;
0436:            }
0437:
0438:            /**
0439:             * Returns a TypeDesc for the type of this ClassFile.
0440:             */
0441:            public TypeDesc getType() {
0442:                if (mType == null) {
0443:                    mType = TypeDesc.forClass(mClassName);
0444:                }
0445:                return mType;
0446:            }
0447:
0448:            public Modifiers getModifiers() {
0449:                return mModifiers;
0450:            }
0451:
0452:            /**
0453:             * Returns the names of all the interfaces that this class implements.
0454:             */
0455:            public String[] getInterfaces() {
0456:                int size = mInterfaces.size();
0457:                String[] names = new String[size];
0458:
0459:                for (int i = 0; i < size; i++) {
0460:                    names[i] = ((ConstantClassInfo) mInterfaces.get(i))
0461:                            .getType().getRootName();
0462:                }
0463:
0464:                return names;
0465:            }
0466:
0467:            /**
0468:             * Returns all the fields defined in this class.
0469:             */
0470:            public FieldInfo[] getFields() {
0471:                FieldInfo[] fields = new FieldInfo[mFields.size()];
0472:                return (FieldInfo[]) mFields.toArray(fields);
0473:            }
0474:
0475:            /**
0476:             * Returns all the methods defined in this class, not including
0477:             * constructors and static initializers.
0478:             */
0479:            public MethodInfo[] getMethods() {
0480:                int size = mMethods.size();
0481:                List methodsOnly = new ArrayList(size);
0482:
0483:                for (int i = 0; i < size; i++) {
0484:                    MethodInfo method = (MethodInfo) mMethods.get(i);
0485:                    String name = method.getName();
0486:                    if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
0487:                        methodsOnly.add(method);
0488:                    }
0489:                }
0490:
0491:                MethodInfo[] methodsArray = new MethodInfo[methodsOnly.size()];
0492:                return (MethodInfo[]) methodsOnly.toArray(methodsArray);
0493:            }
0494:
0495:            /**
0496:             * Returns all the constructors defined in this class.
0497:             */
0498:            public MethodInfo[] getConstructors() {
0499:                int size = mMethods.size();
0500:                List ctorsOnly = new ArrayList(size);
0501:
0502:                for (int i = 0; i < size; i++) {
0503:                    MethodInfo method = (MethodInfo) mMethods.get(i);
0504:                    if ("<init>".equals(method.getName())) {
0505:                        ctorsOnly.add(method);
0506:                    }
0507:                }
0508:
0509:                MethodInfo[] ctorsArray = new MethodInfo[ctorsOnly.size()];
0510:                return (MethodInfo[]) ctorsOnly.toArray(ctorsArray);
0511:            }
0512:
0513:            /**
0514:             * Returns the static initializer defined in this class or null if there
0515:             * isn't one.
0516:             */
0517:            public MethodInfo getInitializer() {
0518:                int size = mMethods.size();
0519:
0520:                for (int i = 0; i < size; i++) {
0521:                    MethodInfo method = (MethodInfo) mMethods.get(i);
0522:                    if ("<clinit>".equals(method.getName())) {
0523:                        return method;
0524:                    }
0525:                }
0526:
0527:                return null;
0528:            }
0529:
0530:            /**
0531:             * Returns all the inner classes defined in this class. If no inner classes
0532:             * are defined, then an array of length zero is returned.
0533:             */
0534:            public ClassFile[] getInnerClasses() {
0535:                if (mInnerClasses == null) {
0536:                    return new ClassFile[0];
0537:                }
0538:
0539:                ClassFile[] innerClasses = new ClassFile[mInnerClasses.size()];
0540:                return (ClassFile[]) mInnerClasses.toArray(innerClasses);
0541:            }
0542:
0543:            /**
0544:             * Returns true if this ClassFile represents an inner class.
0545:             */
0546:            public boolean isInnerClass() {
0547:                return mOuterClass != null;
0548:            }
0549:
0550:            /**
0551:             * If this ClassFile represents a non-anonymous inner class, returns its
0552:             * short inner class name.
0553:             */
0554:            public String getInnerClassName() {
0555:                return mInnerClassName;
0556:            }
0557:
0558:            /**
0559:             * Returns null if this ClassFile does not represent an inner class.
0560:             *
0561:             * @see #isInnerClass()
0562:             */
0563:            public ClassFile getOuterClass() {
0564:                return mOuterClass;
0565:            }
0566:
0567:            /**
0568:             * Returns a value indicating how deeply nested an inner class is with
0569:             * respect to its outermost enclosing class. For top level classes, 0
0570:             * is returned. For first level inner classes, 1 is returned, etc.
0571:             */
0572:            public int getClassDepth() {
0573:                int depth = 0;
0574:
0575:                ClassFile outer = mOuterClass;
0576:                while (outer != null) {
0577:                    depth++;
0578:                    outer = outer.mOuterClass;
0579:                }
0580:
0581:                return depth;
0582:            }
0583:
0584:            /**
0585:             * Returns the source file of this class file or null if not set.
0586:             */
0587:            public String getSourceFile() {
0588:                if (mSource == null) {
0589:                    return null;
0590:                } else {
0591:                    return mSource.getFileName().getValue();
0592:                }
0593:            }
0594:
0595:            public boolean isSynthetic() {
0596:                for (int i = mAttributes.size(); --i >= 0;) {
0597:                    Object obj = mAttributes.get(i);
0598:                    if (obj instanceof  SyntheticAttr) {
0599:                        return true;
0600:                    }
0601:                }
0602:                return false;
0603:            }
0604:
0605:            public boolean isDeprecated() {
0606:                for (int i = mAttributes.size(); --i >= 0;) {
0607:                    Object obj = mAttributes.get(i);
0608:                    if (obj instanceof  DeprecatedAttr) {
0609:                        return true;
0610:                    }
0611:                }
0612:                return false;
0613:            }
0614:
0615:            /**
0616:             * Returns all the runtime invisible annotations defined for this class
0617:             * file, or an empty array if none.
0618:             */
0619:            public Annotation[] getRuntimeInvisibleAnnotations() {
0620:                for (int i = mAttributes.size(); --i >= 0;) {
0621:                    Object obj = mAttributes.get(i);
0622:                    if (obj instanceof  RuntimeInvisibleAnnotationsAttr) {
0623:                        return ((AnnotationsAttr) obj).getAnnotations();
0624:                    }
0625:                }
0626:                return new Annotation[0];
0627:            }
0628:
0629:            /**
0630:             * Returns all the runtime visible annotations defined for this class file,
0631:             * or an empty array if none.
0632:             */
0633:            public Annotation[] getRuntimeVisibleAnnotations() {
0634:                for (int i = mAttributes.size(); --i >= 0;) {
0635:                    Object obj = mAttributes.get(i);
0636:                    if (obj instanceof  RuntimeVisibleAnnotationsAttr) {
0637:                        return ((AnnotationsAttr) obj).getAnnotations();
0638:                    }
0639:                }
0640:                return new Annotation[0];
0641:            }
0642:
0643:            /**
0644:             * Add a runtime invisible annotation.
0645:             */
0646:            public Annotation addRuntimeInvisibleAnnotation(TypeDesc type) {
0647:                AnnotationsAttr attr = null;
0648:                for (int i = mAttributes.size(); --i >= 0;) {
0649:                    Object obj = mAttributes.get(i);
0650:                    if (obj instanceof  RuntimeInvisibleAnnotationsAttr) {
0651:                        attr = (AnnotationsAttr) obj;
0652:                    }
0653:                }
0654:                if (attr == null) {
0655:                    attr = new RuntimeInvisibleAnnotationsAttr(mCp);
0656:                    addAttribute(attr);
0657:                }
0658:                Annotation ann = new Annotation(mCp);
0659:                ann.setType(type);
0660:                attr.addAnnotation(ann);
0661:                return ann;
0662:            }
0663:
0664:            /**
0665:             * Add a runtime visible annotation.
0666:             */
0667:            public Annotation addRuntimeVisibleAnnotation(TypeDesc type) {
0668:                AnnotationsAttr attr = null;
0669:                for (int i = mAttributes.size(); --i >= 0;) {
0670:                    Object obj = mAttributes.get(i);
0671:                    if (obj instanceof  RuntimeVisibleAnnotationsAttr) {
0672:                        attr = (AnnotationsAttr) obj;
0673:                    }
0674:                }
0675:                if (attr == null) {
0676:                    attr = new RuntimeVisibleAnnotationsAttr(mCp);
0677:                    addAttribute(attr);
0678:                }
0679:                Annotation ann = new Annotation(mCp);
0680:                ann.setType(type);
0681:                attr.addAnnotation(ann);
0682:                return ann;
0683:            }
0684:
0685:            /**
0686:             * Returns the signature attribute of this classfile, or null if none is
0687:             * defined.
0688:             */
0689:            // TODO: Eventually remove this method
0690:            public SignatureAttr getSignatureAttr() {
0691:                for (int i = mAttributes.size(); --i >= 0;) {
0692:                    Object obj = mAttributes.get(i);
0693:                    if (obj instanceof  SignatureAttr) {
0694:                        return (SignatureAttr) obj;
0695:                    }
0696:                }
0697:                return null;
0698:            }
0699:
0700:            /**
0701:             * Provides access to the ClassFile's ContantPool.
0702:             *
0703:             * @return The constant pool for this class file.
0704:             */
0705:            public ConstantPool getConstantPool() {
0706:                return mCp;
0707:            }
0708:
0709:            public void setModifiers(Modifiers modifiers) {
0710:                mModifiers = modifiers;
0711:            }
0712:
0713:            /**
0714:             * Add an interface that this class implements.
0715:             *
0716:             * @param interfaceName Full interface name.
0717:             */
0718:            public void addInterface(String interfaceName) {
0719:                if (!mInterfaceSet.contains(interfaceName)) {
0720:                    mInterfaces.add(mCp.addConstantClass(interfaceName));
0721:                    mInterfaceSet.add(interfaceName);
0722:                }
0723:            }
0724:
0725:            /**
0726:             * Add an interface that this class implements.
0727:             */
0728:            public void addInterface(Class i) {
0729:                addInterface(i.getName());
0730:            }
0731:
0732:            /**
0733:             * Add a field to this class.
0734:             */
0735:            public FieldInfo addField(Modifiers modifiers, String fieldName,
0736:                    TypeDesc type) {
0737:                FieldInfo fi = new FieldInfo(this , modifiers, fieldName, type);
0738:                mFields.add(fi);
0739:                return fi;
0740:            }
0741:
0742:            /**
0743:             * Add a method to this class.
0744:             *
0745:             * @param ret Is null if method returns void.
0746:             * @param params May be null if method accepts no parameters.
0747:             */
0748:            public MethodInfo addMethod(Modifiers modifiers, String methodName,
0749:                    TypeDesc ret, TypeDesc[] params) {
0750:                MethodDesc md = MethodDesc.forArguments(ret, params);
0751:                return addMethod(modifiers, methodName, md);
0752:            }
0753:
0754:            /**
0755:             * Add a method to this class.
0756:             */
0757:            public MethodInfo addMethod(Modifiers modifiers, String methodName,
0758:                    MethodDesc md) {
0759:                MethodInfo mi = new MethodInfo(this , modifiers, methodName, md);
0760:                mMethods.add(mi);
0761:                return mi;
0762:            }
0763:
0764:            /**
0765:             * Add a method to this class. This method is handy for implementing
0766:             * methods defined by a pre-existing interface.
0767:             */
0768:            public MethodInfo addMethod(Method method) {
0769:                Modifiers modifiers = Modifiers.getInstance(
0770:                        method.getModifiers()).toAbstract(false);
0771:                MethodInfo mi = addMethod(modifiers, method.getName(),
0772:                        MethodDesc.forMethod(method));
0773:
0774:                // exception stuff...
0775:                Class[] exceptions = method.getExceptionTypes();
0776:                for (int i = 0; i < exceptions.length; i++) {
0777:                    mi.addException(TypeDesc.forClass(exceptions[i]));
0778:                }
0779:
0780:                return mi;
0781:            }
0782:
0783:            /**
0784:             * Add a method to this class by declaration.
0785:             *
0786:             * @throws IllegalArgumentException if declaration syntax is wrong
0787:             * @see MethodDeclarationParser
0788:             */
0789:            public MethodInfo addMethod(String declaration) {
0790:                MethodDeclarationParser p = new MethodDeclarationParser(
0791:                        declaration);
0792:                return addMethod(p.getModifiers(), p.getMethodName(), p
0793:                        .getReturnType(), p.getParameters());
0794:            }
0795:
0796:            /**
0797:             * Add a constructor to this class.
0798:             *
0799:             * @param params May be null if constructor accepts no parameters.
0800:             */
0801:            public MethodInfo addConstructor(Modifiers modifiers,
0802:                    TypeDesc[] params) {
0803:                MethodDesc md = MethodDesc.forArguments(null, params);
0804:                MethodInfo mi = new MethodInfo(this , modifiers, "<init>", md);
0805:                mMethods.add(mi);
0806:                return mi;
0807:            }
0808:
0809:            /**
0810:             * Adds a public, no-arg constructor with the code buffer properly defined.
0811:             */
0812:            public MethodInfo addDefaultConstructor() {
0813:                MethodInfo mi = addConstructor(Modifiers.PUBLIC, null);
0814:                CodeBuilder builder = new CodeBuilder(mi);
0815:                builder.loadThis();
0816:                builder.invokeSuperConstructor(null);
0817:                builder.returnVoid();
0818:                return mi;
0819:            }
0820:
0821:            /**
0822:             * Add a static initializer to this class.
0823:             */
0824:            public MethodInfo addInitializer() {
0825:                MethodDesc md = MethodDesc.forArguments(null, null);
0826:                Modifiers af = Modifiers.NONE.toStatic(true);
0827:                MethodInfo mi = new MethodInfo(this , af, "<clinit>", md);
0828:                mMethods.add(mi);
0829:                return mi;
0830:            }
0831:
0832:            /**
0833:             * Add an inner class to this class. By default, inner classes are private
0834:             * static.
0835:             *
0836:             * @param fullInnerClassName Optional full inner class name.
0837:             * @param innerClassName Optional short inner class name.
0838:             */
0839:            public ClassFile addInnerClass(String fullInnerClassName,
0840:                    String innerClassName) {
0841:                return addInnerClass(fullInnerClassName, innerClassName,
0842:                        (String) null);
0843:            }
0844:
0845:            /**
0846:             * Add an inner class to this class. By default, inner classes are private
0847:             * static.
0848:             *
0849:             * @param fullInnerClassName Optional full inner class name.
0850:             * @param innerClassName Optional short inner class name.
0851:             * @param superClass Super class.
0852:             */
0853:            public ClassFile addInnerClass(String fullInnerClassName,
0854:                    String innerClassName, Class super Class) {
0855:                return addInnerClass(innerClassName, super Class.getName());
0856:            }
0857:
0858:            /**
0859:             * Add an inner class to this class. By default, inner classes are private
0860:             * static.
0861:             *
0862:             * @param fullInnerClassName Optional full inner class name.
0863:             * @param innerClassName Optional short inner class name.
0864:             * @param superClassName Full super class name.
0865:             */
0866:            public ClassFile addInnerClass(String fullInnerClassName,
0867:                    String innerClassName, String super ClassName) {
0868:                if (fullInnerClassName == null) {
0869:                    if (innerClassName == null) {
0870:                        fullInnerClassName = mClassName + '$'
0871:                                + (++mAnonymousInnerClassCount);
0872:                    } else {
0873:                        fullInnerClassName = mClassName + '$' + innerClassName;
0874:                    }
0875:                }
0876:
0877:                ClassFile inner = new ClassFile(fullInnerClassName,
0878:                        super ClassName);
0879:                Modifiers modifiers = inner.getModifiers().toPrivate(true)
0880:                        .toStatic(true);
0881:                inner.setModifiers(modifiers);
0882:                inner.mInnerClassName = innerClassName;
0883:                inner.mOuterClass = this ;
0884:
0885:                if (mInnerClasses == null) {
0886:                    mInnerClasses = new ArrayList();
0887:                }
0888:
0889:                mInnerClasses.add(inner);
0890:
0891:                // Record the inner class in this, the outer class.
0892:                if (mInnerClassesAttr == null) {
0893:                    addAttribute(new InnerClassesAttr(mCp));
0894:                }
0895:
0896:                // TODO: Anonymous inner classes and method scoped classes do not have
0897:                // an outer class listed.
0898:
0899:                mInnerClassesAttr.addInnerClass(fullInnerClassName, mClassName,
0900:                        innerClassName, modifiers);
0901:
0902:                // Record the inner class in itself.
0903:                inner
0904:                        .addAttribute(new InnerClassesAttr(inner
0905:                                .getConstantPool()));
0906:                inner.mInnerClassesAttr.addInnerClass(fullInnerClassName,
0907:                        mClassName, innerClassName, modifiers);
0908:
0909:                return inner;
0910:            }
0911:
0912:            /**
0913:             * Set the source file of this class file by adding a source file
0914:             * attribute. The source doesn't actually have to be a file,
0915:             * but the virtual machine spec names the attribute "SourceFile_attribute".
0916:             */
0917:            public void setSourceFile(String fileName) {
0918:                addAttribute(new SourceFileAttr(mCp, fileName));
0919:            }
0920:
0921:            /**
0922:             * Mark this class as being synthetic by adding a special attribute.
0923:             */
0924:            public void markSynthetic() {
0925:                addAttribute(new SyntheticAttr(mCp));
0926:            }
0927:
0928:            /**
0929:             * Mark this class as being deprecated by adding a special attribute.
0930:             */
0931:            public void markDeprecated() {
0932:                addAttribute(new DeprecatedAttr(mCp));
0933:            }
0934:
0935:            /**
0936:             * Add an attribute to this class.
0937:             */
0938:            public void addAttribute(Attribute attr) {
0939:                if (attr instanceof  SourceFileAttr) {
0940:                    if (mSource != null) {
0941:                        mAttributes.remove(mSource);
0942:                    }
0943:                    mSource = (SourceFileAttr) attr;
0944:                } else if (attr instanceof  InnerClassesAttr) {
0945:                    if (mInnerClassesAttr != null) {
0946:                        mAttributes.remove(mInnerClassesAttr);
0947:                    }
0948:                    mInnerClassesAttr = (InnerClassesAttr) attr;
0949:                }
0950:
0951:                mAttributes.add(attr);
0952:            }
0953:
0954:            public Attribute[] getAttributes() {
0955:                Attribute[] attrs = new Attribute[mAttributes.size()];
0956:                return (Attribute[]) mAttributes.toArray(attrs);
0957:            }
0958:
0959:            /**
0960:             * Specify what target virtual machine version classfile should generate
0961:             * for. Calling this method changes the major and minor version of the
0962:             * classfile format.
0963:             *
0964:             * @param target VM version, 1.0, 1.1, etc.
0965:             * @throws IllegalArgumentException if target is not supported
0966:             */
0967:            public void setTarget(String target)
0968:                    throws IllegalArgumentException {
0969:                int major, minor;
0970:
0971:                if (target == null || "1.0".equals(target)
0972:                        || "1.1".equals(target)) {
0973:                    major = 45;
0974:                    minor = 3;
0975:                    if (target == null) {
0976:                        target = "1.0";
0977:                    }
0978:                } else if ("1.2".equals(target)) {
0979:                    major = 46;
0980:                    minor = 0;
0981:                } else if ("1.3".equals(target)) {
0982:                    major = 47;
0983:                    minor = 0;
0984:                } else if ("1.4".equals(target)) {
0985:                    major = 48;
0986:                    minor = 0;
0987:                } else if ("1.5".equals(target)) {
0988:                    major = 49;
0989:                    minor = 0;
0990:                } else if ("1.6".equals(target)) {
0991:                    major = 50;
0992:                    minor = 0;
0993:                } else {
0994:                    throw new IllegalArgumentException(
0995:                            "Unsupported target version: " + target);
0996:                }
0997:
0998:                mVersion = (minor << 16) | (major & 0xffff);
0999:                mTarget = target.intern();
1000:            }
1001:
1002:            /**
1003:             * Returns the target virtual machine version, or null if unknown.
1004:             */
1005:            public String getTarget() {
1006:                return mTarget;
1007:            }
1008:
1009:            /**
1010:             * Sets the version to use when writing the generated classfile, overriding
1011:             * the target.
1012:             */
1013:            public void setVersion(int major, int minor) {
1014:                if (major > 65535 || minor > 65535) {
1015:                    throw new IllegalArgumentException(
1016:                            "Version number element cannot exceed 65535");
1017:                }
1018:
1019:                mVersion = (minor << 16) | (major & 0xffff);
1020:
1021:                String target;
1022:                switch (major) {
1023:                default:
1024:                    target = null;
1025:                    break;
1026:                case 45:
1027:                    target = minor == 3 ? "1.0" : null;
1028:                    break;
1029:                case 46:
1030:                    target = minor == 0 ? "1.2" : null;
1031:                    break;
1032:                case 47:
1033:                    target = minor == 0 ? "1.3" : null;
1034:                    break;
1035:                case 48:
1036:                    target = minor == 0 ? "1.4" : null;
1037:                    break;
1038:                case 49:
1039:                    target = minor == 0 ? "1.5" : null;
1040:                    break;
1041:                case 50:
1042:                    target = minor == 0 ? "1.6" : null;
1043:                    break;
1044:                }
1045:
1046:                mTarget = target;
1047:            }
1048:
1049:            /**
1050:             * Returns the major version number of the classfile format.
1051:             */
1052:            public int getMajorVersion() {
1053:                return mVersion & 0xffff;
1054:            }
1055:
1056:            /**
1057:             * Returns the minor version number of the classfile format.
1058:             */
1059:            public int getMinorVersion() {
1060:                return (mVersion >> 16) & 0xffff;
1061:            }
1062:
1063:            /**
1064:             * Writes the ClassFile to the given OutputStream.
1065:             */
1066:            public void writeTo(OutputStream out) throws IOException {
1067:                if (!(out instanceof  DataOutput)) {
1068:                    out = new DataOutputStream(out);
1069:                }
1070:                writeTo((DataOutput) out);
1071:            }
1072:
1073:            /**
1074:             * Writes the ClassFile to the given DataOutput.
1075:             */
1076:            public void writeTo(DataOutput dout) throws IOException {
1077:                dout.writeInt(MAGIC);
1078:                dout.writeInt(mVersion);
1079:
1080:                mCp.writeTo(dout);
1081:
1082:                {
1083:                    int flags = mModifiers.getBitmask();
1084:                    if (!mModifiers.isInterface()) {
1085:                        // Set the ACC_SUPER flag for classes only.
1086:                        flags |= Modifier.SYNCHRONIZED;
1087:                    }
1088:                    dout.writeShort(flags);
1089:                }
1090:
1091:                dout.writeShort(mThisClass.getIndex());
1092:                if (mSuperClass != null) {
1093:                    dout.writeShort(mSuperClass.getIndex());
1094:                } else {
1095:                    dout.writeShort(0);
1096:                }
1097:
1098:                int size = mInterfaces.size();
1099:                if (size > 65535) {
1100:                    throw new IllegalStateException(
1101:                            "Interfaces count cannot exceed 65535: " + size);
1102:                }
1103:                dout.writeShort(size);
1104:                for (int i = 0; i < size; i++) {
1105:                    int index = ((ConstantInfo) mInterfaces.get(i)).getIndex();
1106:                    dout.writeShort(index);
1107:                }
1108:
1109:                size = mFields.size();
1110:                if (size > 65535) {
1111:                    throw new IllegalStateException(
1112:                            "Field count cannot exceed 65535: " + size);
1113:                }
1114:                dout.writeShort(size);
1115:                for (int i = 0; i < size; i++) {
1116:                    FieldInfo field = (FieldInfo) mFields.get(i);
1117:                    field.writeTo(dout);
1118:                }
1119:
1120:                size = mMethods.size();
1121:                if (size > 65535) {
1122:                    throw new IllegalStateException(
1123:                            "Method count cannot exceed 65535: " + size);
1124:                }
1125:                dout.writeShort(size);
1126:                for (int i = 0; i < size; i++) {
1127:                    MethodInfo method = (MethodInfo) mMethods.get(i);
1128:                    method.writeTo(dout);
1129:                }
1130:
1131:                size = mAttributes.size();
1132:                if (size > 65535) {
1133:                    throw new IllegalStateException(
1134:                            "Attribute count cannot exceed 65535: " + size);
1135:                }
1136:                dout.writeShort(size);
1137:                for (int i = 0; i < size; i++) {
1138:                    Attribute attr = (Attribute) mAttributes.get(i);
1139:                    attr.writeTo(dout);
1140:                }
1141:            }
1142:
1143:            public String toString() {
1144:                StringBuffer buf = new StringBuffer();
1145:                String modStr = mModifiers.toString();
1146:                if (modStr.length() > 0) {
1147:                    buf.append(modStr);
1148:                    buf.append(' ');
1149:                }
1150:                if (getModifiers().isInterface()) {
1151:                    buf.append("interface");
1152:                } else {
1153:                    buf.append("class");
1154:                }
1155:                buf.append(' ');
1156:                buf.append(getClassName());
1157:
1158:                return buf.toString();
1159:            }
1160:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.