001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/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    package org.deegree.framework.util;
025    
026    /**
027     * 
028     * A hack implementation of something similar to a DCE UUID generator. Generates unique 128-bit
029     * numbers based on the current machine's internet address, the current time, and a sequence number.
030     * This implementation should be made to conform to the DCE specification. ("DEC/HP, Network
031     * Computing Architecture, Remote Procedure Call Runtime Extensions Specification, version OSF
032     * TX1.0.11," Steven Miller, July 23, 1992. This is part of the OSF DCE Documentation. Chapter 10
033     * describes the UUID generation algorithm.)
034     * <P>
035     * Some known deficiencies:
036     * <ul>
037     * <li> Rather than using the 48-bit hardware network address, it uses the 32-bit IP address. IP
038     * addresses are not guaranteed to be unique.
039     * <li> There is no provision for generating a suitably unique number if no IP address is available.
040     * <li> Two processes running on this machine which start their respective UUID services within a
041     * millisecond of one another may generate duplicate UUIDS.
042     * </ul>
043     * <P>
044     * However, the intention is that UUIDs generated from this class will be unique with respect to
045     * UUIDs generated by other DCE UUID generators.
046     * 
047     * @deprecated use
048     * @see UUID
049     * 
050     */
051    
052    public final class BasicUUIDFactory {
053        /*
054         * * Fields of BasicUUIDFactory.
055         */
056    
057        private long majorId; // 48 bits only
058    
059        private long timemillis;
060    
061        public BasicUUIDFactory() {
062    
063            majorId = Runtime.getRuntime().freeMemory();
064    
065            majorId &= 0x0000ffffffffffffL;
066            resetCounters();
067        }
068    
069        public BasicUUIDFactory( long majorId ) {
070    
071            this.majorId = majorId;
072    
073            this.majorId &= 0x0000ffffffffffffL;
074            resetCounters();
075        }
076    
077        //
078        // Constants and fields for computing the sequence number. We started out with monotonically
079        // increasing sequence numbers but realized that this causes collisions at the
080        // ends of BTREEs built on UUID columns. So now we have a random number
081        // generator. We generate these numbers using a technique from Knuth
082        // "Seminumerical Algorithms," section 3.2 (Generating Uniform Random Numbers).
083        // The formula is:
084        //
085        // next = ( (MULTIPLIER * current) + STEP ) % MODULUS
086        //
087        // Here
088        //
089        // MODULUS = int size.
090        // MULTIPLIER = fairly close to the square root of MODULUS to force the
091        // sequence number to jump around. satisifies the rule that
092        // (MULTIPLIER-1) is divisible by 4 and by all the primes which
093        // divide MODULUS.
094        // STEP = a large number that keeps the sequence number jumping around.
095        // must be relatively prime to MODULUS.
096        // INITIAL_VALUE = a number guaranteeing that the first couple sequence numbers
097        // won't be monotonically increasing.
098        //
099        // The sequence numbers should jump around and cycle through all numbers which fit in an int.
100    
101        private static final long MODULUS = ( 1L << 32 );
102    
103        private static final long MULTIPLIER = ( ( 1L << 14 ) + 1 );
104    
105        private static final long STEP = ( ( 1L << 27 ) + 1 );
106    
107        private static final long INITIAL_VALUE = ( 2551218188L );
108    
109        private long currentValue;
110    
111        /*
112         * * Methods of UUID
113         */
114    
115        /**
116         * Generate a new UUID.
117         * 
118         * @see UUIDFactory#createUUID
119         */
120        public synchronized UUID createUUID() {
121            long cv = currentValue = ( ( MULTIPLIER * currentValue ) + STEP ) % MODULUS;
122            if ( cv == INITIAL_VALUE ) {
123                bumpMajor();
124            }
125            int sequence = (int) cv;
126    
127            return new BasicUUID( majorId, timemillis, sequence );
128        }
129    
130        /**
131         * Recreate a UUID previously generated UUID value.
132         * 
133         * @see UUIDFactory#recreateUUID
134         */
135        public UUID recreateUUID( String uuidstring ) {
136            return new BasicUUID( uuidstring );
137        }
138    
139        /**
140         * @see UUIDFactory#recreateUUID
141         */
142        public UUID recreateUUID( byte[] b ) {
143            return new BasicUUID( b );
144        }
145    
146        private void bumpMajor() {
147    
148            // 48 bits only
149            majorId = ( majorId + 1L ) & 0x0000ffffffffffffL;
150            if ( majorId == 0L )
151                resetCounters();
152    
153        }
154    
155        private void resetCounters() {
156            timemillis = System.currentTimeMillis();
157            currentValue = INITIAL_VALUE;
158        }
159    }