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