View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.services.persistence.generic.primarykey;
18  
19  import java.net.InetAddress;
20  import java.net.UnknownHostException;
21  import java.security.SecureRandom;
22  
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  
26  import ch.elca.el4j.util.codingsupport.annotations.FindBugsSuppressWarnings;
27  
28  /**
29   * This key generator generates UUIDs as described in "EJB Design Patterns", F.
30   * Marinescu, pages 112-116. It is a simplified version of the algorithm
31   * presented in
32   * http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt
33   *
34   * The returned UUID is a hex-encoded 32-digit number.
35   *
36   * @svnLink $Revision: 4010 $;$Date: 2009-12-01 10:59:54 +0100 (Di, 01. Dez 2009) $;$Author: jonasha $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/core/src/main/java/ch/elca/el4j/services/persistence/generic/primarykey/UuidPrimaryKeyGenerator.java $
37   *
38   * @author Martin Zeltner (MZE)
39   */
40  public class UuidPrimaryKeyGenerator implements PrimaryKeyGenerator {
41  	/**
42  	 * Private logger of this class.
43  	 */
44  	private static Logger s_logger
45  		= LoggerFactory.getLogger(UuidPrimaryKeyGenerator.class);
46  
47  	/**
48  	 * Middle value.
49  	 */
50  	private String m_midValue;
51  	
52  	/**
53  	 * Seeder.
54  	 */
55  	private SecureRandom m_seeder;
56  	
57  	/**
58  	 * String aaray with zeros.
59  	 */
60  	private String[] m_zeros;
61  
62  	/**
63  	 * Default constructor.
64  	 */
65  	public UuidPrimaryKeyGenerator() {
66  		init();
67  	}
68  
69  	/**
70  	 * {@inheritDoc}
71  	 */
72  	@FindBugsSuppressWarnings(value = "INT_VACUOUS_BIT_OPERATION", 
73  							justification = "Ensures that no rounding takes place")
74  	public String getPrimaryKey() {
75  		long time = System.currentTimeMillis();
76  		int timeLow = (int) time & 0xFFFFFFFF;
77  		int value = m_seeder.nextInt();
78  		String keyString = toHexString(timeLow) + m_midValue
79  			+ toHexString(value);
80  		return keyString;
81  	}
82  
83  	// Checkstyle: MagicNumber off
84  	/**
85  	 * Initalize the primary key generator.
86  	 */
87  	private void init() {
88  		// Fill the m_zeros table
89  		final int ZERO_ARRAY_LENGTH = 8;
90  		m_zeros = new String[ZERO_ARRAY_LENGTH];
91  		m_zeros[0] = "";
92  		for (int i = 1; i < ZERO_ARRAY_LENGTH; i++) {
93  			m_zeros[i] = m_zeros[i - 1] + "0";
94  		}
95  
96  		// Get the IP address as an hex string
97  		byte[] bytes = null;
98  		try {
99  			InetAddress inetAddress = InetAddress.getLocalHost();
100 			bytes = inetAddress.getAddress();
101 		} catch (UnknownHostException npe) {
102 			s_logger.debug("Host ip could not be found. Following "
103 				+ "will be used: 127.0.0.1");
104 			bytes = new byte[] {1, 0, 0, 127};
105 		}
106 		int intAddress = 0;
107 		for (int i = 0; i < bytes.length; i++) {
108 			int unsignedByte = bytes[i] & 0xFF;
109 			intAddress = (intAddress + unsignedByte) << 8;
110 		}
111 		String hexInetAddress = toHexString(intAddress);
112 
113 		String thisHashCode = toHexString(System.identityHashCode(this));
114 
115 		m_midValue = hexInetAddress + thisHashCode;
116 
117 		m_seeder = new SecureRandom();
118 	}
119 
120 	/**
121 	 * Method to convert from decimal to hexadecimal.
122 	 *
123 	 * @param i Is the given decimal number.
124 	 * @return Returns the hexadecimal value of given decimal number.
125 	 */
126 	private String toHexString(int i) {
127 		String hex = Integer.toHexString(i);
128 		int hexLength = hex.length();
129 		return m_zeros[8 - hexLength] + hex;
130 	}
131 	// Checkstyle: MagicNumber on
132 }
133