Up ] Parser ]

CPEntry
Home News Listen Read Resources Feedback Contents Search RSS, Contacts

 

 

 

Sponsor Links

Fast, reliable data access for ODBC, JDBC, ADO.NET and XML
Need an expert for Java, XML and Web Services projects?
WSSC 2008: The only event dedicated to Web Services Security technology and business
IBM MQSeries for Compaq NSK - ( v. 5.1 ) - media
88x31 CTIX Logo - Clear Background
Microsoft SQL Server 2005 Standard Edition X64 - complete package
Corel DESIGNER Technical Suite - ( v. 12 ) - complete package
Find XML examples at XML Pitstop

 

Madhu's Workshop

Reflecting on Binary Files

XML
BCEL
XML Spy

Compiler
ANTLR

Java
VM

Tools
Apache
Eclipse

Logo for grid computing portal: GridSummit.com
Logo for database portal logo: SQLSummit.com

 

<< Previous 1 2 3 4 5

As you can see, the code iterates through each entry in the array and reads the appropriate primitive based on the element type. That's simple, but what about aggregate types? Instead of defining the grammar as an array of types, we can define it using a class, which can contain primitive fields, arrays, and references to other classes. Since the input stream follows the grammar, the input stream is like an instance of the grammar. Just like an object is an instance of a class. So the parse method accepts a grammar (as a class) and returns an object. The object contains data read from the stream, which follows the grammar. This is an example of how meta data can be used avoid a lot of tedium. Here are a few examples of data and their respective meta data:

  • object -> class
  • language -> grammar
  • XML document -> XML schema
  • database row -> database schema

Rather pleasing symmetry, isn't it?

Now that we can read primitives, how do we read aggregate types such as arrays and structures? Arrays require two additional pieces of information: the length and the type for each element in the array. It turns out the length of arrays appears just before the array data in a class file, so my choice was to save the value of the last primitive that was read in a field called count. We obtain the array type by getting the name of class describing the array. For example, a single dimensional array of integers has a class name of [I and an array of Strings has a class name of [Ljava/lang/String;. The count, along with the array type, is used to create an instance of the array. The parser proceeds calling parse() recursively to read count elements and populate the array.

Handling structures is similar, but each field can contain different types. For a given class, we simply create a new instance of the class and iterate through its fields, call parse() recursively and set the value for that field. The constant pool is a little tricky because it's an array of different types of structures. The type of structure is defined by a type byte preceding the data for each structure. It sounds like a job for an abstract class with concrete subclasses for each structure type. We just need a way to map the type byte to the appropriate subclass. My choice was to define two static fields in the abstract class for that mapping. It looks like this:

public abstract class CPEntry {
    static Object[] SUBTYPES = {
        new Byte((byte) 1), Utf8Entry.class,
        new Byte((byte) 3), IntegerEntry.class,
        new Byte((byte) 4), FloatEntry.class,
        new Byte((byte) 5), LongEntry.class,
        new Byte((byte) 6), DoubleEntry.class,
        new Byte((byte) 7), ClassEntry.class,
        new Byte((byte) 8), StringEntry.class,
        new Byte((byte) 9), MemberRefEntry.class,
        new Byte((byte) 10), MemberRefEntry.class,
        new Byte((byte) 11), MemberRefEntry.class,
        new Byte((byte) 12), NameAndTypeEntry.class,
    };
    static Class TYPECLASS = Byte.TYPE;
}

The SUBTYPES array defines the mapping for each type value, TYPECLASS defines the size of the type identifier itself, which is a byte. Now we need to declare classes for each of the subclasses. Here are a couple of examples:

class Utf8Entry extends CPEntry {
    short length;
    byte[] data;
}

class IntegerEntry extends CPEntry {
    int value;
}

Next: Java code for the parser

1 2 3 4 5 Next>>

 

 


 

FreeShip_120X90 macmini_t1_120x90 120x240

 

 

Home ] Up ] Parser ]

Copyright © 2008,  Ken North Computing, LLC
Last modified: March 31, 2008