1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package net.jini.core.lookup; 20 21 import java.io.DataInput; 22 import java.io.DataOutput; 23 import java.io.IOException; 24 import java.io.InvalidObjectException; 25 import java.io.ObjectOutputStream; 26 import java.io.Serializable; 27 import org.apache.river.api.io.AtomicSerial; 28 import org.apache.river.api.io.AtomicSerial.GetArg; 29 30 /** 31 * A universally unique identifier (UUID) for registered services. 32 * A service ID is a 128-bit value. Service IDs are normally intended to 33 * either be built into services at manufacture or deployment time, or 34 * generated dynamically by lookup services at registration time. <p> 35 * 36 * The most significant long can be decomposed into the following 37 * unsigned fields: 38 * <pre> 39 * 0xFFFFFFFF00000000 time_low 40 * 0x00000000FFFF0000 time_mid 41 * 0x000000000000F000 version 42 * 0x0000000000000FFF time_hi 43 * </pre> 44 * The least significant long can be decomposed into the following 45 * unsigned fields: 46 * <pre> 47 * 0xC000000000000000 variant 48 * 0x3FFF000000000000 clock_seq 49 * 0x0000FFFFFFFFFFFF node 50 * </pre> 51 * The variant field must be 0x2. The version field must be either 0x1 or 0x4. 52 * If the version field is 0x4, then the remaining fields are set to values 53 * produced by a cryptographically secure random sequence. If the version 54 * field is 0x1, then the node field is set to an IEEE 802 address, the 55 * clock_seq field is set to a 14-bit random number, and the time_low, 56 * time_mid, and time_hi fields are set to the least, middle and most 57 * significant bits (respectively) of a 60-bit timestamp measured in 58 * 100-nanosecond units since midnight, October 15, 1582 UTC. 59 * 60 * @author Sun Microsystems, Inc. 61 * @since 1.0 62 */ 63 @AtomicSerial 64 public final class ServiceID implements Serializable { 65 66 private static final long serialVersionUID = -7803375959559762239L; 67 68 /** 69 * The most significant 64 bits. 70 * 71 * @serial 72 */ 73 private final long mostSig; 74 /** 75 * The least significant 64 bits. 76 * 77 * @serial 78 */ 79 private final long leastSig; 80 81 private static long mostSig(GetArg arg) throws IOException{ 82 long mostSig = arg.get("mostSig", 0L); 83 // if (mostSig == 0L) 84 // throw new InvalidObjectException("mostSig not allowed to be 0L"); 85 return mostSig; 86 } 87 88 private static long leastSig(GetArg arg) throws IOException{ 89 long leastSig = arg.get("leastSig", 0L); 90 // if (leastSig == 0L) 91 // throw new InvalidObjectException("leastSig not allowed to be 0L"); 92 return leastSig; 93 } 94 95 ServiceID(GetArg arg) throws IOException{ 96 this(mostSig(arg), leastSig(arg)); 97 } 98 99 /** 100 * Simple constructor. 101 * 102 * @param mostSig the most significant 64 bits 103 * @param leastSig the lease significant 64 bits 104 */ 105 public ServiceID(long mostSig, long leastSig) { 106 this.mostSig = mostSig; 107 this.leastSig = leastSig; 108 } 109 110 /** 111 * Reads in 16 bytes in standard network byte order. 112 * 113 * @param in the input stream to read 16 bytes from 114 * @throws IOException if there is a problem 115 * reading the most and least significant bits 116 */ 117 public ServiceID(DataInput in) throws IOException { 118 this.mostSig = in.readLong(); 119 this.leastSig = in.readLong(); 120 } 121 122 /** Returns the most significant 64 bits of the service ID. 123 * 124 * @return a <tt>long</tt> representing the most significant bits value 125 */ 126 public long getMostSignificantBits() { 127 return mostSig; 128 } 129 130 /** Returns the least significant 64 bits of the service ID. 131 * 132 * @return a <tt>long</tt> representing the least significant bits value 133 */ 134 135 public long getLeastSignificantBits() { 136 return leastSig; 137 } 138 139 /** 140 * Writes out 16 bytes in standard network byte order. 141 * 142 * @param out the output stream to which 16 bytes should be written 143 * @throws IOException if there is a problem writing the bytes 144 */ 145 public void writeBytes(DataOutput out) throws IOException { 146 out.writeLong(mostSig); 147 out.writeLong(leastSig); 148 } 149 150 public int hashCode() { 151 return (int)((mostSig >> 32) ^ mostSig ^ (leastSig >> 32) ^ leastSig); 152 } 153 154 /** 155 * Service IDs are equal if they represent the same 128-bit value. 156 */ 157 public boolean equals(Object obj) { 158 if (!(obj instanceof ServiceID)) 159 return false; 160 ServiceID sid = (ServiceID)obj; 161 return (mostSig == sid.mostSig && leastSig == sid.leastSig); 162 } 163 164 /** 165 * Returns a 36-character string of five fields separated by hyphens, with 166 * each field represented in lowercase hexadecimal with the same number of 167 * digits as in the field. The order of fields is: <code>time_low</code>, 168 * <code>time_mid</code>, <code>version</code> and <code>time_hi</code> 169 * treated as a single field, <code>variant</code> and 170 * <code>clock_seq</code> treated as a single field, and <code>node</code>. 171 */ 172 public String toString() { 173 return (digits(mostSig >> 32, 8) + "-" + 174 digits(mostSig >> 16, 4) + "-" + 175 digits(mostSig, 4) + "-" + 176 digits(leastSig >> 48, 4) + "-" + 177 digits(leastSig, 12)); 178 } 179 180 /** Returns val represented by the specified number of hex digits. */ 181 private static String digits(long val, int digits) { 182 long hi = 1L << (digits * 4); 183 return Long.toHexString(hi | (val & (hi - 1))).substring(1); 184 } 185 186 private void writeObject(ObjectOutputStream out) throws IOException { 187 out.defaultWriteObject(); 188 } 189 }