Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: adblockplussbrowser/src/main/java/org/adblockplus/sbrowser/contentblocker/engine/Downloader.java

Issue 29603697: Issue 5931 - Create tests for util package (Closed)
Patch Set: Created Nov. 10, 2017, 2:23 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package org.adblockplus.sbrowser.contentblocker.engine;
19
20 import java.io.BufferedReader;
21 import java.io.IOException;
22 import java.io.InputStreamReader;
23 import java.net.HttpURLConnection;
24 import java.net.URL;
25 import java.nio.charset.StandardCharsets;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.concurrent.LinkedBlockingQueue;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.locks.ReentrantLock;
33 import android.annotation.SuppressLint;
34 import android.util.Log;
35
36 @SuppressLint("DefaultLocale")
37 final class Downloader
38 {
39 private static final int MAX_RETRIES = 5;
40
41 private static final String TAG = Downloader.class.getSimpleName();
42 private final Engine engine;
43 private final ReentrantLock accessLock = new ReentrantLock();
44 private Thread downloaderThread;
45 private final LinkedBlockingQueue<DownloadJob> downloadJobs = new LinkedBlocki ngQueue<>();
46 private final HashSet<String> enqueuedIds = new HashSet<>();
47 private boolean downloaderEnabled = true;
48
49 private Downloader(final Engine engine)
50 {
51 this.engine = engine;
52 }
53
54 void lock()
55 {
56 this.accessLock.lock();
57 }
58
59 void unlock()
60 {
61 this.accessLock.unlock();
62 }
63
64 void connectivityChanged()
65 {
66 this.lock();
67 if (!this.downloaderEnabled)
68 {
69 Log.d(TAG, "Re-checking download permission");
70 }
71 this.downloaderEnabled = true;
72 this.unlock();
73 }
74
75 static void download(final DownloadJob job) throws IOException
76 {
77 final HttpURLConnection connection = (HttpURLConnection) job.url.openConnect ion();
78 connection.setRequestMethod("GET");
79 for (final Entry<String, String> e : job.headers.entrySet())
80 {
81 connection.addRequestProperty(e.getKey(), e.getValue());
82 }
83 connection.connect();
84
85 job.responseCode = connection.getResponseCode();
86 job.responseHeaders.clear();
87 job.responseText = null;
88
89 for (int i = 1;; i++)
90 {
91 final String key = connection.getHeaderFieldKey(i);
92 if (key == null)
93 {
94 break;
95 }
96 final String value = connection.getHeaderField(i);
97 job.responseHeaders.put(key.toLowerCase(), value);
98 }
99
100 final StringBuilder sb = new StringBuilder();
101 try (final BufferedReader r = new BufferedReader(new InputStreamReader(
102 connection.getInputStream(), StandardCharsets.UTF_8)))
103 {
104 for (int ch = r.read(); ch != -1; ch = r.read())
105 {
106 sb.append((char) ch);
107 }
108 job.responseText = sb.toString();
109 }
110 }
111
112 public void enqueueDownload(final URL url, final String id, final Map<String, String> headers)
113 {
114 this.lock();
115 try
116 {
117 if (!this.enqueuedIds.contains(id))
118 {
119 this.enqueuedIds.add(id);
120 this.downloadJobs.add(new DownloadJob(url, id, headers));
121 }
122 }
123 finally
124 {
125 this.unlock();
126 }
127 }
128
129 public static Downloader create(final Engine engine)
130 {
131 final Downloader downloader = new Downloader(engine);
132
133 downloader.downloaderThread = new Thread(new DownloaderHandler(downloader));
134 downloader.downloaderThread.setDaemon(true);
135 downloader.downloaderThread.start();
136
137 return downloader;
138 }
139
140 private static class DownloaderHandler implements Runnable
141 {
142 private static final String TAG = DownloaderHandler.class.getSimpleName();
143
144 private final Downloader downloader;
145
146 public DownloaderHandler(final Downloader downloader)
147 {
148 this.downloader = downloader;
149 }
150
151 @Override
152 public void run()
153 {
154 Log.d(TAG, "Handler thread started");
155 final LinkedBlockingQueue<DownloadJob> reQueue = new LinkedBlockingQueue<> ();
156 boolean interrupted = false;
157 while (!interrupted)
158 {
159 DownloadJob job = null;
160 try
161 {
162 if (!this.downloader.downloaderEnabled)
163 {
164 Thread.sleep(30000);
165 continue;
166 }
167 job = this.downloader.downloadJobs.poll(5 * 60, TimeUnit.SECONDS);
168 if (job != null)
169 {
170 if (this.downloader.engine.canUseInternet())
171 {
172 Log.d(TAG, "Downloading '" + job.id + "' using " + job.url);
173 download(job);
174 Log.d(TAG, "Downloading '" + job.id + "' finished with response co de "
175 + job.responseCode);
176 this.downloader.lock();
177 try
178 {
179 this.downloader.enqueuedIds.remove(job.id);
180 }
181 finally
182 {
183 this.downloader.unlock();
184 }
185
186 this.downloader.engine.downloadFinished(job.id, job.responseCode, job.responseText,
187 job.responseHeaders);
188
189 // Check for retries
190 if (!reQueue.isEmpty())
191 {
192 this.downloader.downloadJobs.add(reQueue.poll());
193 }
194 }
195 else
196 {
197 // we just keep jobs in queue
198 Log.d(TAG, "Updates disabled, re-queuing and disabling downloader" );
199 this.downloader.downloadJobs.add(job);
200 this.downloader.lock();
201 this.downloader.downloaderEnabled = false;
202 this.downloader.unlock();
203 }
204 }
205 }
206 catch (final InterruptedException e)
207 {
208 Log.d(TAG, "Handler interrupted", e);
209 interrupted = true;
210 }
211 catch (final Throwable t)
212 {
213 Log.e(TAG, "Downloading failed: " + t.getMessage(), t);
214 if (job != null)
215 {
216 if (job.retryCount++ < MAX_RETRIES)
217 {
218 reQueue.add(job);
219 }
220 else
221 {
222 this.downloader.lock();
223 try
224 {
225 this.downloader.enqueuedIds.remove(job.id);
226 }
227 finally
228 {
229 this.downloader.unlock();
230 }
231 this.downloader.engine.downloadFinished(job.id, -1, null, null);
232 }
233 }
234 }
235 }
236 Log.d(TAG, "Handler thread finished");
237 }
238 }
239
240 private static class DownloadJob
241 {
242 private final URL url;
243 private final String id;
244 private final HashMap<String, String> headers = new HashMap<>();
245 private int retryCount = 0;
246
247 private int responseCode = 0;
248 private final HashMap<String, String> responseHeaders = new HashMap<>();
249 private String responseText = null;
250
251 public DownloadJob(final URL url, final String id, final Map<String, String> headers)
252 {
253 this.url = url;
254 this.id = id;
255 if (headers != null)
256 {
257 this.headers.putAll(headers);
258 }
259 }
260 }
261 }
OLDNEW

Powered by Google App Engine
This is Rietveld