001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.named.ipc; 020 021import java.io.IOException; 022import java.net.Inet6Address; 023import java.net.InetAddress; 024import java.net.InetSocketAddress; 025import java.net.SocketAddress; 026import java.net.StandardProtocolFamily; 027import java.net.UnixDomainSocketAddress; 028import java.net.UnknownHostException; 029import java.nio.channels.ServerSocketChannel; 030 031/** 032 * Socket factory. 033 * 034 * @since 2.0.1 035 */ 036public enum SocketFamily { 037 inet, 038 unix; 039 040 public ServerSocketChannel openServerSocket() throws IOException { 041 switch (this) { 042 case inet: 043 return ServerSocketChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); 044 case unix: 045 return ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(null, 0); 046 default: 047 throw new IllegalStateException(); 048 } 049 } 050 051 public static SocketAddress fromString(String str) { 052 if (str.startsWith("inet:")) { 053 String s = str.substring("inet:".length()); 054 int ic = s.lastIndexOf(':'); 055 String ia = s.substring(0, ic); 056 int is = ia.indexOf('/'); 057 String h = ia.substring(0, is); 058 String a = ia.substring(is + 1); 059 String p = s.substring(ic + 1); 060 InetAddress addr; 061 if ("<unresolved>".equals(a)) { 062 return InetSocketAddress.createUnresolved(h, Integer.parseInt(p)); 063 } else { 064 if (a.indexOf('.') > 0) { 065 String[] as = a.split("\\."); 066 if (as.length != 4) { 067 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'"); 068 } 069 byte[] ab = new byte[4]; 070 for (int i = 0; i < 4; i++) { 071 ab[i] = (byte) Integer.parseInt(as[i]); 072 } 073 try { 074 addr = InetAddress.getByAddress(h.isEmpty() ? null : h, ab); 075 } catch (UnknownHostException e) { 076 throw new IllegalArgumentException("Unsupported address: " + str, e); 077 } 078 } else { 079 throw new IllegalArgumentException("Unsupported address: " + str); 080 } 081 return new InetSocketAddress(addr, Integer.parseInt(p)); 082 } 083 } else if (str.startsWith("unix:")) { 084 return UnixDomainSocketAddress.of(str.substring("unix:".length())); 085 } else { 086 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'"); 087 } 088 } 089 090 public static String toString(SocketAddress address) { 091 switch (familyOf(address)) { 092 case inet: 093 InetSocketAddress isa = (InetSocketAddress) address; 094 String host = isa.getHostString(); 095 InetAddress addr = isa.getAddress(); 096 int port = isa.getPort(); 097 String formatted; 098 if (addr == null) { 099 formatted = host + "/<unresolved>"; 100 } else { 101 formatted = addr.toString(); 102 if (addr instanceof Inet6Address) { 103 int i = formatted.lastIndexOf("/"); 104 formatted = formatted.substring(0, i + 1) + "[" + formatted.substring(i + 1) + "]"; 105 } 106 } 107 return "inet:" + formatted + ":" + port; 108 case unix: 109 // to keep address string unchanged across all OSes 110 return "unix:" + address.toString().replace('\\', '/'); 111 default: 112 throw new IllegalArgumentException("Unsupported socket address: '" + address + "'"); 113 } 114 } 115 116 public static SocketFamily familyOf(SocketAddress address) { 117 if (address instanceof InetSocketAddress) { 118 return SocketFamily.inet; 119 } else if ("java.net.UnixDomainSocketAddress".equals(address.getClass().getName())) { 120 return SocketFamily.unix; 121 } else { 122 throw new IllegalArgumentException("Unsupported socket address '" + address + "'"); 123 } 124 } 125}