Source Code Cross Referenced for ClassFile.java in  » Database-DBMS » db4o-6.4 » EDU » purdue » cs » bloat » file » 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 » Database DBMS » db4o 6.4 » EDU.purdue.cs.bloat.file 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright (C) 2004 - 2007  db4objects Inc.  http://www.db4o.com
002:
003:        This file is part of the db4o open source object database.
004:
005:        db4o is free software; you can redistribute it and/or modify it under
006:        the terms of version 2 of the GNU General Public License as published
007:        by the Free Software Foundation and as clarified by db4objects' GPL 
008:        interpretation policy, available at
009:        http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010:        Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011:        Suite 350, San Mateo, CA 94403, USA.
012:
013:        db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014:        WARRANTY; without even the implied warranty of MERCHANTABILITY or
015:        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
016:        for more details.
017:
018:        You should have received a copy of the GNU General Public License along
019:        with this program; if not, write to the Free Software Foundation, Inc.,
020:        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
021:        package EDU.purdue.cs.bloat.file;
022:
023:        import java.io.*;
024:        import java.util.*;
025:
026:        import EDU.purdue.cs.bloat.reflect.*;
027:        import EDU.purdue.cs.bloat.util.*;
028:
029:        /**
030:         * ClassFile basically represents a Java classfile as it is found on disk. The
031:         * classfile is modeled according to the Java Virtual Machine Specification.
032:         * Methods are provided to edit the classfile at a very low level.
033:         * 
034:         * @see Attribute
035:         * @see EDU.purdue.cs.bloat.reflect.Constant
036:         * @see Field
037:         * @see Method
038:         * 
039:         * @author Nate Nystrom (<a
040:         *         href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
041:         */
042:        public class ClassFile implements  ClassInfo {
043:            private ClassInfoLoader loader; // ClassInfoLoader that "owns" this class
044:
045:            private List constants; // The constant pool
046:
047:            private int modifiers; // This class's modifer bit field
048:
049:            private int this Class;
050:
051:            private int super Class;
052:
053:            private int[] interfaces;
054:
055:            private Field[] fields;
056:
057:            private Method[] methods;
058:
059:            private Attribute[] attrs;
060:
061:            private File file; // (.class) File in which this class resides
062:
063:            /**
064:             * Constructor. This constructor parses the class file from the input
065:             * stream.
066:             * 
067:             * @param file
068:             *            The file in which the class resides.
069:             * @param loader
070:             *            The class info loader which loaded the class.
071:             * @param in
072:             *            The data stream containing the class.
073:             * @exception ClassFormatError
074:             *                When the class could not be parsed.
075:             */
076:            public ClassFile(final File file, final ClassInfoLoader loader,
077:                    final DataInputStream in) {
078:                this .loader = loader;
079:                this .file = file;
080:                // Assert.isTrue(file != null, "Null file for class file");
081:
082:                // Read in file contents from stream
083:                try {
084:                    if (ClassFileLoader.DEBUG) {
085:                        System.out.println("ClassFile: Reading header");
086:                    }
087:                    readHeader(in);
088:
089:                    if (ClassFileLoader.DEBUG) {
090:                        System.out.println("ClassFile: Reading constant pool");
091:                    }
092:                    readConstantPool(in);
093:
094:                    if (ClassFileLoader.DEBUG) {
095:                        System.out.println("ClassFile: Reading access flags");
096:                    }
097:                    readAccessFlags(in);
098:
099:                    if (ClassFileLoader.DEBUG) {
100:                        System.out.println("ClassFile: Reading class info");
101:                    }
102:                    readClassInfo(in);
103:
104:                    if (ClassFileLoader.DEBUG) {
105:                        System.out.println("ClassFile: Reading fields");
106:                    }
107:                    readFields(in);
108:
109:                    if (ClassFileLoader.DEBUG) {
110:                        System.out.println("ClassFile: Reading methods");
111:                    }
112:                    readMethods(in);
113:
114:                    if (ClassFileLoader.DEBUG) {
115:                        System.out.println("ClassFile: Reading Attributes");
116:                    }
117:                    readAttributes(in);
118:                    in.close();
119:                } catch (final IOException e) {
120:                    throw new ClassFormatException(e.getMessage()
121:                            + " (in file " + file + ")");
122:                }
123:            }
124:
125:            /**
126:             * Creates a new <code>ClassFile</code> from scratch. It has no fields or
127:             * methods.
128:             * 
129:             * @param modifiers
130:             *            The modifiers describing the newly-created class
131:             * @param classIndex
132:             *            The index of the type of the newly-created class in its
133:             *            constant pool
134:             * @param superClassIndex
135:             *            The index of the type of the newly-created class's superclass
136:             *            in its constant pool
137:             * @param interfaceIndexes
138:             *            The indexes of the types of the interfaces that the
139:             *            newly-created class implements
140:             * @param constants
141:             *            The constant pool for the newly created class (a list of
142:             *            {@link Constant}s).
143:             */
144:            public ClassFile(final int modifiers, final int classIndex,
145:                    final int super ClassIndex, final int[] interfaceIndexes,
146:                    final List constants, final ClassInfoLoader loader) {
147:                this .modifiers = modifiers;
148:                this .this Class = classIndex;
149:                this .super Class = super ClassIndex;
150:                this .interfaces = interfaceIndexes;
151:                this .constants = constants;
152:                this .loader = loader;
153:
154:                this .fields = new Field[0];
155:                this .methods = new Method[0];
156:                this .attrs = new Attribute[0];
157:            }
158:
159:            /**
160:             * Get the class info loader for the class.
161:             * 
162:             * @return The class info loader for the class.
163:             */
164:            public ClassInfoLoader loader() {
165:                return loader;
166:            }
167:
168:            /**
169:             * Get the name of the class, including the package name.
170:             * 
171:             * @return The name of the class.
172:             */
173:            public String name() {
174:                Constant c = (Constant) constants.get(this Class);
175:                Assert.isNotNull(c, "Null constant for class name");
176:                if (c.tag() == Constant.CLASS) {
177:                    final Integer nameIndex = (Integer) c.value();
178:                    if (nameIndex != null) {
179:                        c = (Constant) constants.get(nameIndex.intValue());
180:                        if (c.tag() == Constant.UTF8) {
181:                            return (String) c.value();
182:                        }
183:                    }
184:                }
185:
186:                throw new ClassFormatException(
187:                        "Couldn't find class name in file");
188:            }
189:
190:            /**
191:             * Set the index into the constant pool of the name of the class.
192:             * 
193:             * @param index
194:             *            The index of the name of the class.
195:             */
196:            public void setClassIndex(final int index) {
197:                this .this Class = index;
198:            }
199:
200:            /**
201:             * Set the index into the constant pool of the name of the class's
202:             * superclass.
203:             * 
204:             * @param index
205:             *            The index of the name of the superclass.
206:             */
207:            public void setSuperclassIndex(final int index) {
208:                this .super Class = index;
209:            }
210:
211:            /**
212:             * Set the indices into the constant pool of the names of the class's
213:             * interfaces.
214:             * 
215:             * @param indices
216:             *            The indices of the names of the interfaces.
217:             */
218:            public void setInterfaceIndices(final int[] indices) {
219:                this .interfaces = indices;
220:            }
221:
222:            /**
223:             * Get the index into the constant pool of the name of the class.
224:             * 
225:             * @return The index of the name of the class.
226:             */
227:            public int classIndex() {
228:                return this Class;
229:            }
230:
231:            /**
232:             * Get the index into the constant pool of the name of the class's
233:             * superclass.
234:             * 
235:             * @return The index of the name of the superclass.
236:             */
237:            public int super classIndex() {
238:                return super Class;
239:            }
240:
241:            /**
242:             * Get the indices into the constant pool of the names of the class's
243:             * interfaces.
244:             * 
245:             * @return The indices of the names of the interfaces.
246:             */
247:            public int[] interfaceIndices() {
248:                return interfaces;
249:            }
250:
251:            /**
252:             * Set the modifiers of the class. The values correspond to the constants in
253:             * the Modifiers class.
254:             * 
255:             * @param modifiers
256:             *            A bit vector of modifier flags for the class.
257:             * @see Modifiers
258:             */
259:            public void setModifiers(final int modifiers) {
260:                this .modifiers = modifiers;
261:            }
262:
263:            /**
264:             * Get the modifiers of the class. The values correspond to the constants in
265:             * the Modifiers class.
266:             * 
267:             * @return A bit vector of modifier flags for the class.
268:             * @see Modifiers
269:             */
270:            public int modifiers() {
271:                return modifiers;
272:            }
273:
274:            /**
275:             * Get an array of FieldInfo structures for each field in the class.
276:             * 
277:             * @return An array of FieldInfo structures.
278:             */
279:            public FieldInfo[] fields() {
280:                return fields;
281:            }
282:
283:            /**
284:             * Returns an array of MethodInfo structures for each method in the class.
285:             */
286:            public MethodInfo[] methods() {
287:                return methods;
288:            }
289:
290:            /**
291:             * Sets the methods in this class.
292:             */
293:            public void setMethods(final MethodInfo[] methods) {
294:                this .methods = new Method[methods.length];
295:                for (int i = 0; i < methods.length; i++) {
296:                    this .methods[i] = (Method) methods[i];
297:                }
298:
299:            }
300:
301:            /**
302:             * Get an array of the constants in the constant pool.
303:             * 
304:             * @return An array of Constants.
305:             */
306:            public Constant[] constants() {
307:                return (Constant[]) constants.toArray(new Constant[0]);
308:            }
309:
310:            /**
311:             * Set all the constants in the constant pool.
312:             * 
313:             * @param constants
314:             *            The array of Constants.
315:             */
316:            public void setConstants(final Constant[] constants) {
317:                this .constants = new ArrayList(constants.length);
318:                for (int i = 0; i < constants.length; i++) {
319:                    this .constants.add(i, constants[i]);
320:                }
321:            }
322:
323:            /**
324:             * Returns the File from which this <code>ClassFile</code> was created. If
325:             * this <code>ClassFile</code> was created from scratch, <code>null</code>
326:             * is returned.
327:             */
328:            public File file() {
329:                return file;
330:            }
331:
332:            /**
333:             * Creates a new File object to hold this class. It is placed in the output
334:             * directory and has the name of the class represented by this ClassFile
335:             * followed by the .class extension.
336:             */
337:            public File outputFile() {
338:                final File outputDir = ((ClassFileLoader) loader).outputDir();
339:                final String fileName = this .name().replace('/',
340:                        File.separatorChar);
341:                return new File(outputDir, fileName + ".class");
342:            }
343:
344:            /**
345:             * Commit any changes back to a file in the output directory. The output
346:             * directory is determined from the ClassFileLoader.
347:             */
348:            public void commit() {
349:                try {
350:                    commitTo(loader.outputStreamFor(this ));
351:
352:                } catch (final IOException e) {
353:                    e.printStackTrace();
354:                    System.exit(1);
355:                }
356:            }
357:
358:            /**
359:             * Commit changes made to this class. Write changes to an OutputStream.
360:             */
361:            void commitTo(final OutputStream outStream) {
362:                try {
363:                    final DataOutputStream out = new DataOutputStream(outStream);
364:
365:                    writeHeader(out);
366:                    writeConstantPool(out);
367:                    writeAccessFlags(out);
368:                    writeClassInfo(out);
369:                    writeFields(out, null);
370:                    writeMethods(out, null);
371:                    writeAttributes(out);
372:
373:                    out.close();
374:
375:                } catch (final IOException e) {
376:                    e.printStackTrace();
377:                    System.exit(1);
378:                }
379:            }
380:
381:            public void commitOnly(final Set methods, final Set fields) {
382:                try {
383:                    final OutputStream outStream = loader.outputStreamFor(this );
384:                    final DataOutputStream out = new DataOutputStream(outStream);
385:
386:                    writeHeader(out);
387:                    writeConstantPool(out);
388:                    writeAccessFlags(out);
389:                    writeClassInfo(out);
390:                    writeFields(out, fields);
391:                    writeMethods(out, methods);
392:                    writeAttributes(out);
393:
394:                    out.close();
395:
396:                } catch (final IOException e) {
397:                    e.printStackTrace();
398:                    System.exit(1);
399:                }
400:            }
401:
402:            /**
403:             * Write the class file header.
404:             * 
405:             * @param out
406:             *            The stream to which to write.
407:             * @exception IOException
408:             *                If an error occurs while writing.
409:             */
410:            private void writeHeader(final DataOutputStream out)
411:                    throws IOException {
412:                out.writeInt(0xCAFEBABE);
413:                out.writeShort(3);
414:                out.writeShort(45);
415:            }
416:
417:            /**
418:             * Write the class's constant pool.
419:             * 
420:             * @param out
421:             *            The stream to which to write.
422:             * @exception IOException
423:             *                If an error occurs while writing.
424:             */
425:            private void writeConstantPool(final DataOutputStream out)
426:                    throws IOException {
427:                out.writeShort(constants.size());
428:
429:                // Write the constants. The first constant is reserved for
430:                // internal use by the JVM, so start at 1.
431:                for (int i = 1; i < constants.size(); i++) {
432:                    writeConstant(out, (Constant) constants.get(i));
433:
434:                    switch (((Constant) constants.get(i)).tag()) {
435:                    case Constant.LONG:
436:                    case Constant.DOUBLE:
437:                        // Longs and doubles take up 2 constant pool entries.
438:                        i++;
439:                        break;
440:                    }
441:                }
442:            }
443:
444:            /**
445:             * Read a constant from the constant pool.
446:             * 
447:             * @param in
448:             *            The stream from which to read.
449:             * @return The constant.
450:             * @exception IOException
451:             *                If an error occurs while reading.
452:             */
453:            private Constant readConstant(final DataInputStream in)
454:                    throws IOException {
455:                final int tag = in.readUnsignedByte();
456:                Object value;
457:
458:                switch (tag) {
459:                case Constant.CLASS:
460:                case Constant.STRING:
461:                    value = new Integer(in.readUnsignedShort());
462:                    break;
463:                case Constant.FIELD_REF:
464:                case Constant.METHOD_REF:
465:                case Constant.INTERFACE_METHOD_REF:
466:                case Constant.NAME_AND_TYPE:
467:                    value = new int[2];
468:                    ((int[]) value)[0] = in.readUnsignedShort();
469:                    ((int[]) value)[1] = in.readUnsignedShort();
470:                    break;
471:                case Constant.INTEGER:
472:                    value = new Integer(in.readInt());
473:                    break;
474:                case Constant.FLOAT:
475:                    value = new Float(in.readFloat());
476:                    break;
477:                case Constant.LONG:
478:                    // Longs take up 2 constant pool entries.
479:                    value = new Long(in.readLong());
480:                    break;
481:                case Constant.DOUBLE:
482:                    // Doubles take up 2 constant pool entries.
483:                    value = new Double(in.readDouble());
484:                    break;
485:                case Constant.UTF8:
486:                    value = in.readUTF();
487:                    break;
488:                default:
489:                    throw new ClassFormatException(file.getPath()
490:                            + ": Invalid constant tag: " + tag);
491:                }
492:
493:                return new Constant(tag, value);
494:            }
495:
496:            /**
497:             * Write a constant in the constant pool.
498:             * 
499:             * @param out
500:             *            The stream to which to write.
501:             * @param constant
502:             *            The constant.
503:             * @exception IOException
504:             *                If an error occurs while writing.
505:             */
506:            private void writeConstant(final DataOutputStream out,
507:                    final Constant constant) throws IOException {
508:                final int tag = constant.tag();
509:                final Object value = constant.value();
510:
511:                out.writeByte(tag);
512:
513:                switch (tag) {
514:                case Constant.CLASS:
515:                case Constant.STRING:
516:                    out.writeShort(((Integer) value).intValue());
517:                    break;
518:                case Constant.INTEGER:
519:                    out.writeInt(((Integer) value).intValue());
520:                    break;
521:                case Constant.FLOAT:
522:                    out.writeFloat(((Float) value).floatValue());
523:                    break;
524:                case Constant.LONG:
525:                    out.writeLong(((Long) value).longValue());
526:                    break;
527:                case Constant.DOUBLE:
528:                    out.writeDouble(((Double) value).doubleValue());
529:                    break;
530:                case Constant.UTF8:
531:                    out.writeUTF((String) value);
532:                    break;
533:                case Constant.FIELD_REF:
534:                case Constant.METHOD_REF:
535:                case Constant.INTERFACE_METHOD_REF:
536:                case Constant.NAME_AND_TYPE:
537:                    out.writeShort(((int[]) value)[0]);
538:                    out.writeShort(((int[]) value)[1]);
539:                    break;
540:                }
541:            }
542:
543:            /**
544:             * Write the class's access flags.
545:             * 
546:             * @param out
547:             *            The stream to which to write.
548:             * @exception IOException
549:             *                If an error occurs while writing.
550:             */
551:            private void writeAccessFlags(final DataOutputStream out)
552:                    throws IOException {
553:                out.writeShort(modifiers);
554:            }
555:
556:            /**
557:             * Write the class's name, superclass, and interfaces.
558:             * 
559:             * @param out
560:             *            The stream to which to write.
561:             * @exception IOException
562:             *                If an error occurs while writing.
563:             */
564:            private void writeClassInfo(final DataOutputStream out)
565:                    throws IOException {
566:                out.writeShort(this Class);
567:                out.writeShort(super Class);
568:
569:                out.writeShort(interfaces.length);
570:
571:                for (int i = 0; i < interfaces.length; i++) {
572:                    out.writeShort(interfaces[i]);
573:                }
574:            }
575:
576:            /**
577:             * Write the class's fields.
578:             * 
579:             * @param out
580:             *            The stream to which to write.
581:             * @exception IOException
582:             *                If an error occurs while writing.
583:             */
584:            private void writeFields(final DataOutputStream out,
585:                    final Set onlyFields) throws IOException {
586:                out.writeShort(fields.length);
587:
588:                for (int i = 0; i < fields.length; i++) {
589:                    if ((onlyFields != null) && onlyFields.contains(fields[i])) {
590:                        continue;
591:                    }
592:                    fields[i].write(out);
593:                }
594:            }
595:
596:            /**
597:             * Write the class's methods.
598:             * 
599:             * @param out
600:             *            The stream to which to write.
601:             * @exception IOException
602:             *                If an error occurs while writing.
603:             */
604:            private void writeMethods(final DataOutputStream out,
605:                    final Set onlyMethods) throws IOException {
606:                if (onlyMethods != null) {
607:                    out.writeShort(onlyMethods.size());
608:
609:                } else {
610:                    if (Method.DEBUG) {
611:                        System.out.println("Writing " + methods.length
612:                                + " methods");
613:                    }
614:                    out.writeShort(methods.length);
615:                }
616:
617:                for (int i = 0; i < methods.length; i++) {
618:                    if ((onlyMethods != null)
619:                            && onlyMethods.contains(methods[i])) {
620:                        continue;
621:                    }
622:                    methods[i].write(out);
623:                }
624:            }
625:
626:            /**
627:             * Write the class's attributes. No attributes are written by this method
628:             * since none are required.
629:             * 
630:             * @param out
631:             *            The stream to which to write.
632:             * @exception IOException
633:             *                If an error occurs while writing.
634:             */
635:            private void writeAttributes(final DataOutputStream out)
636:                    throws IOException {
637:                out.writeShort(attrs.length);
638:
639:                for (int i = 0; i < attrs.length; i++) {
640:                    out.writeShort(attrs[i].nameIndex());
641:                    out.writeInt(attrs[i].length());
642:                    attrs[i].writeData(out);
643:                }
644:            }
645:
646:            /**
647:             * Read the class file header.
648:             * 
649:             * @param in
650:             *            The stream from which to read.
651:             * @exception IOException
652:             *                If an error occurs while reading.
653:             */
654:            private void readHeader(final DataInputStream in)
655:                    throws IOException {
656:                final int magic = in.readInt();
657:
658:                if (magic != 0xCAFEBABE) {
659:                    throw new ClassFormatError("Bad magic number.");
660:                }
661:
662:                in.readUnsignedShort(); // major
663:                in.readUnsignedShort(); // minor
664:            }
665:
666:            /**
667:             * Read the class's constant pool. Constants in the constant pool are
668:             * modeled by an array of <tt>reflect.Constant</tt>/
669:             * 
670:             * @param in
671:             *            The stream from which to read.
672:             * @exception IOException
673:             *                If an error occurs while reading.
674:             * 
675:             * @see EDU.purdue.cs.bloat.reflect.Constant
676:             * @see #constants
677:             */
678:            private void readConstantPool(final DataInputStream in)
679:                    throws IOException {
680:                final int count = in.readUnsignedShort();
681:
682:                constants = new ArrayList(count);
683:
684:                // The first constant is reserved for internal use by the JVM.
685:                constants.add(0, null);
686:
687:                // Read the constants.
688:                for (int i = 1; i < count; i++) {
689:                    constants.add(i, readConstant(in));
690:
691:                    switch (((Constant) constants.get(i)).tag()) {
692:                    case Constant.LONG:
693:                    case Constant.DOUBLE:
694:                        // Longs and doubles take up 2 constant pool entries.
695:                        constants.add(++i, null);
696:                        break;
697:                    }
698:                }
699:            }
700:
701:            /**
702:             * Read the class's access flags.
703:             * 
704:             * @param in
705:             *            The stream from which to read.
706:             * @exception IOException
707:             *                If an error occurs while reading.
708:             */
709:            private void readAccessFlags(final DataInputStream in)
710:                    throws IOException {
711:                modifiers = in.readUnsignedShort();
712:            }
713:
714:            /**
715:             * Read the class's name, superclass, and interfaces.
716:             * 
717:             * @param in
718:             *            The stream from which to read.
719:             * @exception IOException
720:             *                If an error occurs while reading.
721:             */
722:            private void readClassInfo(final DataInputStream in)
723:                    throws IOException {
724:                this Class = in.readUnsignedShort();
725:                super Class = in.readUnsignedShort();
726:
727:                final int numInterfaces = in.readUnsignedShort();
728:
729:                interfaces = new int[numInterfaces];
730:
731:                for (int i = 0; i < numInterfaces; i++) {
732:                    interfaces[i] = in.readUnsignedShort();
733:                }
734:            }
735:
736:            /**
737:             * Read the class's fields.
738:             * 
739:             * @param in
740:             *            The stream from which to read.
741:             * @exception IOException
742:             *                If an error occurs while reading.
743:             */
744:            private void readFields(final DataInputStream in)
745:                    throws IOException {
746:                final int numFields = in.readUnsignedShort();
747:
748:                fields = new Field[numFields];
749:
750:                for (int i = 0; i < numFields; i++) {
751:                    fields[i] = new Field(in, this );
752:                }
753:            }
754:
755:            /**
756:             * Read the class's methods.
757:             * 
758:             * @param in
759:             *            The stream from which to read.
760:             * @exception IOException
761:             *                If an error occurs while reading.
762:             */
763:            private void readMethods(final DataInputStream in)
764:                    throws IOException {
765:                final int numMethods = in.readUnsignedShort();
766:
767:                methods = new Method[numMethods];
768:
769:                for (int i = 0; i < numMethods; i++) {
770:                    methods[i] = new Method(in, this );
771:                }
772:            }
773:
774:            /**
775:             * Read the class's attributes. Since none of the attributes are required,
776:             * just read the length of each attribute and skip that many bytes.
777:             * 
778:             * @param in
779:             *            The stream from which to read.
780:             * @exception IOException
781:             *                If an error occurs while reading.
782:             */
783:            private void readAttributes(final DataInputStream in)
784:                    throws IOException {
785:                final int numAttributes = in.readUnsignedShort();
786:
787:                attrs = new Attribute[numAttributes];
788:
789:                for (int i = 0; i < numAttributes; i++) {
790:                    final int nameIndex = in.readUnsignedShort();
791:                    final int length = in.readInt();
792:                    attrs[i] = new GenericAttribute(in, nameIndex, length);
793:                }
794:            }
795:
796:            /**
797:             * Creates a new field in this classfile
798:             */
799:            public FieldInfo addNewField(final int modifiers,
800:                    final int typeIndex, final int nameIndex) {
801:                final Field field = new Field(this , modifiers, typeIndex,
802:                        nameIndex);
803:
804:                // Add the new field to the list of fields
805:                final Field[] fields = new Field[this .fields.length + 1];
806:                for (int i = 0; i < this .fields.length; i++) {
807:                    fields[i] = this .fields[i];
808:                }
809:                fields[this .fields.length] = field;
810:                this .fields = fields;
811:
812:                return (field);
813:            }
814:
815:            /**
816:             * Creates a new field in this classfile
817:             */
818:            public FieldInfo addNewField(final int modifiers,
819:                    final int typeIndex, final int nameIndex,
820:                    final int cvNameIndex, final int constantValueIndex) {
821:                final Field field = new Field(this , modifiers, typeIndex,
822:                        nameIndex, cvNameIndex, constantValueIndex);
823:
824:                // Add the new field to the list of fields
825:                final Field[] fields = new Field[this .fields.length + 1];
826:                for (int i = 0; i < this .fields.length; i++) {
827:                    fields[i] = this .fields[i];
828:                }
829:                fields[this .fields.length] = field;
830:                this .fields = fields;
831:
832:                return (field);
833:            }
834:
835:            /**
836:             * Removes the field whose name is at the given index in the constant pool.
837:             * 
838:             * @throws IllegalArgumentException The class does not contain a field whose
839:             *        name is at the given index
840:             */
841:            public void deleteField(final int nameIndex) {
842:                final List newFields = new ArrayList();
843:
844:                boolean foundIt = false;
845:                for (int i = 0; i < this .fields.length; i++) {
846:                    final Field field = this .fields[i];
847:                    if (field.nameIndex() == nameIndex) {
848:                        foundIt = true;
849:
850:                    } else {
851:                        newFields.add(field);
852:                    }
853:                }
854:
855:                if (!foundIt) {
856:                    final String s = "No field with name index " + nameIndex
857:                            + " in " + this .name();
858:                    throw new IllegalArgumentException(s);
859:
860:                } else {
861:                    this .fields = (Field[]) newFields.toArray(new Field[0]);
862:                }
863:            }
864:
865:            /**
866:             * Deletes a method from this class
867:             * 
868:             * @param nameIndex
869:             *            Index in the constant pool of the name of the method to be
870:             *            deleted
871:             * @param typeIndex
872:             *            Index in the constant pool of the type of the method to be
873:             *            deleted
874:             * 
875:             * @throws IllegalArgumentException The class modeled by this
876:             *        <code>ClassInfo</code> does not contain a method whose name and
877:             *        type are not at the given indices
878:             */
879:            public void deleteMethod(final int nameIndex, final int typeIndex) {
880:                final List newMethods = new ArrayList();
881:
882:                boolean foundIt = false;
883:                for (int i = 0; i < this .methods.length; i++) {
884:                    final Method method = this .methods[i];
885:                    if ((method.nameIndex() == nameIndex)
886:                            && (method.typeIndex() == typeIndex)) {
887:                        foundIt = true;
888:
889:                    } else {
890:                        newMethods.add(method);
891:                    }
892:                }
893:
894:                if (!foundIt) {
895:                    final String s = "No method with name index " + nameIndex
896:                            + " and type index " + typeIndex + " in "
897:                            + this .name();
898:                    throw new IllegalArgumentException(s);
899:
900:                } else {
901:                    this .methods = (Method[]) newMethods.toArray(new Method[0]);
902:                }
903:            }
904:
905:            /**
906:             * Creates a new method in this class
907:             */
908:            public MethodInfo addNewMethod(final int modifiers,
909:                    final int typeIndex, final int nameIndex,
910:                    final int exceptionIndex, final int[] exceptionTypeIndices,
911:                    final int codeIndex) {
912:                final Exceptions exceptions = new Exceptions(this ,
913:                        exceptionIndex, exceptionTypeIndices);
914:                final Code code = new Code(this , codeIndex); // code can't be null
915:                final Attribute[] attributes = new Attribute[] { exceptions,
916:                        code };
917:
918:                final Method method = new Method(this , modifiers, nameIndex,
919:                        typeIndex, attributes, code, exceptions);
920:
921:                // Add the new method to the list of method
922:                final Method[] methods = new Method[this .methods.length + 1];
923:                for (int i = 0; i < this .methods.length; i++) {
924:                    methods[i] = this .methods[i];
925:                }
926:                methods[this .methods.length] = method;
927:                this .methods = methods;
928:
929:                return (method);
930:            }
931:
932:            /**
933:             * Prints a textual representation of this classfile to a PrintStream. The
934:             * text includes information such as the constants in the constant pool, the
935:             * name of the class's superclass, its modifier flags, its fields, and its
936:             * methods.
937:             * 
938:             * @param out
939:             *            The stream to which to print.
940:             */
941:            public void print(final PrintStream out) {
942:                print(new PrintWriter(out, true));
943:            }
944:
945:            public void print(final PrintWriter out) {
946:                out.print("(constants");
947:                for (int i = 0; i < constants.size(); i++) {
948:                    out.print("\n    " + i + ": " + constants.get(i));
949:                }
950:                out.println(")");
951:
952:                out.println("(class " + classIndex() + ")");
953:                out.println("(super " + super classIndex() + ")");
954:
955:                out.print("(interfaces");
956:                for (int i = 0; i < interfaces.length; i++) {
957:                    out.print("\n    " + i + ": " + interfaces[i]);
958:                }
959:                out.println(")");
960:
961:                out.print("(modifiers");
962:                if ((modifiers & Modifiers.PUBLIC) != 0) {
963:                    out.print(" PUBLIC");
964:                }
965:                if ((modifiers & Modifiers.FINAL) != 0) {
966:                    out.print(" FINAL");
967:                }
968:                if ((modifiers & Modifiers.SUPER) != 0) {
969:                    out.print(" SUPER");
970:                }
971:                if ((modifiers & Modifiers.INTERFACE) != 0) {
972:                    out.print(" INTERFACE");
973:                }
974:                if ((modifiers & Modifiers.ABSTRACT) != 0) {
975:                    out.print(" ABSTRACT");
976:                }
977:                out.println(")");
978:
979:                out.print("(fields");
980:                for (int i = 0; i < fields.length; i++) {
981:                    out.print("\n    " + i + ": " + fields[i]);
982:                }
983:                out.println(")");
984:
985:                out.print("(methods");
986:                for (int i = 0; i < methods.length; i++) {
987:                    out.print("\n    " + i + ": " + methods[i]);
988:                }
989:                out.println(")");
990:            }
991:
992:            public String toString() {
993:                return "(ClassFile " + name() + ")";
994:            }
995:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.