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

com.sun.ejb.base.sfsb.util.SimpleKeyGenerator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejb.base.sfsb.util;

import com.sun.ejb.spi.sfsb.util.SFSBUUIDUtil;
import com.sun.enterprise.util.Utility;
import org.glassfish.ha.store.util.KeyTransformer;

/**
 * A utility class that generates stateful session keys using two longs
 * The session id generated by this class is guarenteed to be unique as
 * long as the system clock is never reset to a previous value
 *
 * The hashCode of the SessionKey generated by SimpleKeyGenerator
 * also allows uniform distribution of keys when hashed in a HashMap
 *
 * @author  Mahesh Kannan
 */
public class SimpleKeyGenerator
    implements SFSBUUIDUtil, KeyTransformer {

    protected long prefix;
    protected long suffix;
    protected int idCounter;

    public SimpleKeyGenerator() {
        long now = System.currentTimeMillis();
        now = ((int) (now >>> 32)) + ((int) now);
        scramble((int) now, System.identityHashCode(this));
    }


    public SimpleKeyGenerator(byte[] ipAddress, int port) {
        scramble(Utility.bytesToInt(ipAddress, 0), port);
    }


    public SimpleKeyGenerator(long uniquePrefix) {
        this.prefix = uniquePrefix;

        // Initial suffix
        this.suffix = System.currentTimeMillis();

        // Inital isCounter value
        this.idCounter = 0;

    }


    /**
     * Create and return the sessionKey.
     *
     * @return the sessionKey object
     */
    @Override
    public SimpleSessionKey createSessionKey() {
        int id = 0;
        synchronized (this) {
            id = idCounter++;
            if (id < 0) {
                // idCounter wrapped around!!
                id = idCounter = 0;
                suffix = System.currentTimeMillis();
            }
        }

        return new SimpleSessionKey(prefix, suffix, id);
    }


    /**
     * Called from the Container before publishing an IOR.
     * The method must convert the sessionKey into a byte[]
     *
     * @return A byte[] representation of the key. The byte[]
     *         could be created using serialization.
     */
    @Override
    public byte[] keyToByteArray(SimpleSessionKey key) {
        byte[] array = new byte[20];

        Utility.longToBytes(key.prefix, array, 0);
        Utility.longToBytes(key.suffix, array, 8);
        Utility.intToBytes(key.id, array, 16);

        return array;
    }


    /**
     * Return the sessionKey that represents the sessionKey.
     * This has to be super efficient as the container calls this
     * method on every invocation. Two objects obtained from identical
     * byte[] must satisfy both o1.equals(o2) and
     * o1.hashCode() == o2.hashCode()
     *
     * @return the sessionKey object
     */
    @Override
    public SimpleSessionKey byteArrayToKey(byte[] array, int startIndex, int len) {
        long myPrefix = Utility.bytesToLong(array, startIndex);
        long mySuffix = Utility.bytesToLong(array, startIndex + 8);
        int myId = Utility.bytesToInt(array, startIndex + 16);

        return new SimpleSessionKey(myPrefix, mySuffix, myId);
    }


    private void scramble(int hi, int lo) {
        byte[] hiBytes = new byte[4];
        Utility.intToBytes(hi, hiBytes, 0);
        byte[] loBytes = new byte[4];
        Utility.intToBytes(lo, loBytes, 0);

        swapBytes(hiBytes, loBytes, 2, 3);
        swapBytes(hiBytes, loBytes, 3, 0);
        swapBytes(hiBytes, loBytes, 1, 3);

        swapBytes(hiBytes, hiBytes, 0, 3);
        swapBytes(loBytes, loBytes, 2, 3);

        this.prefix = Utility.bytesToInt(hiBytes, 0);

        this.prefix = (this.prefix << 32) + Utility.bytesToInt(loBytes, 0);

        // Inital isCounter value
        this.idCounter = 0;

        // Set the default suffix value
        this.suffix = (int) System.currentTimeMillis();
    }


    private static final void swapBytes(byte[] a, byte[] b, int index1, int index2) {
        byte temp = a[index1];
        a[index1] = b[index2];
        b[index2] = temp;
    }

    protected static class SimpleSessionKey implements java.io.Serializable {

        long prefix;
        long suffix;
        int id;

        public SimpleSessionKey(long prefix, long suffix, int id) {
            this.prefix = prefix;
            this.suffix = suffix;
            this.id = id;
        }


        @Override
        public int hashCode() {
            return id;
        }


        @Override
        public boolean equals(Object otherObj) {
            if (otherObj instanceof SimpleSessionKey) {
                SimpleSessionKey other = (SimpleSessionKey) otherObj;
                return ((id == other.id) && (prefix == other.prefix) && (suffix == other.suffix));
            }

            return false;
        }


        @Override
        public String toString() {
            StringBuffer sbuf = new StringBuffer();
            sbuf.append(Long.toHexString(prefix)).append("-").append(Long.toHexString(suffix)).append("-")
                .append(Integer.toHexString(id));
            return sbuf.toString();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy