All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gwtproject.rpc.serialization.api.impl.AbstractSerializationStream Maven / Gradle / Ivy

There is a newer version: 1.0-alpha-8
Show newest version
package org.gwtproject.rpc.serialization.api.impl;

/**
 * Base class for the client and server serialization streams. This class
 * handles the basic serialization and deserialization formatting for primitive
 * types since these are common between the client and the server.
 */
public abstract class AbstractSerializationStream {

    /**
     * The default flags to be used by serialization streams.
     */
    public static final int DEFAULT_FLAGS = 0;

    /**
     * The character used to separate fields in client->server RPC messages.
     */
    public static final char RPC_SEPARATOR_CHAR = '|';

    /**
     * The newest supported RPC protocol version.
     */
    public static final int SERIALIZATION_STREAM_MAX_VERSION = 8;

    /**
     * The current RPC protocol version.
     */
    public static final int SERIALIZATION_STREAM_VERSION = 7;

    /**
     * The oldest supported RPC protocol version.
     */
    public static final int SERIALIZATION_STREAM_MIN_VERSION = 5;

    /**
     * First version to support valid JSON formatted payload responses
     */
    public static final int SERIALIZATION_STREAM_JSON_VERSION = 8;

    /**
     * Indicates that obfuscated type names should be used in the RPC payload.
     */
    public static final int FLAG_ELIDE_TYPE_NAMES = 0x1;

    /**
     * Indicates that RPC token is included in the RPC payload.
     */
    public static final int FLAG_RPC_TOKEN_INCLUDED = 0x2;

    /**
     * Bit mask representing all valid flags.
     */
    public static final int VALID_FLAGS_MASK = 0x3;

    private int flags = DEFAULT_FLAGS;
    private int version = SERIALIZATION_STREAM_VERSION;

    public final void addFlags(int flags) {
        this.flags |= flags;
    }

    /**
     * Checks if flags are valid.
     *
     * @return true if flags are valid and false
     *         otherwise.
     */
    public final boolean areFlagsValid() {
        return (((flags | VALID_FLAGS_MASK) ^ VALID_FLAGS_MASK) == 0);
    }

    public final int getFlags() {
        return flags;
    }

    public final int getVersion() {
        return version;
    }

    public final boolean hasFlags(int flags) {
        return (getFlags() & flags) == flags;
    }

    public final void setFlags(int flags) {
        this.flags = flags;
    }

    protected final void setVersion(int version) {
        this.version = version;
    }

    /**
     * Parse a string containing a base-64 encoded version of a long value.
     *
     * Keep this synchronized with the version in Base64Utils.
     */
    protected static long longFromBase64(String value) {
        int pos = 0;
        long longVal = base64Value(value.charAt(pos++));
        int len = value.length();
        while (pos < len) {
            longVal <<= 6;
            longVal |= base64Value(value.charAt(pos++));
        }
        return longVal;
    }

    /**
     * Return an optionally single-quoted string containing a base-64 encoded
     * version of the given long value.
     *
     * Keep this synchronized with the version in Base64Utils.
     */
    protected static String longToBase64(long value) {
        // Convert to ints early to avoid need for long ops
        int low = (int) (value & 0xffffffff);
        int high = (int) (value >> 32);

        StringBuilder sb = new StringBuilder();
        boolean haveNonZero = base64Append(sb, (high >> 28) & 0xf, false);
        haveNonZero = base64Append(sb, (high >> 22) & 0x3f, haveNonZero);
        haveNonZero = base64Append(sb, (high >> 16) & 0x3f, haveNonZero);
        haveNonZero = base64Append(sb, (high >> 10) & 0x3f, haveNonZero);
        haveNonZero = base64Append(sb, (high >> 4) & 0x3f, haveNonZero);
        int v = ((high & 0xf) << 2) | ((low >> 30) & 0x3);
        haveNonZero = base64Append(sb, v, haveNonZero);
        haveNonZero = base64Append(sb, (low >> 24) & 0x3f, haveNonZero);
        haveNonZero = base64Append(sb, (low >> 18) & 0x3f, haveNonZero);
        haveNonZero = base64Append(sb, (low >> 12) & 0x3f, haveNonZero);
        base64Append(sb, (low >> 6) & 0x3f, haveNonZero);
        base64Append(sb, low & 0x3f, true);

        return sb.toString();
    }

    private static boolean base64Append(StringBuilder sb, int digit, boolean haveNonZero) {
        if (digit > 0) {
            haveNonZero = true;
        }
        if (haveNonZero) {
            int c;
            if (digit < 26) {
                c = 'A' + digit;
            } else if (digit < 52) {
                c = 'a' + digit - 26;
            } else if (digit < 62) {
                c = '0' + digit - 52;
            } else if (digit == 62) {
                c = '$';
            } else {
                c = '_';
            }
            sb.append((char) c);
        }
        return haveNonZero;
    }

    // Assume digit is one of [A-Za-z0-9$_]
    private static int base64Value(char digit) {
        if (digit >= 'A' && digit <= 'Z') {
            return digit - 'A';
        }
        // No need to check digit <= 'z'
        if (digit >= 'a') {
            return digit - 'a' + 26;
        }
        if (digit >= '0' && digit <= '9') {
            return digit - '0' + 52;
        }
        if (digit == '$') {
            return 62;
        }
        // digit == '_'
        return 63;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy