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