1515
1616import java .io .ByteArrayOutputStream ;
1717import java .io .File ;
18+ import java .io .FileNotFoundException ;
1819import java .io .IOException ;
1920import java .io .InputStream ;
2021import java .net .HttpURLConnection ;
21- import java .net .MalformedURLException ;
2222import java .net .URI ;
2323import java .net .URISyntaxException ;
2424import java .net .URL ;
2525import java .net .URLConnection ;
2626import java .nio .charset .StandardCharsets ;
2727import java .nio .file .Files ;
2828import java .nio .file .StandardCopyOption ;
29+ import java .util .ArrayList ;
30+ import java .util .List ;
2931
3032public final class DownloadUtils {
3133 private static final TypeAdapter <String > STRING = new TypeAdapter <String >() {
@@ -42,6 +44,7 @@ public String read(JsonReader in) throws IOException {
4244 }
4345 return in .nextString ();
4446 }
47+
4548 @ Override
4649 public void write (JsonWriter out , String value ) throws IOException {
4750 out .value (value );
@@ -69,114 +72,145 @@ public String read(final JsonReader in) throws IOException {
6972 })
7073 .create ();
7174
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 {
7379 URI uri ;
74- URL url ;
7580 try {
7681 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 );
8284 }
85+ URL url = uri .toURL ();
8386
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+ ));
118112 } else {
119- break ;
113+ Log .debug ("Following redirect: " + location );
114+ uri = uri .resolve (location );
115+ url = uri .toURL ();
120116 }
117+ } else if (res == 404 ) {
118+ throw new FileNotFoundException ("Returned 404: " + address );
119+ } else {
120+ break ;
121121 }
122- return con ;
123- } catch (IOException e ) {
124- Log .error ("Failed to establish connection to " + address );
125- e .printStackTrace (Log .ERROR );
126- return null ;
127122 }
123+
124+ return con ;
128125 }
129126
130127 /**
131128 * Downloads a string from the given URL, effectively acting as {@code curl}.
132129 *
133130 * @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
134154 * @return The downloaded string, or {@code null} if the download failed
135155 */
136- public static @ Nullable String downloadString ( String url ) {
156+ public static @ Nullable String tryDownloadString ( boolean silent , String url ) {
137157 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 );
152159 } 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 ;
155166 }
156- return null ;
157167 }
158168
159169 /**
160170 * Downloads a file from the given URL into the target file, effectively acting as {@code wget}.
161171 *
162172 * @param target The file to download to
163173 * @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
164201 * @return {@code true} if the download was successful
165202 */
166- public static boolean downloadFile ( File target , String url ) {
203+ public static boolean tryDownloadFile ( boolean silent , File target , String url ) {
167204 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 ;
176207 } 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 ;
179214 }
180- return false ;
181215 }
182216}
0 commit comments