Package blackberry.core

Source Code of blackberry.core.WidgetBlob$SliceFunction

/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package blackberry.core;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import net.rim.device.api.crypto.MD5Digest;
import net.rim.device.api.script.Scriptable;

/**
* A WidgetBlob is a reference to an opaque block of binary data.
*
* Blobs are a general-purpose interchange format. They can be passed into, and returned by, a variety of Gears methods. Blobs
* are, in many ways, parallel to Strings. Most APIs that accept a 'String' could be updated to accept 'String-or-Blob'.
*
* Blobs are immutable. The binary data referenced by a Blob cannot be modified directly. (This guarantees Blobs will have
* predictable behavior when passed to asynchronous APIs.) In practice, this is not a limitation; APIs can accept Blobs and return
* new Blobs. Note that JavaScript strings are also immutable; they behave the same way.
*/
public final class WidgetBlob extends Scriptable implements Blob {

    // Content of the blob as byte array.
    private final byte[] _bytes;
    private final int _size;
    private final String _id;
    private Hashtable _fields;
   
    private static Hashtable _registry = new Hashtable();

    /**
     * Constructs a Blob object.
     *
     * @param bytes
     *            The contents of the blob.
     */
    public WidgetBlob( byte[] bytes ) {
        // The byte array is NOT copied intentionally, as Gears fully controls
        // the construction of the Blob objects.
        _bytes = bytes;
        _size = bytes.length;
        _id = md5Hash( bytes );

        // add JS fields/methods - length, slice(), getBytes(), id
        _fields = new Hashtable();
        _fields.put( "length", new Integer( _size ) );
        _fields.put( "getBytes", new GetBytesFunction() );
        _fields.put( "slice", new SliceFunction() );
        _fields.put( "id", _id );
       
        // add blob to registry
        _registry.put( _id, this );
    }

    /**
     * @see blackberry.core.Blob
     */
    public Blob slice( int offset, int length ) {
        if( _bytes.length < offset + length ) {
            throw new IllegalArgumentException( "length of the byte array must be >= offset + length" );
        }

        if( offset == 0 && length == _bytes.length ) {
            return this;
        } else {
            byte[] bytes = new byte[ length ];
            System.arraycopy( _bytes, offset, bytes, 0, length );
            return new WidgetBlob( bytes );
        }
    }

    /**
     * @see blackberry.core.Blob
     */
    public int size() {
        return _size;
    }

    /**
     * @see blackberry.core.Blob
     */
    public byte[] getBytes() {
        return _bytes;
    }

    /**
     * see net.rim.device.api.script.Scriptable#getElementCount()
     */
    public int getElementCount() {
        return _fields.size();
    }

    /**
     * @see net.rim.device.api.script.Scriptable#enumerateFields(Vector)
     */
    public void enumerateFields( Vector v ) {
        if( !_fields.isEmpty() ) {
            for( Enumeration e = _fields.keys(); e.hasMoreElements(); ) {
                v.addElement( e.nextElement() );
            }
        }
    }

    /**
     * @see net.rim.device.api.script.Scriptable#getField(String)
     */
    public Object getField( String name ) throws Exception {
        Object field = _fields.get( name );
        if( field == null ) {
            return UNDEFINED;
        }
        return field;
    }

    /**
     * Scriptable function wrapper class for getBytes() method.
     */
    private static class GetBytesFunction extends ScriptableFunctionBase {
        /**
         * Returns the bytes (as integers in the range 0-255) of a slice of the Blob.
         *
         * Parameters: offset - Optional. The position of the first byte to return. The default value is zero. length - Optional.
         * The number of bytes to return. The default value means to the end of the Blob.
         *
         * Return: An integer array containing the Blob's bytes.
         */
        public Object execute( Object thiz, Object[] args ) throws Exception {
            // Perform action
            byte[] blobBytes = ( (Blob) thiz ).getBytes();
            Integer[] result = new Integer[ blobBytes.length ];

            // populate int array
            for( int i = 0; i < result.length; i++ ) {
                result[ i ] = new Integer( (int) blobBytes[ i ] & 0xFF );
            }

            return result;
        }

        /**
         * @see net.rim.device.api.web.jse.base.ScriptableFunctionBase
         */
        protected FunctionSignature[] getFunctionSignatures() {
            return null;
        }
    }

    /**
     * Scriptable function wrapper class for slice() method.
     */
    private static class SliceFunction extends ScriptableFunctionBase {
        /**
         * Extracts a subset of the current Blob and returns it as a new Blob.
         *
         * Parameters: offset - The position of the first byte to extract. length - Optional. The number of bytes to extract. The
         * default value means to the end of the Blob.
         *
         * Return: A new Blob containing the specified subset.
         */
        public Object execute( Object thiz, Object[] args ) throws Exception {
            int offset = ( (Integer) args[ 0 ] ).intValue();
            int length = 0;
            if( args.length == 2 ) {
                length = ( (Integer) args[ 1 ] ).intValue();
            } else {
                length = ( (Blob) thiz ).size();
            }

            // validate non-negative
            if( offset < 0 ) {
                throw new IllegalArgumentException( "offset must be non-negative integer" );
            }
            if( length < 0 ) {
                throw new IllegalArgumentException( "length must be non-negative integer" );
            }

            // Perform action
            return ( (Blob) thiz ).slice( offset, length );
        }

        /**
         * @see net.rim.device.api.web.jse.base.ScriptableFunctionBase
         */
        protected FunctionSignature[] getFunctionSignatures() {
            FunctionSignature fs = new FunctionSignature( 2 );
            fs.addParam( Integer.class, true );
            fs.addParam( Integer.class, false );
            return new FunctionSignature[] { fs };
        }
    }
   
    public static WidgetBlob getBlobById( String id ) {
        return (WidgetBlob) _registry.get( id );
    }
   
    private static String md5Hash( byte[] bytes ) {
        MD5Digest md5 = new MD5Digest();
        md5.reset();
        md5.update( bytes, 0, bytes.length );
        return new String( convertToHexStr( md5.getDigest() ).getBytes() );
    }

    private static String convertToHexStr( byte[] data ) {
        StringBuffer buf = new StringBuffer();
        for( int i = 0; i < data.length; i++ ) {
            int halfbyte = ( data[ i ] >>> 4 ) & 0x0F;
            int two_halfs = 0;
            do {
                if( ( 0 <= halfbyte ) && ( halfbyte <= 9 ) )
                    buf.append( (char) ( '0' + halfbyte ) );
                else
                    buf.append( (char) ( 'a' + ( halfbyte - 10 ) ) );
                halfbyte = data[ i ] & 0x0F;
            } while( two_halfs++ < 1 );
        }
        return buf.toString();
    }
}
TOP

Related Classes of blackberry.core.WidgetBlob$SliceFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
script>