1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.net.Socket;
23 import java.net.SocketException;
24 import java.net.URLDecoder;
25 import java.util.Objects;
26
27 import javax.net.SocketFactory;
28
29
30
31
32
33
34
35
36
37
38
39 public abstract class AFUNIXSocketFactory extends AFSocketFactory<AFUNIXSocketAddress> {
40
41
42
43 protected AFUNIXSocketFactory() {
44 super(AFUNIXSocketAddress.class);
45 }
46
47 @Override
48 public Socket createSocket() throws SocketException {
49 return AFUNIXSocket.newInstance(this);
50 }
51
52 @Override
53 protected AFUNIXSocket connectTo(AFUNIXSocketAddress addr) throws IOException {
54 return AFUNIXSocket.connectTo(addr);
55 }
56
57
58
59
60
61
62 private abstract static class DefaultSocketHostnameSocketFactory extends AFUNIXSocketFactory {
63 private static final String PROP_SOCKET_HOSTNAME = "org.newsclub.net.unix.socket.hostname";
64
65
66
67
68 public DefaultSocketHostnameSocketFactory() {
69 super();
70 }
71
72 @Override
73 public final boolean isHostnameSupported(String host) {
74 return getDefaultSocketHostname().equals(host);
75 }
76
77 private static String getDefaultSocketHostname() {
78 return System.getProperty(PROP_SOCKET_HOSTNAME, "localhost");
79 }
80 }
81
82
83
84
85
86
87
88
89
90
91
92 public static final class FactoryArg extends DefaultSocketHostnameSocketFactory {
93 private final File socketFile;
94
95
96
97
98
99
100 public FactoryArg(String socketPath) {
101 super();
102 Objects.requireNonNull(socketPath, "Socket path was null");
103
104 this.socketFile = new File(socketPath);
105 }
106
107
108
109
110
111
112 public FactoryArg(File file) {
113 super();
114 Objects.requireNonNull(file, "File was null");
115
116 this.socketFile = file;
117 }
118
119 @Override
120 public AFUNIXSocketAddress addressFromHost(String host, int port) throws SocketException {
121 return AFUNIXSocketAddress.of(socketFile, port);
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136 public static final class SystemProperty extends DefaultSocketHostnameSocketFactory {
137 private static final String PROP_SOCKET_DEFAULT = "org.newsclub.net.unix.socket.default";
138
139
140
141
142 public SystemProperty() {
143 super();
144 }
145
146 @Override
147 public AFUNIXSocketAddress addressFromHost(String host, int port) throws SocketException {
148 String path = System.getProperty(PROP_SOCKET_DEFAULT);
149 if (path == null || path.isEmpty()) {
150 throw new IllegalStateException("Property not configured: " + PROP_SOCKET_DEFAULT);
151 }
152 File socketFile = new File(path);
153
154 return AFUNIXSocketAddress.of(socketFile, port);
155 }
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public static final class URIScheme extends AFUNIXSocketFactory {
171 private static final String FILE_SCHEME_PREFIX = "file://";
172 private static final String FILE_SCHEME_PREFIX_ENCODED = "file%";
173 private static final String FILE_SCHEME_LOCALHOST = "localhost";
174
175
176
177
178 public URIScheme() {
179 super();
180 }
181
182 private static String stripBrackets(String host) {
183 if (host.startsWith("[")) {
184 if (host.endsWith("]")) {
185 host = host.substring(1, host.length() - 1);
186 } else {
187 host = host.substring(1);
188 }
189 }
190 return host;
191 }
192
193 @Override
194 public boolean isHostnameSupported(String host) {
195 host = stripBrackets(host);
196 return host.startsWith(FILE_SCHEME_PREFIX) || host.startsWith(FILE_SCHEME_PREFIX_ENCODED);
197 }
198
199 @Override
200 public AFUNIXSocketAddress addressFromHost(String host, int port) throws SocketException {
201 host = stripBrackets(host);
202 if (host.startsWith(FILE_SCHEME_PREFIX_ENCODED)) {
203 try {
204 host = URLDecoder.decode(host, "UTF-8");
205 } catch (Exception e) {
206 throw (SocketException) new SocketException().initCause(e);
207 }
208 }
209 if (!host.startsWith(FILE_SCHEME_PREFIX)) {
210 throw new SocketException("Unsupported scheme");
211 }
212
213 String path = host.substring(FILE_SCHEME_PREFIX.length());
214 if (path.startsWith(FILE_SCHEME_LOCALHOST)) {
215 path = path.substring(FILE_SCHEME_LOCALHOST.length());
216 }
217 if (path.isEmpty()) {
218 throw new SocketException("Path is empty");
219 }
220 if (!path.startsWith("/")) {
221 throw new SocketException("Path must be absolute");
222 }
223
224 File socketFile = new File(path);
225 return AFUNIXSocketAddress.of(socketFile, port);
226 }
227 }
228 }