| 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(); |