FileDocCategorySizeDatePackage
MessageBytes.javaAPI DocGlassfish v2 API22468Fri May 04 22:33:14 BST 2007org.apache.tomcat.util.buf

MessageBytes

public final class MessageBytes extends Object implements Serializable, Cloneable
This class is used to represent a subarray of bytes in an HTTP message. It represents all request/response elements. The byte/char conversions are delayed and cached. Everything is recyclable. The object can represent a byte[], a char[], or a (sub) String. All operations can be made in case sensitive mode or not.
author
dac@eng.sun.com
author
James Todd [gonzo@eng.sun.com]
author
Costin Manolache

Fields Summary
private int
type
public static final int
T_NULL
public static final int
T_STR
getType() is T_STR if the the object used to create the MessageBytes was a String
public static final int
T_BYTES
getType() is T_STR if the the object used to create the MessageBytes was a byte[]
public static final int
T_CHARS
getType() is T_STR if the the object used to create the MessageBytes was a char[]
private int
hashCode
private boolean
hasHashCode
private boolean
caseSensitive
private ByteChunk
byteC
private CharChunk
charC
private String
strValue
private boolean
hasStrValue
private int
intValue
private boolean
hasIntValue
private long
longValue
private boolean
hasLongValue
private Date
dateValue
private boolean
hasDateValue
private static MessageBytesFactory
factory
Constructors Summary
public MessageBytes()
Creates a new, uninitialized MessageBytes object.

deprecated
Use static newInstance() in order to allow future hooks.

    
                           
      
    
Methods Summary
public voidduplicate(org.apache.tomcat.util.buf.MessageBytes src)
Copy the src into this MessageBytes, allocating more space if needed

        // START CR 6309514
        // Discard previous state before duplicating
        recycle();
        // END CR 6309514
        
        switch( src.getType() ) {
            case MessageBytes.T_BYTES:
                type=T_BYTES;
                ByteChunk bc=src.getByteChunk();
                byteC.allocate( 2 * bc.getLength(), -1 );
                byteC.append( bc );
                break;
            case MessageBytes.T_CHARS:
                type=T_CHARS;
                CharChunk cc=src.getCharChunk();
                charC.allocate( 2 * cc.getLength(), -1 );
                charC.append( cc );
                break;
            case MessageBytes.T_STR:
                type=T_STR;
                String sc=src.getString();
                this.setString( sc );
                break;
        }
    
public booleanequals(java.lang.String s)
Compares the message bytes to the specified String object.

param
s the String to compare
return
true if the comparison succeeded, false otherwise

        if( s == null )
            return false;

        if( ! caseSensitive )
            return equalsIgnoreCase( s );
        switch (type) {
            case T_STR:
                if( strValue==null && s!=null) return false;
                return strValue.equals( s );
            case T_CHARS:
                return charC.equals( s );
            case T_BYTES:
                return byteC.equals( s );
            default:
                return false;
        }
    
public booleanequals(java.lang.Object obj)

        
        if (obj == null || (!(obj instanceof MessageBytes))) {
            return false;
        }
        
        MessageBytes mb = (MessageBytes) obj;
        
        switch (type) {
            case T_STR:
                return mb.equals( strValue );
        }
        
        if( mb.type != T_CHARS &&
                mb.type!= T_BYTES ) {
            // it's a string or int/date string value
            return equals( mb.toString() );
        }
        
        // mb is either CHARS or BYTES.
        // this is either CHARS or BYTES
        // Deal with the 4 cases ( in fact 3, one is simetric)
        
        if( mb.type == T_CHARS && type==T_CHARS ) {
            return charC.equals( mb.charC );
        }
        if( mb.type==T_BYTES && type== T_BYTES ) {
            return byteC.equals( mb.byteC );
        }
        if( mb.type== T_CHARS && type== T_BYTES ) {
            return byteC.equals( mb.charC );
        }
        if( mb.type== T_BYTES && type== T_CHARS ) {
            return mb.byteC.equals( charC );
        }
        // can't happen
        return true;
    
public booleanequalsIgnoreCase(java.lang.String s)
Compares the message bytes to the specified String object.

param
s the String to compare
return
true if the comparison succeeded, false otherwise

        switch (type) {
            case T_STR:
                if( strValue==null && s!=null) return false;
                return strValue.equalsIgnoreCase( s );
            case T_CHARS:
                return charC.equalsIgnoreCase( s );
            case T_BYTES:
                return byteC.equalsIgnoreCase( s );
            default:
                return false;
        }
    
public ByteChunkgetByteChunk()
Returns the byte chunk, representing the byte[] and offset/length. Valid only if T_BYTES or after a conversion was made.

        return byteC;
    
public CharChunkgetCharChunk()
Returns the char chunk, representing the char[] and offset/length. Valid only if T_CHARS or after a conversion was made.

        return charC;
    
public org.apache.tomcat.util.buf.MessageBytesgetClone()

        try {
            return (MessageBytes)this.clone();
        } catch( Exception ex) {
            return null;
        }
    
public intgetInt()
Convert the buffer to an int, cache the value

        if( hasIntValue )
            return intValue;
        
        switch (type) {
            case T_BYTES:
                intValue=byteC.getInt();
                break;
            default:
                intValue=Integer.parseInt(toString());
        }
        hasIntValue=true;
        return intValue;
    
public intgetLength()
Returns the length of the original buffer. Note that the length in bytes may be different from the length in chars.

        if(type==T_BYTES)
            return byteC.getLength();
        if(type==T_CHARS) {
            return charC.getLength();
        }
        if(type==T_STR)
            return strValue.length();
        toString();
        if( strValue==null ) return 0;
        return strValue.length();
    
public longgetLong()
Convert the buffer to an long, cache the value

        if( hasLongValue )
            return longValue;
        
        switch (type) {
            case T_BYTES:
                longValue=byteC.getLong();
                break;
            default:
                longValue=Long.parseLong(toString());
        }
        
        hasLongValue=true;
        return longValue;
        
    
public java.lang.StringgetString()
Returns the string value. Valid only if T_STR or after a conversion was made.

        return strValue;
    
public longgetTime()

deprecated
The buffer are general purpose, caching for headers should be done in headers

        if( hasDateValue ) {
            if( dateValue==null) return -1;
            return dateValue.getTime();
        }
        
        long l=DateTool.parseDate( this );
        if( dateValue==null)
            dateValue=new Date(l);
        else
            dateValue.setTime(l);
        hasDateValue=true;
        return l;
    
public intgetType()
Return the type of the original content. Can be T_STR, T_BYTES, T_CHARS or T_NULL

        return type;
    
private inthash()

        int code=0;
        switch (type) {
            case T_STR:
                // We need to use the same hash function
                for (int i = 0; i < strValue.length(); i++) {
                    code = code * 37 + strValue.charAt( i );
                }
                return code;
            case T_CHARS:
                return charC.hash();
            case T_BYTES:
                return byteC.hash();
            default:
                return 0;
        }
    
public inthashCode()

        if( hasHashCode ) return hashCode;
        int code = 0;
        
        if( caseSensitive )
            code=hash();
        else
            code=hashIgnoreCase();
        hashCode=code;
        hasHashCode=true;
        return code;
    
private inthashIgnoreCase()

        int code=0;
        switch (type) {
            case T_STR:
                for (int i = 0; i < strValue.length(); i++) {
                    code = code * 37 + Ascii.toLower(strValue.charAt( i ));
                }
                return code;
            case T_CHARS:
                return charC.hashIgnoreCase();
            case T_BYTES:
                return byteC.hashIgnoreCase();
            default:
                return 0;
        }
    
public intindexOf(char c)

        return indexOf( c, 0);
    
public intindexOf(java.lang.String s, int starting)

        toString();
        return strValue.indexOf( s, starting );
    
public intindexOf(java.lang.String s)

        return indexOf( s, 0 );
    
public intindexOf(char c, int starting)
Returns true if the message bytes starts with the specified string.

param
c the character
param
starting The start position

        switch (type) {
            case T_STR:
                return strValue.indexOf( c, starting );
            case T_CHARS:
                return charC.indexOf( c, starting);
            case T_BYTES:
                return byteC.indexOf( c, starting );
            default:
                return -1;
        }
    
public intindexOfIgnoreCase(java.lang.String s, int starting)

        toString();
        String upper=strValue.toUpperCase();
        String sU=s.toUpperCase();
        return upper.indexOf( sU, starting );
    
public booleanisNull()

//		should we check also hasStrValue ???
        return byteC.isNull() && charC.isNull() && ! hasStrValue;
        // bytes==null && strValue==null;
    
public static org.apache.tomcat.util.buf.MessageBytesnewInstance()
Construct a new MessageBytes instance

        return factory.newInstance();
    
public voidrecycle()
Resets the message bytes to an uninitialized (NULL) state.

        type=T_NULL;
        byteC.recycle();
        charC.recycle();
        
        strValue=null;
        caseSensitive=true;
        
        hasStrValue=false;
        hasHashCode=false;
        hasIntValue=false;
        hasLongValue=false;
        hasDateValue=false;
    
public voidresetStringValue()
Remove the cached string value. Use it after a conversion on the byte[] or after the encoding is changed XXX Is this needed ?

        if( type != T_STR ) {
            // If this was cread as a byte[] or char[], we remove
            // the old string value
            hasStrValue=false;
            strValue=null;
        }
    
public voidsetBytes(byte[] b, int off, int len)
Sets the content to the specified subarray of bytes.

param
b the bytes
param
off the start offset of the bytes
param
len the length of the bytes

        byteC.setBytes( b, off, len );
        type=T_BYTES;
        hasStrValue=false;
        hasHashCode=false;
        hasIntValue=false;
        hasLongValue=false;
        hasDateValue=false;
    
public voidsetCaseSenitive(boolean b)
Configure the case sensitivity

        caseSensitive=b;
    
public voidsetChars(char[] c, int off, int len)
Sets the content to be a char[]

param
c the bytes
param
off the start offset of the bytes
param
len the length of the bytes

        charC.setChars( c, off, len );
        type=T_CHARS;
        hasStrValue=false;
        hasHashCode=false;
        hasIntValue=false;
        hasLongValue=false;
        hasDateValue=false;
    
public voidsetEncoding(java.lang.String enc)
Set the encoding. If the object was constructed from bytes[]. any previous conversion is reset. If no encoding is set, we'll use 8859-1.

        if( !byteC.isNull() ) {
            // if the encoding changes we need to reset the converion results
            charC.recycle();
            hasStrValue=false;
        }
        byteC.setEncoding(enc);
    
public static voidsetFactory(org.apache.tomcat.util.buf.MessageBytes$MessageBytesFactory mbf)

    
           
        factory=mbf;
    
public voidsetInt(int i)
Set the buffer to the representation of an int

        byteC.allocate(16, 32);
        int current = i;
        byte[] buf = byteC.getBuffer();
        int start = 0;
        int end = 0;
        if (i == 0) {
            buf[end++] = (byte) '0";
        }
        if (i < 0) {
            current = -i;
            buf[end++] = (byte) '-";
        }
        while (current > 0) {
            int digit = current % 10;
            current = current / 10;
            buf[end++] = HexUtils.HEX[digit];
        }
        byteC.setOffset(0);
        byteC.setEnd(end);
        // Inverting buffer
        end--;
        if (i < 0) {
            start++;
        }
        while (end > start) {
            byte temp = buf[start];
            buf[start] = buf[end];
            buf[end] = temp;
            start++;
            end--;
        }
        intValue=i;
        hasStrValue=false;
        hasHashCode=false;
        hasIntValue=true;
        hasLongValue=false;
        hasDateValue=false;
        type=T_BYTES;
    
public voidsetLong(long l)
Set the buffer to the representation of an long

        byteC.allocate(32, 64);
        long current = l;
        byte[] buf = byteC.getBuffer();
        int start = 0;
        int end = 0;
        if (l == 0) {
            buf[end++] = (byte) '0";
        }
        if (l < 0) {
            current = -l;
            buf[end++] = (byte) '-";
        }
        while (current > 0) {
            int digit = (int) (current % 10);
            current = current / 10;
            buf[end++] = HexUtils.HEX[digit];
        }
        byteC.setOffset(0);
        byteC.setEnd(end);
        // Inverting buffer
        end--;
        if (l < 0) {
            start++;
        }
        while (end > start) {
            byte temp = buf[start];
            buf[start] = buf[end];
            buf[end] = temp;
            start++;
            end--;
        }
        longValue=l;
        hasStrValue=false;
        hasHashCode=false;
        hasIntValue=false;
        hasLongValue=true;
        hasDateValue=false;
        type=T_BYTES;
    
public voidsetString(java.lang.String s)
Set the content to be a string

        strValue=s;
        hasHashCode=false;
        hasIntValue=false;
        hasLongValue=false;
        hasDateValue=false;
        if (s == null) {
            hasStrValue=false;
            type=T_NULL;
        } else {
            hasStrValue=true;
            type=T_STR;
        }
    
public voidsetTime(long t, java.text.DateFormat df)

deprecated
The buffer are general purpose, caching for headers should be done in headers. The second parameter allows us to pass a date format instance to avoid synchronization problems.

    
                                        
          
        // XXX replace it with a byte[] tool
        recycle();
        if( dateValue==null)
            dateValue=new Date(t);
        else
            dateValue.setTime(t);
        if( df==null )
            strValue=DateTool.format1123(dateValue);
        else
            strValue=DateTool.format1123(dateValue,df);
        hasStrValue=true;
        hasDateValue=true;
        type=T_STR;
    
public voidsetTime(long t)

        setTime( t, null );
    
public booleanstartsWith(java.lang.String s)
Returns true if the message bytes starts with the specified string.

param
s the string

        switch (type) {
            case T_STR:
                return strValue.startsWith( s );
            case T_CHARS:
                return charC.startsWith( s );
            case T_BYTES:
                return byteC.startsWith( s );
            default:
                return false;
        }
    
public booleanstartsWithIgnoreCase(java.lang.String s, int pos)
Returns true if the message bytes starts with the specified string.

param
s the string
param
pos The start position

        switch (type) {
            case T_STR:
                if( strValue==null ) return false;
                if( strValue.length() < pos + s.length() ) return false;
                
                for( int i=0; i<s.length(); i++ ) {
                    if( Ascii.toLower( s.charAt( i ) ) !=
                            Ascii.toLower( strValue.charAt( pos + i ))) {
                        return false;
                    }
                }
                return true;
            case T_CHARS:
                return charC.startsWithIgnoreCase( s, pos );
            case T_BYTES:
                return byteC.startsWithIgnoreCase( s, pos );
            default:
                return false;
        }
    
public voidtoBytes()
Unimplemented yet. Do a char->byte conversion.

        if( ! byteC.isNull() ) {
            type=T_BYTES;
            return;
        }
        toString();
        type=T_BYTES;
        byte bb[] = strValue.getBytes();
        byteC.setBytes(bb, 0, bb.length);
    
public voidtoChars()
Convert to char[] and fill the CharChunk. XXX Not optimized - it converts to String first.

        if( ! charC.isNull() ) {
            type=T_CHARS;
            return;
        }
        // inefficient
        toString();
        type=T_CHARS;
        char cc[]=strValue.toCharArray();
        charC.setChars(cc, 0, cc.length);
    
public java.lang.StringtoString()
Compute the string value

        if( hasStrValue ) return strValue;
        hasStrValue=true;
        
        switch (type) {
            case T_CHARS:
                strValue=charC.toString();
                return strValue;
            case T_BYTES:
                strValue=byteC.toString();
                return strValue;
        }
        return null;