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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.named.ipc;
20  
21  import java.io.IOException;
22  import java.net.Inet6Address;
23  import java.net.InetAddress;
24  import java.net.InetSocketAddress;
25  import java.net.SocketAddress;
26  import java.net.StandardProtocolFamily;
27  import java.net.UnixDomainSocketAddress;
28  import java.net.UnknownHostException;
29  import java.nio.channels.ServerSocketChannel;
30  
31  /**
32   * Socket factory.
33   *
34   * @since 2.0.1
35   */
36  public enum SocketFamily {
37      inet,
38      unix;
39  
40      public ServerSocketChannel openServerSocket() throws IOException {
41          return switch (this) {
42              case inet -> ServerSocketChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
43              case unix -> ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(null, 0);
44              default -> throw new IllegalStateException();
45          };
46      }
47  
48      public static SocketAddress fromString(String str) {
49          if (str.startsWith("inet:")) {
50              String s = str.substring("inet:".length());
51              int ic = s.lastIndexOf(':');
52              String ia = s.substring(0, ic);
53              int is = ia.indexOf('/');
54              String h = ia.substring(0, is);
55              String a = ia.substring(is + 1);
56              String p = s.substring(ic + 1);
57              InetAddress addr;
58              if ("<unresolved>".equals(a)) {
59                  return InetSocketAddress.createUnresolved(h, Integer.parseInt(p));
60              } else {
61                  if (a.indexOf('.') > 0) {
62                      String[] as = a.split("\\.");
63                      if (as.length != 4) {
64                          throw new IllegalArgumentException("Unsupported socket address: '" + str + "'");
65                      }
66                      byte[] ab = new byte[4];
67                      for (int i = 0; i < 4; i++) {
68                          ab[i] = (byte) Integer.parseInt(as[i]);
69                      }
70                      try {
71                          addr = InetAddress.getByAddress(h.isEmpty() ? null : h, ab);
72                      } catch (UnknownHostException e) {
73                          throw new IllegalArgumentException("Unsupported address: " + str, e);
74                      }
75                  } else {
76                      throw new IllegalArgumentException("Unsupported address: " + str);
77                  }
78                  return new InetSocketAddress(addr, Integer.parseInt(p));
79              }
80          } else if (str.startsWith("unix:")) {
81              return UnixDomainSocketAddress.of(str.substring("unix:".length()));
82          } else {
83              throw new IllegalArgumentException("Unsupported socket address: '" + str + "'");
84          }
85      }
86  
87      public static String toString(SocketAddress address) {
88          switch (familyOf(address)) {
89              case inet:
90                  InetSocketAddress isa = (InetSocketAddress) address;
91                  String host = isa.getHostString();
92                  InetAddress addr = isa.getAddress();
93                  int port = isa.getPort();
94                  String formatted;
95                  if (addr == null) {
96                      formatted = host + "/<unresolved>";
97                  } else {
98                      formatted = addr.toString();
99                      if (addr instanceof Inet6Address) {
100                         int i = formatted.lastIndexOf("/");
101                         formatted = formatted.substring(0, i + 1) + "[" + formatted.substring(i + 1) + "]";
102                     }
103                 }
104                 return "inet:" + formatted + ":" + port;
105             case unix:
106                 // to keep address string unchanged across all OSes
107                 return "unix:" + address.toString().replace('\\', '/');
108             default:
109                 throw new IllegalArgumentException("Unsupported socket address: '" + address + "'");
110         }
111     }
112 
113     public static SocketFamily familyOf(SocketAddress address) {
114         if (address instanceof InetSocketAddress) {
115             return SocketFamily.inet;
116         } else if ("java.net.UnixDomainSocketAddress".equals(address.getClass().getName())) {
117             return SocketFamily.unix;
118         } else {
119             throw new IllegalArgumentException("Unsupported socket address '" + address + "'");
120         }
121     }
122 }