001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data;
017:
018: /**
019: * Default implementation of the FeatureLockFactory. Generates id numbers.
020: *
021: * @author Jody Garnett, Refractions Research, Inc.
022: * @author Chris Holmes, TOPP.
023: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/data/DefaultFeatureLockFactory.java $
024: * @version $Id: DefaultFeatureLockFactory.java 20651 2006-07-21 07:51:54Z jgarnett $
025: *
026: * @task REVISIT: Should more of this code move to the parent? I guess if
027: * other implementations came along they may want to implement
028: * differently.
029: * @task REVISIT: The generation code can move to the parent. Even if other
030: * implementations come along we do not want the to implement the
031: * generation differently.
032: */
033: public class DefaultFeatureLockFactory extends FeatureLockFactory {
034: /** Count used to generate unique ID numbers */
035: static long count = 0;
036:
037: protected FeatureLock createLock(String name, long duration) {
038: long number = nextIdNumber(duration);
039:
040: return new DefaultFeatureLock(name + "_"
041: + Long.toString(number, 16), duration);
042: }
043:
044: /**
045: * Package visiable generate function for JUnit tests
046: *
047: * @param name The name to give this lock.
048: * @param duration How long it is to last.
049: *
050: * @return The new FeatureLock.
051: */
052: static FeatureLock createTestLock(String name, long duration) {
053: return new DefaultFeatureLock(name, duration);
054: }
055:
056: /**
057: * Used to seed nextIDNumber to allow for reproduceable JUnit tests. Not
058: * part of the public API - package protected method used for JUnits
059: * Tests
060: *
061: * @param seed The number to start seeding with.
062: */
063: static void seedIdNumber(long seed) {
064: count = seed;
065: }
066:
067: /**
068: * Produces the next ID number based on count, duration and the current
069: * time. The uniquity is 'good enough' although not provable as per
070: * security systems. The method used will probably have to be changed
071: * later, the api is what is important right now.
072: * <table border=1, bgcolor="lightgray", width="100%"><tr><td><code><pre>
073: * count: 000000000000000000000000000001011 (increasing count)
074: * date: 000000000001111010101010101000000 (expriry date milliseconds usually empty)
075: * now: 000101100111011010011111000000000 (bit order reverse of current time)
076: * ---------------------------------
077: * number: 000101100110100000110101001001011
078: * </pre></code></td></tr></table>
079: * Once again method is package visible for testing.
080: *
081: * @param duration The time for the lock to last.
082: *
083: * @return The next generated id number.
084: */
085: static long nextIdNumber(long duration) {
086: long number;
087: long now = System.currentTimeMillis();
088: long time = now + duration;
089:
090: // start of with number
091: count++;
092: number = count;
093: number = number ^ time; // count fills 'empty' milliseconds
094:
095: StringBuffer reverse = new StringBuffer(asBits(now));
096: now = Long.parseLong(reverse.reverse().toString(), 2); // flip now around
097:
098: number = number ^ now;
099:
100: return number;
101: }
102:
103: /**
104: * Utility method used to reverse bits.
105: * <p>
106: * Since generating ID numbers is not performance critical I won't care
107: * right now.
108: * </p>
109: *
110: * @param number
111: * @return Number represented as bits
112: */
113: private static String asBits(long number) {
114: long yum = number;
115: StringBuffer buf = new StringBuffer(32);
116:
117: for (int i = 0; i < 63; i++) {
118: buf.append(yum & 1);
119: yum = yum >> 1;
120: }
121:
122: buf.reverse();
123:
124: return buf.toString();
125: }
126: }
|