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

org.apache.commons.id.uuid.state.StateHelper Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.id.uuid.state;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import java.util.StringTokenizer;

import org.apache.commons.id.DecoderException;
import org.apache.commons.discovery.tools.DiscoverClass;
import org.apache.commons.id.uuid.Bytes;
import org.apache.commons.id.uuid.Constants;
import org.apache.commons.id.uuid.clock.Clock;
import org.apache.commons.id.uuid.clock.OverClockedException;
import org.apache.commons.id.DigestUtils;
import org.apache.commons.id.Hex;

/**
 * 

StateHelper provides helper methods for the uuid state * implementations.

* * @author Commons-Id team * @version $Id: StateHelper.java 480488 2006-11-29 08:57:26Z bayard $ */ public final class StateHelper implements Constants { /** The key for the System.property containing the ClockImpl String. */ public static final String UUID_CLOCK_IMPL_PROPERTY_KEY = Clock.class.getName(); /** The key for the System.property containing the StateImpl String. */ public static final String UUID_STATE_IMPL_PROPERTY_KEY = State.class.getName(); /** Array length of node bytes. */ public static final int NODE_ID_BYTE_LENGTH = 6; /** Number of bytes in a short. */ public static final short BYTES_IN_SHORT = 2; /** Number of postitions to shift when shifting by one byte. */ public static final short SHIFT_BY_BYTE = 8; /** Number of postitions to shift when shifting by one byte. */ public static final short HOSTNAME_MAX_CHAR_LEN = 255; /** OR-Mask to set the node's multicast bit true. */ private static final int MULTICAST_BIT_SET = 0x80; /** The maximum character length of a long */ private static final short LONG_CHAR_LEN = 19; /** Standard one page buffer size */ private static final int BUF_PAGE_SZ = 1024; /** Start of the XML document used to store state persistence in XML */ protected static final String XML_DOC_START = "" + "\n\n" + " \n" + " \n" + " \n" + " \n]>" + "\n"; /** Start of XML node tag */ protected static final String XML_NODE_TAG_START = "\n\t"; /** End of the XML document used to store state persistence in XML */ protected static final String XML_DOC_END = "\n"; /** Number of tokens in a MAC address with "-" as separator */ private static final short MAC_ADDRESS_TOKEN_COUNT = 6; /** String length of a MAC address with "-" as separator */ private static final short MAC_ADDRESS_CHAR_LENGTH = 17; /** Default constructor */ private StateHelper() { super(); } /** *

Creates a Random node identifier as described in IEFT UUID URN * specification.

* * @return a random node idenfifier based on MD5 of system information. */ public static byte[] randomNodeIdentifier() { //Holds the 16 byte MD5 value byte[] seed = new byte[UUID_BYTE_LENGTH]; //Set the initial string buffer capacity //Time + Object.hashCode + HostName + Guess of all system properties int bufSize = (LONG_CHAR_LEN * 2) + HOSTNAME_MAX_CHAR_LEN + (2 * BUF_PAGE_SZ); StringBuffer randInfo = new StringBuffer(bufSize); //Add current time long time = 0; try { time = getClockImpl().getUUIDTime(); } catch (OverClockedException oce) { time = System.currentTimeMillis(); } randInfo.append(time); //Add hostname try { InetAddress address = InetAddress.getLocalHost(); randInfo.append(address.getHostName()); } catch (UnknownHostException ukhe) { randInfo.append("Host Unknown"); } //Add something else "random" randInfo.append(new Object().hashCode()); //Add system properties Collection info = System.getProperties().values(); Iterator it = info.iterator(); while (it.hasNext()) { randInfo.append(it.next()); } //MD5 Hash code the system information to get a node id. seed = DigestUtils.md5(randInfo.toString()); //Return upper 6 bytes of hash byte[] raw = new byte[NODE_ID_BYTE_LENGTH]; System.arraycopy(seed, 0, raw, 0, NODE_ID_BYTE_LENGTH); //Per draft set multi-cast bit true raw[0] |= MULTICAST_BIT_SET; return raw; } /** *

Generates a new security quality random clock sequence.

* * @return a new security quality random clock sequence. */ public static short newClockSequence() { Random random = new Random(); byte[] bytes = new byte[BYTES_IN_SHORT]; random.nextBytes(bytes); return (short) (Bytes.toShort(bytes) & 0x3FFF); } /** *

Returns the Clock implementation using commons discovery.

* * @return the Clock implementation using commons discovery. */ public static Clock getClockImpl() { Clock c = null; try { DiscoverClass dc = new DiscoverClass(); c = (Clock) dc.newInstance( Clock.class, Clock.DEFAULT_CLOCK_IMPL); } catch (Exception ex) { // ignore as default implementation will be used. } return c; } /** *

Returns the State implementation in use.

* * @return the State implementation in use. */ public static State getStateImpl() { State s = null; try { DiscoverClass dc = new DiscoverClass(); s = (State) dc.newInstance( State.class, State.DEFAULT_STATE_IMPL); } catch (Exception ex) { // ignore as default implementation will be used. } return s; } /** *

Utility method decodes a valid MAC address in the form of * XX-XX-XX-XX-XX-XX where each XX represents a hexidecimal value.

* *

Returns null if the address can not be decoded.

* * @param address the String hexidecimal dash separated MAC address. * @return a byte array representing the the address. Null if not a valid address. */ public static byte[] decodeMACAddress(String address) { StringBuffer buf = new StringBuffer(MAC_ADDRESS_TOKEN_COUNT * 2); StringTokenizer tokens = new StringTokenizer(address, "-"); if (tokens.countTokens() != MAC_ADDRESS_TOKEN_COUNT) { return null; } else { for (int i = 0; i < MAC_ADDRESS_TOKEN_COUNT; i++) { buf.append(tokens.nextToken()); } } try { char[] c = buf.toString().toCharArray(); return Hex.decodeHex(c); } catch (DecoderException de) { de.printStackTrace(); return null; } } /** *

Returns the node id / address byte array in it's hexidecimal string * representation in the following format: XX-XX-XX-XX-XX-XX where each XX * represents a hexidecimal value.

* * @param address the 6 byte node id / address. * @return the node id /address byte array in as hexidecimal with dash * separating each octet. * @throws IOException an Input Output Exception. */ public static String encodeMACAddress(byte[] address) throws IOException { char[] chars = Hex.encodeHex(address); StringBuffer buf = new StringBuffer(MAC_ADDRESS_CHAR_LENGTH); for (int i = 0; i < chars.length; i++) { buf.append(chars[i]); if (i != chars.length - 1 && i % 2 != 0) { buf.append("-"); } } return buf.toString().toUpperCase(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy