1 package com.github.davidmoten.aws.lw.client.internal.util;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.UncheckedIOException;
7 import java.io.UnsupportedEncodingException;
8 import java.net.HttpURLConnection;
9 import java.net.MalformedURLException;
10 import java.net.URL;
11 import java.net.URLEncoder;
12 import java.nio.charset.StandardCharsets;
13 import java.security.MessageDigest;
14 import java.security.NoSuchAlgorithmException;
15 import java.util.Locale;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Optional;
19
20
21
22
23 public final class Util {
24
25 private Util() {
26
27 }
28
29 public static HttpURLConnection createHttpConnection(URL endpointUrl, String httpMethod,
30 Map<String, String> headers, int connectTimeoutMs, int readTimeoutMs) throws IOException {
31 Preconditions.checkNotNull(headers);
32 HttpURLConnection connection = (HttpURLConnection) endpointUrl.openConnection();
33 connection.setRequestMethod(httpMethod);
34
35 for (Entry<String, String> entry : headers.entrySet()) {
36 connection.setRequestProperty(entry.getKey(), entry.getValue());
37 }
38
39 connection.setUseCaches(false);
40 connection.setDoInput(true);
41 connection.setDoOutput(true);
42 connection.setConnectTimeout(connectTimeoutMs);
43 connection.setReadTimeout(readTimeoutMs);
44 return connection;
45 }
46
47 public static String canonicalMetadataKey(String meta) {
48 StringBuilder b = new StringBuilder();
49 String s = meta.toLowerCase(Locale.ENGLISH);
50 for (int ch : s.toCharArray()) {
51 if (Character.isDigit(ch) || Character.isAlphabetic(ch)) {
52 b.append((char) ch);
53 }
54 }
55 return b.toString();
56 }
57
58
59
60
61
62
63
64
65 public static String toHex(byte[] data) {
66 StringBuilder sb = new StringBuilder(data.length * 2);
67 for (int i = 0; i < data.length; i++) {
68 String hex = Integer.toHexString(data[i]);
69 if (hex.length() == 1) {
70
71 sb.append("0");
72 } else if (hex.length() == 8) {
73
74 hex = hex.substring(6);
75 }
76 sb.append(hex);
77 }
78 return sb.toString().toLowerCase(Locale.getDefault());
79 }
80
81 public static URL toUrl(String url) {
82 try {
83 return new URL(url);
84 } catch (MalformedURLException e) {
85 throw new RuntimeException(e);
86 }
87 }
88
89 public static String urlEncode(String url, boolean keepPathSlash) {
90 return urlEncode(url, keepPathSlash, "UTF-8");
91 }
92
93
94 static String urlEncode(String url, boolean keepPathSlash, String charset) {
95 String encoded;
96 try {
97 encoded = URLEncoder.encode(url, charset).replace("+", "%20");
98 } catch (UnsupportedEncodingException e) {
99 throw new RuntimeException(e);
100 }
101 if (keepPathSlash) {
102 return encoded.replace("%2F", "/");
103 } else {
104 return encoded;
105 }
106 }
107
108
109
110
111 public static byte[] sha256(String text) {
112 return sha256(text.getBytes(StandardCharsets.UTF_8));
113 }
114
115 public static byte[] sha256(byte[] data) {
116 return hash(data, "SHA-256");
117 }
118
119
120 static byte[] hash(byte[] data, String algorithm) {
121 try {
122 MessageDigest md = MessageDigest.getInstance(algorithm);
123 md.update(data);
124 return md.digest();
125 } catch (NoSuchAlgorithmException e) {
126 throw new RuntimeException(e);
127 }
128 }
129
130 public static byte[] readBytesAndClose(InputStream in) {
131 try {
132 byte[] buffer = new byte[8192];
133 int n;
134 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
135 while ((n = in.read(buffer)) != -1) {
136 bytes.write(buffer, 0, n);
137 }
138 return bytes.toByteArray();
139 } catch (IOException e) {
140 throw new UncheckedIOException(e);
141 } finally {
142 try {
143 in.close();
144 } catch (IOException e) {
145 throw new UncheckedIOException(e);
146 }
147 }
148 }
149
150 private static final InputStream EMPTY_INPUT_STREAM = new InputStream() {
151 @Override
152 public int read() throws IOException {
153 return -1;
154 }
155 };
156
157 public static final InputStream emptyInputStream() {
158 return EMPTY_INPUT_STREAM;
159 }
160
161 public static Optional<String> jsonFieldText(String json, String fieldName) {
162
163 String key = "\"" + fieldName + "\"";
164 int keyPosition = json.indexOf(key);
165 if (keyPosition == -1) {
166 return Optional.empty();
167 }
168
169
170 int colonPosition = json.indexOf(":", keyPosition + key.length());
171 if (colonPosition == -1) {
172 return Optional.empty();
173 }
174
175
176 int valueStart = colonPosition + 1;
177 while (valueStart < json.length() && Character.isWhitespace(json.charAt(valueStart))) {
178 valueStart++;
179 }
180
181
182 boolean isString = json.charAt(valueStart) == '"';
183 StringBuilder value = new StringBuilder();
184 boolean isEscaped = false;
185
186
187 for (int i = valueStart + (isString ? 1 : 0); i < json.length(); i++) {
188 char c = json.charAt(i);
189
190 if (isString) {
191
192 if (isEscaped) {
193
194 value.append(c);
195 isEscaped = false;
196 } else if (c == '\\') {
197
198 isEscaped = true;
199 } else if (c == '"') {
200
201 break;
202 } else {
203 value.append(c);
204 }
205 } else {
206
207 if (c == ',' || c == '}') {
208
209 break;
210 } else {
211 value.append(c);
212 }
213 }
214 }
215 String v = value.toString().trim();
216 if (!isString && "null".equals(v)) {
217 return Optional.empty();
218 } else {
219 return Optional.of(v);
220 }
221 }
222 }