001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/framework/util/BasicUUIDFactory.java $
002    /*
003     * 
004     This class orginaly has been part of the apache derby project. It has 
005     slightly been changed to match the requirements of deegree.
006    
007     Derby - Class org.apache.derby.impl.services.uuid.BasicUUIDFactory
008    
009     Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
010    
011     Licensed under the Apache License, Version 2.0 (the "License");
012     you may not use this file except in compliance with the License.
013     You may obtain a copy of the License at
014    
015     http://www.apache.org/licenses/LICENSE-2.0
016    
017     Unless required by applicable law or agreed to in writing, software
018     distributed under the License is distributed on an "AS IS" BASIS,
019     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020     See the License for the specific language governing permissions and
021     limitations under the License.
022    
023     */
024    
025    package org.deegree.framework.util;
026    
027    /**
028     * 
029     * A hack implementation of something similar to a DCE UUID generator. Generates unique 128-bit
030     * numbers based on the current machine's internet address, the current time, and a sequence number.
031     * This implementation should be made to conform to the DCE specification. ("DEC/HP, Network
032     * Computing Architecture, Remote Procedure Call Runtime Extensions Specification, version OSF
033     * TX1.0.11," Steven Miller, July 23, 1992. This is part of the OSF DCE Documentation. Chapter 10
034     * describes the UUID generation algorithm.)
035     * <P>
036     * Some known deficiencies:
037     * <ul>
038     * <li> Rather than using the 48-bit hardware network address, it uses the 32-bit IP address. IP
039     * addresses are not guaranteed to be unique.
040     * <li> There is no provision for generating a suitably unique number if no IP address is available.
041     * <li> Two processes running on this machine which start their respective UUID services within a
042     * millisecond of one another may generate duplicate UUIDS.
043     * </ul>
044     * <P>
045     * However, the intention is that UUIDs generated from this class will be unique with respect to
046     * UUIDs generated by other DCE UUID generators.
047     * 
048     * @deprecated use
049     * @see UUID
050     * 
051     */
052    
053    public final class BasicUUIDFactory {
054        /*
055         * * Fields of BasicUUIDFactory.
056         */
057    
058        private long majorId; // 48 bits only
059    
060        private long timemillis;
061    
062        public BasicUUIDFactory() {
063    
064            majorId = Runtime.getRuntime().freeMemory();
065    
066            majorId &= 0x0000ffffffffffffL;
067            resetCounters();
068        }
069    
070        public BasicUUIDFactory( long majorId ) {
071    
072            this.majorId = majorId;
073    
074            this.majorId &= 0x0000ffffffffffffL;
075            resetCounters();
076        }
077    
078        //
079        // Constants and fields for computing the sequence number. We started out with monotonically
080        // increasing sequence numbers but realized that this causes collisions at the
081        // ends of BTREEs built on UUID columns. So now we have a random number
082        // generator. We generate these numbers using a technique from Knuth
083        // "Seminumerical Algorithms," section 3.2 (Generating Uniform Random Numbers).
084        // The formula is:
085        //
086        // next = ( (MULTIPLIER * current) + STEP ) % MODULUS
087        //
088        // Here
089        //
090        // MODULUS = int size.
091        // MULTIPLIER = fairly close to the square root of MODULUS to force the
092        // sequence number to jump around. satisifies the rule that
093        // (MULTIPLIER-1) is divisible by 4 and by all the primes which
094        // divide MODULUS.
095        // STEP = a large number that keeps the sequence number jumping around.
096        // must be relatively prime to MODULUS.
097        // INITIAL_VALUE = a number guaranteeing that the first couple sequence numbers
098        // won't be monotonically increasing.
099        //
100        // The sequence numbers should jump around and cycle through all numbers which fit in an int.
101    
102        private static final long MODULUS = ( 1L << 32 );
103    
104        private static final long MULTIPLIER = ( ( 1L << 14 ) + 1 );
105    
106        private static final long STEP = ( ( 1L << 27 ) + 1 );
107    
108        private static final long INITIAL_VALUE = ( 2551218188L );
109    
110        private long currentValue;
111    
112        /*
113         * * Methods of UUID
114         */
115    
116        /**
117         * Generate a new UUID.
118         * 
119         * @see UUIDFactory#createUUID
120         */
121        public synchronized UUID createUUID() {
122            long cv = currentValue = ( ( MULTIPLIER * currentValue ) + STEP ) % MODULUS;
123            if ( cv == INITIAL_VALUE ) {
124                bumpMajor();
125            }
126            int sequence = (int) cv;
127    
128            return new BasicUUID( majorId, timemillis, sequence );
129        }
130    
131        /**
132         * Recreate a UUID previously generated UUID value.
133         * 
134         * @see UUIDFactory#recreateUUID
135         */
136        public UUID recreateUUID( String uuidstring ) {
137            return new BasicUUID( uuidstring );
138        }
139    
140        /**
141         * @see UUIDFactory#recreateUUID
142         */
143        public UUID recreateUUID( byte[] b ) {
144            return new BasicUUID( b );
145        }
146    
147        private void bumpMajor() {
148    
149            // 48 bits only
150            majorId = ( majorId + 1L ) & 0x0000ffffffffffffL;
151            if ( majorId == 0L )
152                resetCounters();
153    
154        }
155    
156        private void resetCounters() {
157            timemillis = System.currentTimeMillis();
158            currentValue = INITIAL_VALUE;
159        }
160    }