15
15
16
16
import java .io .ByteArrayOutputStream ;
17
17
import java .io .File ;
18
+ import java .io .FileNotFoundException ;
18
19
import java .io .IOException ;
19
20
import java .io .InputStream ;
20
21
import java .net .HttpURLConnection ;
21
- import java .net .MalformedURLException ;
22
22
import java .net .URI ;
23
23
import java .net .URISyntaxException ;
24
24
import java .net .URL ;
25
25
import java .net .URLConnection ;
26
26
import java .nio .charset .StandardCharsets ;
27
27
import java .nio .file .Files ;
28
28
import java .nio .file .StandardCopyOption ;
29
+ import java .util .ArrayList ;
30
+ import java .util .List ;
29
31
30
32
public final class DownloadUtils {
31
33
private static final TypeAdapter <String > STRING = new TypeAdapter <String >() {
@@ -42,6 +44,7 @@ public String read(JsonReader in) throws IOException {
42
44
}
43
45
return in .nextString ();
44
46
}
47
+
45
48
@ Override
46
49
public void write (JsonWriter out , String value ) throws IOException {
47
50
out .value (value );
@@ -69,114 +72,145 @@ public String read(final JsonReader in) throws IOException {
69
72
})
70
73
.create ();
71
74
72
- private static @ Nullable URLConnection getConnection (String address ) {
75
+ private static final int TIMEOUT = 5 * 1000 ;
76
+ private static final int MAX_REDIRECTS = 3 ;
77
+
78
+ private static URLConnection getConnection (String address ) throws IOException {
73
79
URI uri ;
74
- URL url ;
75
80
try {
76
81
uri = new URI (address );
77
- url = uri .toURL ();
78
- } catch (MalformedURLException | URISyntaxException e ) {
79
- Log .error ("Malformed URL: " + address );
80
- e .printStackTrace (Log .ERROR );
81
- return null ;
82
+ } catch (URISyntaxException e ) {
83
+ throw new IOException (e );
82
84
}
85
+ URL url = uri .toURL ();
83
86
84
- try {
85
- int timeout = 5 * 1000 ;
86
- int max_redirects = 3 ;
87
-
88
- URLConnection con = null ;
89
- for (int x = 0 ; x < max_redirects ; x ++) {
90
- con = url .openConnection ();
91
- con .setConnectTimeout (timeout );
92
- con .setReadTimeout (timeout );
93
-
94
- if (con instanceof HttpURLConnection ) {
95
- HttpURLConnection hcon = (HttpURLConnection ) con ;
96
- hcon .setRequestProperty ("User-Agent" , "MinecraftMaven" );
97
- hcon .setRequestProperty ("accept" , "application/json" );
98
- hcon .setInstanceFollowRedirects (false );
99
-
100
- int res = hcon .getResponseCode ();
101
- if (res == HttpURLConnection .HTTP_MOVED_PERM || res == HttpURLConnection .HTTP_MOVED_TEMP ) {
102
- String location = hcon .getHeaderField ("Location" );
103
- hcon .disconnect ();
104
- if (x == max_redirects - 1 ) {
105
- Log .error ("Invalid number of redirects: " + location );
106
- return null ;
107
- } else {
108
- Log .debug ("Following redirect: " + location );
109
- uri = uri .resolve (location );
110
- url = uri .toURL ();
111
- }
112
- } else if (res == 404 ) {
113
- // File not found
114
- return null ;
115
- } else {
116
- break ;
117
- }
87
+ List <String > redirections = new ArrayList <>();
88
+ URLConnection con ;
89
+ for (int redirects = 0 ; ; redirects ++) {
90
+ con = url .openConnection ();
91
+ con .setConnectTimeout (TIMEOUT );
92
+ con .setReadTimeout (TIMEOUT );
93
+
94
+ if (!(con instanceof HttpURLConnection )) break ;
95
+
96
+ HttpURLConnection hcon = (HttpURLConnection ) con ;
97
+ hcon .setRequestProperty ("User-Agent" , "MinecraftMaven" );
98
+ hcon .setRequestProperty ("accept" , "application/json" );
99
+ hcon .setInstanceFollowRedirects (false );
100
+
101
+ int res = hcon .getResponseCode ();
102
+ if (res == HttpURLConnection .HTTP_MOVED_PERM || res == HttpURLConnection .HTTP_MOVED_TEMP ) {
103
+ String location = hcon .getHeaderField ("Location" );
104
+ redirections .add (location );
105
+ hcon .disconnect ();
106
+
107
+ if (redirects == MAX_REDIRECTS - 1 ) {
108
+ throw new IOException (String .format (
109
+ "Too many redirects: %s -- redirections: [%s]" ,
110
+ address , String .join (", " , redirections )
111
+ ));
118
112
} else {
119
- break ;
113
+ Log .debug ("Following redirect: " + location );
114
+ uri = uri .resolve (location );
115
+ url = uri .toURL ();
120
116
}
117
+ } else if (res == 404 ) {
118
+ throw new FileNotFoundException ("Returned 404: " + address );
119
+ } else {
120
+ break ;
121
121
}
122
- return con ;
123
- } catch (IOException e ) {
124
- Log .error ("Failed to establish connection to " + address );
125
- e .printStackTrace (Log .ERROR );
126
- return null ;
127
122
}
123
+
124
+ return con ;
128
125
}
129
126
130
127
/**
131
128
* Downloads a string from the given URL, effectively acting as {@code curl}.
132
129
*
133
130
* @param url The URL to download from
131
+ * @return The downloaded string
132
+ * @throws IOException If the download failed
133
+ */
134
+ public static String downloadString (String url ) throws IOException {
135
+ URLConnection connection = getConnection (url );
136
+ try (InputStream stream = connection .getInputStream ();
137
+ ByteArrayOutputStream out = new ByteArrayOutputStream ();
138
+ ) {
139
+ byte [] buf = new byte [1024 ];
140
+ int n ;
141
+ while ((n = stream .read (buf )) > 0 ) {
142
+ out .write (buf , 0 , n );
143
+ }
144
+
145
+ return new String (out .toByteArray (), StandardCharsets .UTF_8 );
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Downloads a string from the given URL, effectively acting as {@code curl}.
151
+ * <p>Returns {@code null} on failure.</p>
152
+ *
153
+ * @param url The URL to download from
134
154
* @return The downloaded string, or {@code null} if the download failed
135
155
*/
136
- public static @ Nullable String downloadString ( String url ) {
156
+ public static @ Nullable String tryDownloadString ( boolean silent , String url ) {
137
157
try {
138
- URLConnection connection = getConnection (url );
139
- if (connection != null ) {
140
- try (InputStream stream = connection .getInputStream ();
141
- ByteArrayOutputStream out = new ByteArrayOutputStream ();
142
- ) {
143
- byte [] buf = new byte [1024 ];
144
- int n ;
145
- while ((n = stream .read (buf )) > 0 ) {
146
- out .write (buf , 0 , n );
147
- }
148
-
149
- return new String (out .toByteArray (), StandardCharsets .UTF_8 );
150
- }
151
- }
158
+ return downloadString (url );
152
159
} catch (IOException e ) {
153
- Log .warn ("Failed to download " + url );
154
- e .printStackTrace (Log .WARN );
160
+ if (!silent ) {
161
+ Log .warn ("Failed to download " + url );
162
+ e .printStackTrace (Log .WARN );
163
+ }
164
+
165
+ return null ;
155
166
}
156
- return null ;
157
167
}
158
168
159
169
/**
160
170
* Downloads a file from the given URL into the target file, effectively acting as {@code wget}.
161
171
*
162
172
* @param target The file to download to
163
173
* @param url The URL to download from
174
+ * @throws IOException If the download failed
175
+ */
176
+ public static void downloadFile (File target , String url ) throws IOException {
177
+ downloadFile (false , target , url );
178
+ }
179
+
180
+ /**
181
+ * Downloads a file from the given URL into the target file, effectively acting as {@code wget}.
182
+ *
183
+ * @param silent If no log messages should be sent
184
+ * @param target The file to download to
185
+ * @param url The URL to download from
186
+ * @throws IOException If the download failed
187
+ */
188
+ public static void downloadFile (boolean silent , File target , String url ) throws IOException {
189
+ if (!silent ) Log .quiet ("Downloading " + url );
190
+
191
+ URLConnection connection = getConnection (url );
192
+ Files .createDirectories (target .toPath ().getParent ());
193
+ Files .copy (connection .getInputStream (), target .toPath (), StandardCopyOption .REPLACE_EXISTING );
194
+ }
195
+
196
+ /**
197
+ * Attempts to download a file from the given URL into the target file, effectively acting as {@code wget}.
198
+ *
199
+ * @param target The file to download to
200
+ * @param url The URL to download from
164
201
* @return {@code true} if the download was successful
165
202
*/
166
- public static boolean downloadFile ( File target , String url ) {
203
+ public static boolean tryDownloadFile ( boolean silent , File target , String url ) {
167
204
try {
168
- Files .createDirectories (target .toPath ().getParent ());
169
- Log .quiet ("Downloading " + url );
170
-
171
- URLConnection connection = getConnection (url );
172
- if (connection != null ) {
173
- Files .copy (connection .getInputStream (), target .toPath (), StandardCopyOption .REPLACE_EXISTING );
174
- return true ;
175
- }
205
+ downloadFile (silent , target , url );
206
+ return true ;
176
207
} catch (IOException e ) {
177
- Log .warn ("Failed to download " + url );
178
- e .printStackTrace (Log .WARN );
208
+ if (!silent ) {
209
+ Log .warn ("Failed to download " + url );
210
+ e .printStackTrace (Log .WARN );
211
+ }
212
+
213
+ return false ;
179
214
}
180
- return false ;
181
215
}
182
216
}
0 commit comments