1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package org.jboss.netty.channel.local;
17
18 import java.net.SocketAddress;
19
20 /**
21 * An endpoint in the local transport. Each endpoint is identified by a unique
22 * case-insensitive string, except for the pre-defined value called
23 * {@code "ephemeral"}.
24 *
25 * <h3>Ephemeral Address</h3>
26 *
27 * An ephemeral address is an anonymous address which is assigned temporarily
28 * and is released as soon as the connection is closed. All ephemeral addresses
29 * have the same ID, {@code "ephemeral"}, but they are not equal to each other.
30 * @apiviz.landmark
31 */
32 public final class LocalAddress extends SocketAddress implements Comparable<LocalAddress> {
33
34 private static final long serialVersionUID = -3601961747680808645L;
35
36 public static final String EPHEMERAL = "ephemeral";
37
38 private final String id;
39 private final boolean ephemeral;
40
41 /**
42 * Creates a new instance with the specified ID.
43 */
44 public LocalAddress(int id) {
45 this(String.valueOf(id));
46 }
47
48 /**
49 * Creates a new instance with the specified ID.
50 */
51 public LocalAddress(String id) {
52 if (id == null) {
53 throw new NullPointerException("id");
54 }
55 id = id.trim().toLowerCase();
56 if (id.length() == 0) {
57 throw new IllegalArgumentException("empty id");
58 }
59 this.id = id;
60 ephemeral = "ephemeral".equals(id);
61 }
62
63 /**
64 * Returns the ID of this address.
65 */
66 public String getId() {
67 return id;
68 }
69
70 /**
71 * Returns {@code true} if and only if this address is ephemeral.
72 */
73 public boolean isEphemeral() {
74 return ephemeral;
75 }
76
77 @Override
78 public int hashCode() {
79 if (ephemeral) {
80 return System.identityHashCode(this);
81 } else {
82 return id.hashCode();
83 }
84 }
85
86 @Override
87 public boolean equals(Object o) {
88 if (!(o instanceof LocalAddress)) {
89 return false;
90 }
91
92 if (ephemeral) {
93 return this == o;
94 } else {
95 return getId().equals(((LocalAddress) o).getId());
96 }
97 }
98
99 // FIXME: This comparison is broken! Assign distinct port numbers for
100 // ephemeral ports, just like O/S does for port number 0. It will
101 // break backward compatibility though.
102
103 public int compareTo(LocalAddress o) {
104 if (ephemeral) {
105 if (o.ephemeral) {
106 if (this == o) {
107 return 0;
108 }
109
110 int a = System.identityHashCode(this);
111 int b = System.identityHashCode(o);
112 if (a < b) {
113 return -1;
114 } else if (a > b) {
115 return 1;
116 } else {
117 throw new Error(
118 "Two different ephemeral addresses have " +
119 "same identityHashCode.");
120 }
121 } else {
122 return 1;
123 }
124 } else {
125 if (o.ephemeral) {
126 return -1;
127 } else {
128 return getId().compareTo(o.getId());
129 }
130 }
131 }
132
133 @Override
134 public String toString() {
135 return "local:" + getId();
136 }
137 }