| | 93 | final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(); |
| | 94 | monitor.beginTask(tr("Attempting to fetch Bing attribution information"), ProgressMonitor.ALL_TICKS); |
| | 95 | final Timer timer = new Timer(Thread.currentThread().getName() + "-timer", true); |
| | 96 | timer.schedule(new AttributionTimerTask(monitor, timer, 1, attributions, finished), 0); |
| | 97 | synchronized (finished) { |
| | 98 | while (!finished.get() && !monitor.isCanceled()) { |
| | 99 | finished.wait(1000); |
| | 100 | } |
| | 101 | } |
| | 102 | monitor.finishTask(); |
| | 103 | monitor.close(); |
| | 104 | return attributions.get(); |
| | 105 | }; |
| | 106 | } |
| | 107 | |
| | 108 | /** |
| | 109 | * A timer task for fetching Bing attribution information |
| | 110 | */ |
| | 111 | private class AttributionTimerTask extends TimerTask { |
| | 112 | private final ProgressMonitor monitor; |
| | 113 | private final Timer timer; |
| | 114 | private final int waitTimeSec; |
| | 115 | private final AtomicReference<List<Attribution>> attributions; |
| | 116 | private final AtomicBoolean finished; |
| | 117 | |
| | 118 | /** |
| | 119 | * Create a new task for fetching Bing attribution data |
| | 120 | * @param monitor The monitor to update and use for cancellations |
| | 121 | * @param timer The timer thread to add the next task to, if this task failed to fetch the attribution data |
| | 122 | * @param waitTimeSec The time this task is waiting in seconds prior to execution |
| | 123 | * @param attributions The reference to put attributions in |
| | 124 | * @param finished Set to {@code true} when we have successfully fetched attributions <i>or</i> fetching has been cancelled. |
| | 125 | */ |
| | 126 | AttributionTimerTask(ProgressMonitor monitor, Timer timer, int waitTimeSec, |
| | 127 | AtomicReference<List<Attribution>> attributions, AtomicBoolean finished) { |
| | 128 | this.monitor = monitor; |
| | 129 | this.timer = timer; |
| | 130 | this.waitTimeSec = waitTimeSec; |
| | 131 | this.attributions = attributions; |
| | 132 | this.finished = finished; |
| | 133 | } |
| | 134 | |
| | 135 | @Override |
| | 136 | public void run() { |
| 85 | | int waitTimeSec = 1; |
| 86 | | while (true) { |
| 87 | | try { |
| 88 | | String xml = attributionLoader.updateIfRequiredString(); |
| 89 | | List<Attribution> ret = parseAttributionText(new InputSource(new StringReader(xml))); |
| 90 | | if (attributionDownloadedTask != null) { |
| 91 | | GuiHelper.runInEDT(attributionDownloadedTask); |
| 92 | | attributionDownloadedTask = null; |
| 93 | | } |
| 94 | | return ret; |
| 95 | | } catch (IOException ex) { |
| 96 | | Logging.log(Logging.LEVEL_WARN, "Could not connect to Bing API. Will retry in " + waitTimeSec + " seconds.", ex); |
| 97 | | Thread.sleep(TimeUnit.SECONDS.toMillis(waitTimeSec)); |
| 98 | | waitTimeSec *= 2; |
| | 138 | try { |
| | 139 | String xml = attributionLoader.updateIfRequiredString(); |
| | 140 | List<Attribution> ret; |
| | 141 | try (StringReader sr = new StringReader(xml)) { |
| | 142 | ret = parseAttributionText(new InputSource(sr)); |
| | 143 | } |
| | 144 | if (attributionDownloadedTask != null) { |
| | 145 | GuiHelper.runInEDT(attributionDownloadedTask); |
| | 146 | attributionDownloadedTask = null; |
| | 147 | } |
| | 148 | this.attributions.set(ret); |
| | 149 | this.finished.set(true); |
| | 150 | } catch (IOException ex) { |
| | 151 | final String message = tr("Could not connect to Bing API. Will retry in {0} seconds.", waitTimeSec); |
| | 152 | Logging.log(Logging.LEVEL_WARN, message, ex); |
| | 153 | if (this.monitor.isCanceled()) { |
| | 154 | this.finished.set(true); |
| | 155 | return; |
| | 156 | } |
| | 157 | this.monitor.setCustomText(message); |
| | 158 | this.monitor.worked(1); |
| | 159 | final int newWaitTimeSec = 2 * this.waitTimeSec; |
| | 160 | this.timer.schedule(new AttributionTimerTask(this.monitor, this.timer, newWaitTimeSec, this.attributions, this.finished), |
| | 161 | newWaitTimeSec * 1000L); |
| | 162 | } finally { |
| | 163 | synchronized (this.finished) { |
| | 164 | this.finished.notifyAll(); |