View Javadoc
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 }