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 }