Sfoglia il codice sorgente

Merge pull request #22 from greboid/tidying

Tidy downloader.
pull/24/head
Chris Smith 9 anni fa
parent
commit
d84337a9ca

+ 50
- 0
src/com/dmdirc/util/collections/CollectionFunctions.java Vedi File

@@ -0,0 +1,50 @@
1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util.collections;
24
+
25
+import java.io.UnsupportedEncodingException;
26
+import java.net.URLEncoder;
27
+import java.util.Map;
28
+import java.util.stream.Stream;
29
+
30
+/**
31
+ * Collection related functions.
32
+ */
33
+public final class CollectionFunctions {
34
+
35
+    private CollectionFunctions() {
36
+    }
37
+
38
+    public static Stream<String> flattenAndEncodeKeyPair(final Map.Entry<String, String> entry) {
39
+        String key;
40
+        String value;
41
+        try {
42
+            key = URLEncoder.encode(entry.getKey(), "UTF-8");
43
+            value = URLEncoder.encode(entry.getValue(), "UTF-8");
44
+        } catch (UnsupportedEncodingException ex){
45
+            key = entry.getKey();
46
+            value = entry.getValue();
47
+        }
48
+        return Stream.of(key + '=' + value);
49
+    }
50
+}

+ 15
- 63
src/com/dmdirc/util/io/Downloader.java Vedi File

@@ -22,20 +22,19 @@
22 22
 
23 23
 package com.dmdirc.util.io;
24 24
 
25
+import com.dmdirc.util.collections.CollectionFunctions;
26
+
25 27
 import java.io.BufferedReader;
26 28
 import java.io.DataOutputStream;
27 29
 import java.io.IOException;
28
-import java.io.InputStream;
29 30
 import java.io.InputStreamReader;
30
-import java.io.OutputStream;
31 31
 import java.net.URL;
32 32
 import java.net.URLConnection;
33
-import java.net.URLEncoder;
34 33
 import java.nio.file.Files;
35 34
 import java.nio.file.Path;
36
-import java.util.ArrayList;
37 35
 import java.util.List;
38 36
 import java.util.Map;
37
+import java.util.stream.Collectors;
39 38
 
40 39
 /**
41 40
  * Allows easy downloading of files from HTTP sites.
@@ -50,7 +49,6 @@ public class Downloader {
50 49
      * @throws IOException If there's an I/O error while downloading
51 50
      */
52 51
     public List<String> getPage(final String url) throws IOException {
53
-
54 52
         return getPage(url, "");
55 53
     }
56 54
 
@@ -64,23 +62,12 @@ public class Downloader {
64 62
      */
65 63
     public List<String> getPage(final String url, final String postData)
66 64
             throws IOException {
67
-
68
-        final List<String> res = new ArrayList<>();
69
-
70 65
         final URLConnection urlConn = getConnection(url, postData);
71
-
66
+        final List<String> res;
72 67
         try (BufferedReader in = new BufferedReader(new InputStreamReader(
73 68
                 urlConn.getInputStream()))) {
74
-            String line;
75
-            do {
76
-                line = in.readLine();
77
-
78
-                if (line != null) {
79
-                    res.add(line);
80
-                }
81
-            } while (line != null);
69
+            res = in.lines().collect(Collectors.toList());
82 70
         }
83
-
84 71
         return res;
85 72
     }
86 73
 
@@ -94,16 +81,9 @@ public class Downloader {
94 81
      */
95 82
     public List<String> getPage(final String url,
96 83
             final Map<String, String> postData) throws IOException {
97
-        final StringBuilder data = new StringBuilder();
98
-
99
-        for (Map.Entry<String, String> entry : postData.entrySet()) {
100
-            data.append('&');
101
-            data.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
102
-            data.append('=');
103
-            data.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
104
-        }
105
-
106
-        return getPage(url, data.length() == 0 ? "" : data.substring(1));
84
+        return getPage(url, postData.entrySet().stream()
85
+                .flatMap(CollectionFunctions::flattenAndEncodeKeyPair)
86
+                .collect(Collectors.joining("&")));
107 87
     }
108 88
 
109 89
     /**
@@ -126,37 +106,11 @@ public class Downloader {
126 106
      * @param listener The progress listener for this download
127 107
      * @throws IOException If there's an I/O error while downloading
128 108
      */
129
-    public void downloadPage(final String url, final Path file,
130
-            final DownloadListener listener) throws IOException {
131
-
132
-        final URLConnection urlConn = getConnection(url, "");
133
-
134
-        try (OutputStream output = Files.newOutputStream(file);
135
-                InputStream input = urlConn.getInputStream()) {
136
-            final int length = urlConn.getContentLength();
137
-
138
-            if (listener != null) {
139
-                listener.setIndeterminate(length == -1);
140
-            }
141
-
142
-            final byte[] buffer = new byte[512];
143
-            int count;
144
-
145
-            int current = 0;
146
-            do {
147
-                count = input.read(buffer);
148
-
149
-                if (count > 0) {
150
-                    current += count;
151
-                    output.write(buffer, 0, count);
152
-
153
-                    if (listener != null && length != -1) {
154
-                        listener.downloadProgress(100 * (float) current
155
-                                / length);
156
-                    }
157
-                }
158
-            } while (count > 0);
159
-        }
109
+    public void downloadPage(final String url, final Path file, final DownloadListener listener)
110
+            throws IOException {
111
+        final URLConnection connection = getConnection(url, "");
112
+        Files.copy(new ListenerInputStream(connection.getInputStream(), listener,
113
+                        connection.getContentLength()), file);
160 114
     }
161 115
 
162 116
     /**
@@ -167,8 +121,7 @@ public class Downloader {
167 121
      * @return An URLConnection for the specified URL/data
168 122
      * @throws IOException If an I/O exception occurs while connecting
169 123
      */
170
-    private URLConnection getConnection(final String url,
171
-            final String postData)
124
+    private URLConnection getConnection(final String url, final String postData)
172 125
             throws IOException {
173 126
         final URLConnection urlConn = getURLConnection(url);
174 127
 
@@ -178,8 +131,7 @@ public class Downloader {
178 131
         urlConn.setConnectTimeout(10000);
179 132
 
180 133
         if (!postData.isEmpty()) {
181
-            urlConn.setRequestProperty("Content-Type",
182
-                    "application/x-www-form-urlencoded");
134
+            urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
183 135
 
184 136
             try (DataOutputStream out = new DataOutputStream(urlConn.getOutputStream())) {
185 137
                 out.writeBytes(postData);

+ 128
- 0
src/com/dmdirc/util/io/ListenerInputStream.java Vedi File

@@ -0,0 +1,128 @@
1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util.io;
24
+
25
+import java.io.FilterInputStream;
26
+import java.io.IOException;
27
+import java.io.InputStream;
28
+
29
+import javax.annotation.Nonnull;
30
+
31
+/**
32
+ * Wrapped {@link InputStream} that provides updates to a {@link DownloadListener} as it reads a
33
+ * stream.
34
+ */
35
+public class ListenerInputStream extends FilterInputStream {
36
+
37
+    private final DownloadListener listener;
38
+    private final int length;
39
+    private int count;
40
+    private int mark;
41
+
42
+    /**
43
+     * Creates a new stream.
44
+     *
45
+     * @param in        Stream to wrap
46
+     * @param listener  Listener to gives up dates to
47
+     * @param length    Length of the stream, if -1 the listener will be indeterminate
48
+     */
49
+    public ListenerInputStream(@Nonnull final InputStream in, final DownloadListener listener,
50
+            final int length) {
51
+        super(in);
52
+        this.listener = listener;
53
+        this.length = length;
54
+        count = 0;
55
+        mark = count;
56
+        if (listener != null) {
57
+            listener.setIndeterminate(length == -1);
58
+        }
59
+    }
60
+
61
+    @Override
62
+    public int read() throws IOException {
63
+        final int read = super.read();
64
+        return update(read);
65
+    }
66
+
67
+    @Override
68
+    public int read(@Nonnull final byte[] b) throws IOException {
69
+        final int read = super.read(b);
70
+        return update(read);
71
+    }
72
+
73
+    @Override
74
+    public int read(@Nonnull final byte[] b, final int off, final int len) throws IOException {
75
+        final int read = super.read(b, off, len);
76
+        return update(read);
77
+    }
78
+
79
+    @Override
80
+    public long skip(final long n) throws IOException {
81
+        final long read = super.skip(n);
82
+        return update((int) read);
83
+    }
84
+
85
+    @Override
86
+    public int available() throws IOException {
87
+        return super.available();
88
+    }
89
+
90
+    @Override
91
+    public void close() throws IOException {
92
+        super.close();
93
+    }
94
+
95
+    @Override
96
+    public synchronized void mark(final int readlimit) {
97
+        mark = count;
98
+        super.mark(readlimit);
99
+    }
100
+
101
+    @Override
102
+    public synchronized void reset() throws IOException {
103
+        update(mark - count);
104
+        super.reset();
105
+    }
106
+
107
+    @Override
108
+    public boolean markSupported() {
109
+        return super.markSupported();
110
+    }
111
+
112
+    /**
113
+     * Updates the listener and total read count.
114
+     *
115
+     * @param read Number of bytes further into stream.
116
+     *
117
+     * @return Returns the number of bytes read.
118
+     */
119
+    private int update(final int read) {
120
+        if (read > 0) {
121
+            count += read;
122
+            if (listener != null && length != -1) {
123
+                listener.downloadProgress(100 * (float) count / length);
124
+            }
125
+        }
126
+        return read;
127
+    }
128
+}

+ 50
- 0
test/com/dmdirc/util/collections/CollectionFunctionsTest.java Vedi File

@@ -0,0 +1,50 @@
1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.util.collections;
24
+
25
+import com.google.common.collect.ImmutableMap;
26
+
27
+import java.util.List;
28
+import java.util.Map;
29
+import java.util.stream.Collectors;
30
+
31
+import org.junit.Test;
32
+
33
+import static junit.framework.TestCase.assertEquals;
34
+
35
+public class CollectionFunctionsTest {
36
+
37
+    @Test
38
+    public void testflattenAndEncodeKeyPair() throws Exception {
39
+        final Map<String, String> map = ImmutableMap.<String, String>builder()
40
+                .put("key", "value")
41
+                .put("key&", "value&")
42
+                .build();
43
+        final List<String> result = map.entrySet().stream()
44
+                .flatMap(CollectionFunctions::flattenAndEncodeKeyPair)
45
+                .collect(Collectors.toList());
46
+        assertEquals(2, result.size());
47
+        assertEquals("key=value", result.get(0));
48
+        assertEquals("key%26=value%26", result.get(1));
49
+    }
50
+}

+ 14
- 0
test/com/dmdirc/util/io/DownloaderTest.java Vedi File

@@ -104,6 +104,20 @@ public class DownloaderTest {
104 104
         assertTrue(postDataString1.equals(os.toString()) || postDataString2.equals(os.toString()));
105 105
     }
106 106
 
107
+    @Test
108
+    public void testGetPageMapEncoding() throws IOException {
109
+        final Map<String, String> postData = Maps.newHashMap();
110
+        postData.put("ke&y1", "value1");
111
+        postData.put("key2", "val&ue2");
112
+        new TestableDownloader().getPage("rar", postData);
113
+        verify(mockedConnection).setRequestProperty("Content-Type",
114
+                "application/x-www-form-urlencoded");
115
+
116
+        final String postDataString1 = "ke%26y1=value1&key2=val%26ue2";
117
+        final String postDataString2 = "key2=val%26ue2&ke%26y1=value1";
118
+        assertTrue(postDataString1.equals(os.toString()) || postDataString2.equals(os.toString()));
119
+    }
120
+
107 121
     @Test
108 122
     public void testDownloadPage() throws IOException {
109 123
         final Path file = fakeFS.getPath("test.txt");

Loading…
Annulla
Salva