001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.downloadtasks; 003 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.List; 007 008import org.openstreetmap.josm.data.ProjectionBounds; 009import org.openstreetmap.josm.io.UrlPattern; 010import org.openstreetmap.josm.io.XmlWriter; 011 012/** 013 * Common abstract implementation of other download tasks. 014 * @param <T> The downloaded data type 015 * @since 2322 016 */ 017public abstract class AbstractDownloadTask<T> implements DownloadTask { 018 private final List<Object> errorMessages; 019 private boolean canceled; 020 private boolean failed; 021 protected T downloadedData; 022 protected boolean zoomAfterDownload = true; 023 024 /** 025 * Constructs a new {@code AbstractDownloadTask}. 026 */ 027 public AbstractDownloadTask() { 028 errorMessages = new ArrayList<>(); 029 } 030 031 /** 032 * Determines if the download task has been canceled. 033 * @return {@code true} if the download task has been canceled 034 */ 035 public boolean isCanceled() { 036 return canceled; 037 } 038 039 /** 040 * Marks this download task as canceled. 041 * @param canceled {@code true} to mark this download task as canceled 042 */ 043 public void setCanceled(boolean canceled) { 044 this.canceled = canceled; 045 } 046 047 /** 048 * Determines if the download task has failed. 049 * @return {@code true} if the download task has failed 050 */ 051 public boolean isFailed() { 052 return failed; 053 } 054 055 /** 056 * Marks this download task as failed. 057 * @param failed {@code true} to mark this download task as failed 058 */ 059 public void setFailed(boolean failed) { 060 this.failed = failed; 061 } 062 063 protected static <T extends Enum<T> & UrlPattern> String[] patterns(Class<T> urlPatternEnum) { 064 // Do not use a method reference until we switch to Java 11, as we face JDK-8141508 with Java 8 065 return Arrays.stream(urlPatternEnum.getEnumConstants()).map(/* JDK-8141508 */ t -> t.pattern()).toArray(String[]::new); 066 } 067 068 protected final void rememberErrorMessage(String message) { 069 errorMessages.add(message); 070 } 071 072 protected final void rememberException(Exception exception) { 073 errorMessages.add(exception); 074 } 075 076 protected final void rememberDownloadedData(T data) { 077 this.downloadedData = data; 078 } 079 080 /** 081 * Replies the downloaded data. 082 * @return The downloaded data. 083 */ 084 public final T getDownloadedData() { 085 return downloadedData; 086 } 087 088 @Override 089 public final void setZoomAfterDownload(boolean zoomAfterDownload) { 090 this.zoomAfterDownload = zoomAfterDownload; 091 } 092 093 @Override 094 public List<Object> getErrorObjects() { 095 return errorMessages; 096 } 097 098 @Override 099 public String acceptsDocumentationSummary() { 100 StringBuilder buff = new StringBuilder(128) 101 .append("<tr><td>") 102 .append(getTitle()) 103 .append(":</td><td>"); 104 String[] patterns = getPatterns(); 105 if (patterns.length > 0) { 106 buff.append("<ul>"); 107 for (String pattern: patterns) { 108 buff.append("<li>") 109 .append(XmlWriter.encode(pattern)) 110 .append("</li>"); 111 } 112 buff.append("</ul>"); 113 } 114 buff.append("</td></tr>"); 115 return buff.toString(); 116 } 117 118 /** 119 * Determines if the given URL is accepted by {@link #getPatterns}. 120 * Can be overridden for more complex checking logic. 121 * @param url URL to donwload 122 * @return {@code true} if this URL is accepted 123 */ 124 public boolean acceptsUrl(String url) { 125 return url != null && Arrays.stream(getPatterns()).anyMatch(url::matches); 126 } 127 128 /** 129 * Check / decide if the task is safe for remotecontrol. 130 * 131 * Keep in mind that a potential attacker has full control over the content 132 * of the file that will be downloaded. 133 * If it is possible to run arbitrary code or write to the local file 134 * system, then the task is (obviously) not save for remote execution. 135 * 136 * The default value is false = unsafe. Override in a subclass to 137 * allow running the task via remotecontol. 138 * 139 * @return true if it is safe to download and open any file of the 140 * corresponding format, false otherwise 141 */ 142 public boolean isSafeForRemotecontrolRequests() { 143 return false; 144 } 145 146 @Override 147 public boolean acceptsUrl(String url, boolean isRemotecontrol) { 148 if (isRemotecontrol && !isSafeForRemotecontrolRequests()) 149 return false; 150 return acceptsUrl(url); 151 } 152 153 // Default name to keep old plugins compatible 154 @Override 155 public String getTitle() { 156 return getClass().getName(); 157 } 158 159 @Override 160 public String toString() { 161 return this.getTitle(); 162 } 163 164 // Default pattern to keep old plugins compatible 165 @Override 166 public String[] getPatterns() { 167 return new String[]{}; 168 } 169 170 /** 171 * Returns the projection bounds of downloaded data. 172 * @return the projection bounds of downloaded data or {@code null} 173 * @since 11774 174 */ 175 public ProjectionBounds getDownloadProjectionBounds() { 176 return null; 177 } 178}