diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/BaseDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/common/BaseDelegate.java new file mode 100644 index 00000000..20f7f1fe --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/common/BaseDelegate.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.common; + +import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.inf.ITargetHandler; +import com.arialyy.aria.util.CommonUtil; + +public abstract class BaseDelegate implements ITargetHandler { + protected TARGET mTarget; + protected final String TAG; + + public BaseDelegate(TARGET target) { + mTarget = target; + TAG = CommonUtil.getClassName(getClass()); + } + + @Override public void add() { + mTarget.add(); + } + + @Override public void start() { + mTarget.start(); + } + + @Override public void stop() { + mTarget.stop(); + } + + @Override public void resume() { + mTarget.resume(); + } + + @Override public void cancel() { + mTarget.cancel(); + } + + @Override public void save() { + mTarget.save(); + } + + @Override public void cancel(boolean removeFile) { + mTarget.cancel(removeFile); + } + + @Override public void reTry() { + mTarget.reTry(); + } + + @Override public void reStart() { + mTarget.reStart(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java index 279c19c3..52639637 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java @@ -60,7 +60,7 @@ public abstract class AbsFtpInfoThread implements ITargetHandler { - private final String TAG = "FTPSDelegate"; - private TARGET mTarget; +public class FTPSDelegate extends BaseDelegate { + private FtpUrlEntity mUrlEntity; public FTPSDelegate(TARGET target) { - mTarget = target; + super(target); mUrlEntity = mTarget.getTaskWrapper().asFtp().getUrlEntity(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpTaskConfig.java b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpTaskConfig.java new file mode 100644 index 00000000..58dfc0b9 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpTaskConfig.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.common.ftp; + +import com.arialyy.aria.core.FtpUrlEntity; +import com.arialyy.aria.core.inf.ITaskConfig; +import java.net.Proxy; + +/** + * fTP任务设置的信息,如:用户名、密码、端口等信息 + */ +public class FtpTaskConfig implements ITaskConfig { + + /** + * 账号和密码 + */ + private FtpUrlEntity urlEntity; + + private Proxy proxy; + + /** + * 字符编码,默认为"utf-8" + */ + private String charSet = "utf-8"; + + /** + * 上传拦截器 + */ + private IFtpUploadInterceptor uploadInterceptor; + + /** + * 上传到服务器文件的新文件名{@link FtpInterceptHandler#getNewFileName()} + */ + private String newFileName; + + public String getNewFileName() { + return newFileName; + } + + public void setNewFileName(String newFileName) { + this.newFileName = newFileName; + } + + public IFtpUploadInterceptor getUploadInterceptor() { + return uploadInterceptor; + } + + public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) { + this.uploadInterceptor = uploadInterceptor; + } + + public FtpUrlEntity getUrlEntity() { + return urlEntity; + } + + public void setUrlEntity(FtpUrlEntity urlEntity) { + this.urlEntity = urlEntity; + } + + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } + + public Proxy getProxy() { + return proxy; + } + + public String getCharSet() { + return charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpDelegate.java index 20ba2357..0e1680ae 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpDelegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpDelegate.java @@ -15,25 +15,31 @@ */ package com.arialyy.aria.core.common.http; +import android.support.annotation.NonNull; import android.text.TextUtils; +import com.arialyy.aria.core.common.BaseDelegate; import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DownloadGroupTarget; import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.inf.AbsTaskWrapper; +import com.arialyy.aria.core.inf.IHttpFileLenAdapter; +import com.arialyy.aria.core.inf.IHttpHeaderDelegate; import com.arialyy.aria.core.inf.ITargetHandler; import com.arialyy.aria.util.ALog; +import java.net.Proxy; +import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Set; /** - * HTTP参数委托 + * HTTP协议处理 */ -class HttpDelegate implements ITargetHandler { - private static final String TAG = "PostDelegate"; - TARGET mTarget; - - HttpDelegate(TARGET target) { - mTarget = target; +public class HttpDelegate extends BaseDelegate + implements IHttpHeaderDelegate { + public HttpDelegate(TARGET target) { + super(target); } public TARGET setParams(Map params) { @@ -65,39 +71,105 @@ class HttpDelegate implements ITargetHandler { return mTarget; } - @Override public void add() { - mTarget.add(); - } - - @Override public void start() { - mTarget.start(); - } - - @Override public void stop() { - mTarget.stop(); + /** + * 给url请求添加Header数据 + * 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 + * + * @param key header对应的key + * @param value header对应的value + */ + @Override + public TARGET addHeader(@NonNull String key, @NonNull String value) { + if (TextUtils.isEmpty(key)) { + ALog.w(TAG, "设置header失败,header对应的key不能为null"); + return mTarget; + } else if (TextUtils.isEmpty(value)) { + ALog.w(TAG, "设置header失败,header对应的value不能为null"); + return mTarget; + } + addHeader(mTarget.getTaskWrapper(), key, value); + return mTarget; } - @Override public void resume() { - mTarget.resume(); + /** + * 给url请求添加一组header数据 + * 如果新的header数据和数据保存的不一致,则更新数据库中对应的header数据 + * + * @param headers 一组http header数据 + */ + @Override + public TARGET addHeaders(@NonNull Map headers) { + if (headers.size() == 0) { + ALog.w(TAG, "设置header失败,map没有header数据"); + return mTarget; + } + addHeaders(mTarget.getTaskWrapper(), headers); + return mTarget; } - @Override public void cancel() { - mTarget.cancel(); + @Override public TARGET setUrlProxy(Proxy proxy) { + mTarget.getTaskWrapper().asHttp().setProxy(proxy); + return mTarget; } - @Override public void save() { - mTarget.save(); + public TARGET setFileLenAdapter(IHttpFileLenAdapter adapter) { + if (adapter == null) { + throw new IllegalArgumentException("adapter为空"); + } + mTarget.getTaskWrapper().asHttp().setFileLenAdapter(adapter); + return mTarget; } - @Override public void cancel(boolean removeFile) { - mTarget.cancel(removeFile); + private void addHeader(AbsTaskWrapper taskWrapper, String key, String value) { + HttpTaskConfig taskDelegate = taskWrapper.asHttp(); + if (taskDelegate.getHeaders().get(key) == null) { + taskDelegate.getHeaders().put(key, value); + } else if (!taskDelegate.getHeaders().get(key).equals(value)) { + taskDelegate.getHeaders().put(key, value); + } } - @Override public void reTry() { - mTarget.reTry(); - } + private void addHeaders(AbsTaskWrapper taskWrapper, Map headers) { + HttpTaskConfig taskDelegate = taskWrapper.asHttp(); + /* + 两个map比较逻辑 + 1、比对key是否相同 + 2、如果key相同,比对value是否相同 + 3、只有当上面两个步骤中key 和 value都相同时才能任务两个map数据一致 + */ + boolean mapEquals = false; + if (taskDelegate.getHeaders().size() == headers.size()) { + int i = 0; + Set keys = taskDelegate.getHeaders().keySet(); + for (String key : keys) { + if (headers.containsKey(key)) { + i++; + } else { + break; + } + } + if (i == taskDelegate.getHeaders().size()) { + int j = 0; + Collection values = taskDelegate.getHeaders().values(); + for (String value : values) { + if (headers.containsValue(value)) { + j++; + } else { + break; + } + } + if (j == taskDelegate.getHeaders().size()) { + mapEquals = true; + } + } + } - @Override public void reStart() { - mTarget.reStart(); + if (!mapEquals) { + taskDelegate.getHeaders().clear(); + Set keys = headers.keySet(); + for (String key : keys) { + taskDelegate.getHeaders().put(key, headers.get(key)); + } + } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpTaskConfig.java b/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpTaskConfig.java new file mode 100644 index 00000000..8748021c --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/common/http/HttpTaskConfig.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.aria.core.common.http; + +import com.arialyy.aria.core.common.RequestEnum; +import com.arialyy.aria.core.inf.IHttpFileLenAdapter; +import com.arialyy.aria.core.inf.ITaskConfig; +import java.net.CookieManager; +import java.net.Proxy; +import java.util.HashMap; +import java.util.Map; + +/** + * Http任务设置的信息,如:cookie、请求参数 + */ +public class HttpTaskConfig implements ITaskConfig { + + private CookieManager cookieManager; + + /** + * 请求参数 + */ + private Map params; + + /** + * http 请求头 + */ + private Map headers = new HashMap<>(); + + /** + * 字符编码,默认为"utf-8" + */ + private String charSet = "utf-8"; + + /** + * 网络请求类型 + */ + private RequestEnum requestEnum = RequestEnum.GET; + + /** + * 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment; filename="filename.jpg"} {@code true} + * 使用 + */ + private boolean useServerFileName = false; + + /** + * 重定向链接 + */ + private String redirectUrl = ""; + + /** + * 是否是chunk模式 + */ + private boolean isChunked = false; + /** + * 文件上传需要的key + */ + private String attachment; + /** + * 上传的文件类型 + */ + private String contentType = "multipart/form-data"; + private String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"; + + private Proxy proxy; + /** + * 文件上传表单 + */ + private Map formFields = new HashMap<>(); + + private IHttpFileLenAdapter fileLenAdapter; + + public IHttpFileLenAdapter getFileLenAdapter() { + return fileLenAdapter; + } + + public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) { + this.fileLenAdapter = fileLenAdapter; + } + + public Map getFormFields() { + return formFields; + } + + public void setFormFields(Map formFields) { + this.formFields = formFields; + } + + public String getAttachment() { + return attachment; + } + + public void setAttachment(String attachment) { + this.attachment = attachment; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public boolean isChunked() { + return isChunked; + } + + public void setChunked(boolean chunked) { + isChunked = chunked; + } + + public CookieManager getCookieManager() { + return cookieManager; + } + + public void setCookieManager(CookieManager cookieManager) { + this.cookieManager = cookieManager; + } + + public Proxy getProxy() { + return proxy; + } + + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public String getCharSet() { + return charSet; + } + + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + public RequestEnum getRequestEnum() { + return requestEnum; + } + + public void setRequestEnum(RequestEnum requestEnum) { + this.requestEnum = requestEnum; + } + + public boolean isUseServerFileName() { + return useServerFileName; + } + + public void setUseServerFileName(boolean useServerFileName) { + this.useServerFileName = useServerFileName; + } + + public String getRedirectUrl() { + return redirectUrl; + } + + public void setRedirectUrl(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/AbsGroupConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/download/AbsGroupConfigHandler.java new file mode 100644 index 00000000..24c3ce87 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/AbsGroupConfigHandler.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.support.annotation.CheckResult; +import android.text.TextUtils; +import com.arialyy.aria.core.inf.IGroupConfigHandler; +import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CommonUtil; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by lyy on 2019/4/9. + * 下载组合任务功能 + */ +abstract class AbsGroupConfigHandler implements IGroupConfigHandler { + protected String TAG; + private TARGET mTarget; + private DGTaskWrapper mWrapper; + /** + * 组任务名 + */ + private String mGroupHash; + /** + * 文件夹临时路径 + */ + private String mDirPathTemp; + /** + * 是否需要修改路径 + */ + private boolean needModifyPath = false; + + AbsGroupConfigHandler(TARGET target, DGTaskWrapper wrapper) { + TAG = CommonUtil.getClassName(getClass()); + mTarget = target; + mWrapper = wrapper; + setGroupHash(wrapper.getKey()); + mTarget.setTaskWrapper(wrapper); + if (getEntity() != null) { + mDirPathTemp = getEntity().getDirPath(); + } + } + + @Override public boolean isRunning() { + DownloadGroupTask task = DownloadGroupTaskQueue.getInstance().getTask(getEntity().getKey()); + return task != null && task.isRunning(); + } + + @CheckResult + TARGET setDirPath(String dirPath) { + mDirPathTemp = dirPath; + return mTarget; + } + + /** + * 改变任务组文件夹路径,修改文件夹路径会将子任务所有路径更换 + * + * @param newDirPath 新的文件夹路径 + */ + void reChangeDirPath(String newDirPath) { + ALog.d(TAG, String.format("修改新路径为:%s", newDirPath)); + List subTasks = mWrapper.getSubTaskWrapper(); + if (subTasks != null && !subTasks.isEmpty()) { + List des = new ArrayList<>(); + for (DTaskWrapper dte : subTasks) { + DownloadEntity de = dte.getEntity(); + String oldPath = de.getDownloadPath(); + String newPath = newDirPath + "/" + de.getFileName(); + File file = new File(oldPath); + if (file.exists()) { + file.renameTo(new File(newPath)); + } + de.setDownloadPath(newPath); + des.add(de); + } + } + } + + /** + * 检查并设置文件夹路径 + * + * @return {@code true} 合法 + */ + @Override public boolean checkDirPath() { + if (TextUtils.isEmpty(mDirPathTemp)) { + ALog.e(TAG, "文件夹路径不能为null"); + return false; + } else if (!mDirPathTemp.startsWith("/")) { + ALog.e(TAG, "文件夹路径【" + mDirPathTemp + "】错误"); + return false; + } + File file = new File(mDirPathTemp); + if (file.isFile()) { + ALog.e(TAG, "路径【" + mDirPathTemp + "】是文件,请设置文件夹路径"); + return false; + } + + if (TextUtils.isEmpty(getEntity().getDirPath()) || !getEntity().getDirPath() + .equals(mDirPathTemp)) { + if (!file.exists()) { + file.mkdirs(); + } + needModifyPath = true; + getEntity().setDirPath(mDirPathTemp); + ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", mDirPathTemp)); + } + return true; + } + + @Override public DownloadGroupEntity getEntity() { + return mWrapper.getEntity(); + } + + @Override public boolean taskExists() { + return DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", mWrapper.getKey()); + } + + DGTaskWrapper getTaskWrapper() { + return mWrapper; + } + + boolean isNeedModifyPath() { + return needModifyPath; + } + + String getDirPathTemp() { + return mDirPathTemp; + } + + TARGET getTarget() { + return mTarget; + } + + public String getGroupHash() { + return mGroupHash; + } + + public void setGroupHash(String groupHash) { + this.mGroupHash = groupHash; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DNormalConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/download/DNormalConfigHandler.java new file mode 100644 index 00000000..efe87ce8 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DNormalConfigHandler.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.text.TextUtils; +import com.arialyy.aria.core.inf.ITargetHandler; +import com.arialyy.aria.core.inf.IConfigHandler; +import com.arialyy.aria.core.manager.TaskWrapperManager; +import com.arialyy.aria.core.queue.DownloadTaskQueue; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.io.File; + +/** + * Created by AriaL on 2019/4/5. + * 普通下载任务通用功能处理 + */ +class DNormalConfigHandler implements IConfigHandler { + private final String TAG = "DNormalDelegate"; + private DownloadEntity mEntity; + + private TARGET mTarget; + private String mNewUrl; + /** + * 设置的文件保存路径的临时变量 + */ + private String mTempFilePath; + + /** + * {@code true}强制下载,不考虑文件路径是否被占用 + */ + private boolean forceDownload = false; + /** + * 资源地址 + */ + private String mUrl; + + DNormalConfigHandler(TARGET target, String url, String targetName) { + this.mTarget = target; + initTarget(url, targetName); + } + + private void initTarget(String url, String targetName) { + DTaskWrapper taskWrapper = + TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, url); + mEntity = taskWrapper.getEntity(); + + mUrl = url; + mTarget.setTargetName(targetName); + mTarget.setTaskWrapper(taskWrapper); + if (mEntity != null) { + mTempFilePath = mEntity.getDownloadPath(); + } + } + + TARGET updateUrl(String newUrl) { + if (TextUtils.isEmpty(newUrl)) { + ALog.e(TAG, "url更新失败,newUrl为null"); + return mTarget; + } + if (mUrl.equals(newUrl)) { + ALog.e(TAG, "url更新失败,新的下载url和旧的url一致"); + return mTarget; + } + mNewUrl = newUrl; + mTarget.getTaskWrapper().setRefreshInfo(true); + return mTarget; + } + + @Override public DownloadEntity getEntity() { + return mTarget.getEntity(); + } + + @Override public boolean taskExists() { + return DbEntity.checkDataExist(DownloadEntity.class, "url=?", mUrl); + } + + @Override public boolean isRunning() { + DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity.getKey()); + return task != null && task.isRunning(); + } + + @Override public boolean checkEntity() { + boolean b = checkUrl() && checkFilePath(); + if (b) { + mEntity.save(); + } + return b; + } + + @Override public boolean checkFilePath() { + String filePath = mTempFilePath; + if (TextUtils.isEmpty(filePath)) { + ALog.e(TAG, "下载失败,文件保存路径为null"); + return false; + } else if (!filePath.startsWith("/")) { + ALog.e(TAG, "下载失败,文件保存路径【" + filePath + "】错误"); + return false; + } + File file = new File(filePath); + if (file.isDirectory()) { + if (mTarget.getTargetType() == ITargetHandler.D_HTTP) { + ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip"); + return false; + } else if (mTarget.getTargetType() == ITargetHandler.D_FTP) { + filePath += mEntity.getFileName(); + } + } else { + // http文件名设置 + if (TextUtils.isEmpty(mEntity.getFileName())) { + mEntity.setFileName(file.getName()); + } + } + + //设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径 + if (!filePath.equals(mEntity.getFilePath())) { + // 检查路径冲突 + if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) { + if (!forceDownload) { + ALog.e(TAG, "下载失败,保存路径【" + filePath + "】已经被其它任务占用,请设置其它保存路径"); + return false; + } else { + ALog.w(TAG, "保存路径【" + filePath + "】已经被其它任务占用,当前任务将覆盖该路径的文件"); + CommonUtil.delTaskRecord(filePath, 1); + mTarget.setTaskWrapper( + TaskWrapperManager.getInstance() + .getHttpTaskWrapper(DTaskWrapper.class, mUrl)); + } + } + File oldFile = new File(mEntity.getDownloadPath()); + File newFile = new File(filePath); + mEntity.setDownloadPath(filePath); + mEntity.setFileName(newFile.getName()); + // 如过使用Content-Disposition中的文件名,将不会执行重命名工作 + if (mTarget.getTaskWrapper().asHttp().isUseServerFileName()) { + return true; + } + if (oldFile.exists()) { + // 处理普通任务的重命名 + CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); + ALog.i(TAG, String.format("将任务重命名为:%s", newFile.getName())); + } else if (CommonUtil.blockTaskExists(oldFile.getPath())) { + // 处理分块任务的重命名 + CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); + ALog.i(TAG, String.format("将分块任务重命名为:%s", newFile.getName())); + } + } + return true; + } + + @Override public boolean checkUrl() { + final String url = mEntity.getUrl(); + if (TextUtils.isEmpty(url)) { + ALog.e(TAG, "下载失败,url为null"); + return false; + } else if (!CheckUtil.checkUrlNotThrow(url)) { + ALog.e(TAG, "下载失败,url【" + url + "】错误"); + return false; + } + int index = url.indexOf("://"); + if (index == -1) { + ALog.e(TAG, "下载失败,url【" + url + "】不合法"); + return false; + } + if (!TextUtils.isEmpty(mNewUrl)) { + mEntity.setUrl(mNewUrl); + } + return true; + } + + void setForceDownload(boolean forceDownload) { + this.forceDownload = forceDownload; + } + + void setUrl(String url) { + this.mUrl = url; + } + + String getUrl() { + return mUrl; + } + + void setTempFilePath(String mTempFilePath) { + this.mTempFilePath = mTempFilePath; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java index ea9a3951..f9724e95 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java @@ -17,10 +17,10 @@ package com.arialyy.aria.core.download; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; -import com.arialyy.aria.core.common.http.HttpHeaderDelegate; +import com.arialyy.aria.core.common.http.GetDelegate; +import com.arialyy.aria.core.common.http.HttpDelegate; import com.arialyy.aria.core.common.http.PostDelegate; import com.arialyy.aria.core.inf.IHttpFileLenAdapter; -import com.arialyy.aria.core.inf.IHttpHeaderDelegate; import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.exception.ParamException; import com.arialyy.aria.util.ALog; @@ -32,10 +32,9 @@ import java.util.Map; * Created by AriaL on 2017/6/29. * 下载任务组 */ -public class DownloadGroupTarget extends AbsDGTarget implements - IHttpHeaderDelegate { - private HttpHeaderDelegate mHeaderDelegate; - private HttpGroupDelegate mGroupDelegate; +public class DownloadGroupTarget extends AbsDGTarget { + private HttpDelegate mHttpDelegate; + private HttpGroupConfigHandler mConfigHandler; DownloadGroupTarget(DownloadGroupEntity groupEntity, String targetName) { setTargetName(targetName); @@ -52,9 +51,9 @@ public class DownloadGroupTarget extends AbsDGTarget implem } private void init(List urls) { - mGroupDelegate = new HttpGroupDelegate(this, + mConfigHandler = new HttpGroupConfigHandler(this, TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, urls)); - mHeaderDelegate = new HttpHeaderDelegate<>(this); + mHttpDelegate = new HttpDelegate<>(this); } /** @@ -62,7 +61,17 @@ public class DownloadGroupTarget extends AbsDGTarget implem */ @CheckResult public PostDelegate asPost() { - return new PostDelegate<>(this); + mHttpDelegate = new PostDelegate<>(this); + return (PostDelegate) mHttpDelegate; + } + + /** + * get处理 + */ + @CheckResult + public GetDelegate asGet() { + mHttpDelegate = new GetDelegate<>(this); + return (GetDelegate) mHttpDelegate; } /** @@ -72,7 +81,7 @@ public class DownloadGroupTarget extends AbsDGTarget implem */ @CheckResult public DownloadGroupTarget updateUrls(List urls) { - return mGroupDelegate.updateUrls(urls); + return mConfigHandler.updateUrls(urls); } /** @@ -113,7 +122,7 @@ public class DownloadGroupTarget extends AbsDGTarget implem */ @CheckResult public DownloadGroupTarget setGroupUrl(List urls) { - return mGroupDelegate.setGroupUrl(urls); + return mConfigHandler.setGroupUrl(urls); } /** @@ -147,7 +156,7 @@ public class DownloadGroupTarget extends AbsDGTarget implem */ @CheckResult public DownloadGroupTarget setDirPath(String dirPath) { - return mGroupDelegate.setDirPath(dirPath); + return mConfigHandler.setDirPath(dirPath); } /** @@ -155,14 +164,14 @@ public class DownloadGroupTarget extends AbsDGTarget implem */ @CheckResult public DownloadGroupTarget setSubFileName(List subTaskFileName) { - return mGroupDelegate.setSubFileName(subTaskFileName); + return mConfigHandler.setSubFileName(subTaskFileName); } /** * 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度 */ public DownloadGroupTarget setFileLenAdapter(IHttpFileLenAdapter adapter) { - return mHeaderDelegate.setFileLenAdapter(adapter); + return mHttpDelegate.setFileLenAdapter(adapter); } @Override public int getTargetType() { @@ -170,29 +179,29 @@ public class DownloadGroupTarget extends AbsDGTarget implem } @Override protected boolean checkEntity() { - return mGroupDelegate.checkEntity(); + return mConfigHandler.checkEntity(); } @Override public boolean isRunning() { - return mGroupDelegate.isRunning(); + return mConfigHandler.isRunning(); } @Override public boolean taskExists() { - return mGroupDelegate.taskExists(); + return mConfigHandler.taskExists(); } @CheckResult - @Override public DownloadGroupTarget addHeader(@NonNull String key, @NonNull String value) { - return mHeaderDelegate.addHeader(key, value); + public DownloadGroupTarget addHeader(@NonNull String key, @NonNull String value) { + return mHttpDelegate.addHeader(key, value); } @CheckResult - @Override public DownloadGroupTarget addHeaders(Map headers) { - return mHeaderDelegate.addHeaders(headers); + public DownloadGroupTarget addHeaders(Map headers) { + return mHttpDelegate.addHeaders(headers); } @CheckResult - @Override public DownloadGroupTarget setUrlProxy(Proxy proxy) { - return mHeaderDelegate.setUrlProxy(proxy); + public DownloadGroupTarget setUrlProxy(Proxy proxy) { + return mHttpDelegate.setUrlProxy(proxy); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java index 6c6c222a..e65dbe1d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -18,10 +18,9 @@ package com.arialyy.aria.core.download; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; import com.arialyy.aria.core.common.http.GetDelegate; -import com.arialyy.aria.core.common.http.HttpHeaderDelegate; +import com.arialyy.aria.core.common.http.HttpDelegate; import com.arialyy.aria.core.common.http.PostDelegate; import com.arialyy.aria.core.inf.IHttpFileLenAdapter; -import com.arialyy.aria.core.inf.IHttpHeaderDelegate; import java.net.Proxy; import java.util.Map; @@ -29,18 +28,17 @@ import java.util.Map; * Created by lyy on 2016/12/5. * https://github.com/AriaLyy/Aria */ -public class DownloadTarget extends AbsDTarget - implements IHttpHeaderDelegate { - private HttpHeaderDelegate mHeaderDelegate; - private DNormalDelegate mNormalDelegate; +public class DownloadTarget extends AbsDTarget { + private HttpDelegate mHttpDelegate; + private DNormalConfigHandler mConfigHandler; DownloadTarget(DownloadEntity entity, String targetName) { this(entity.getUrl(), targetName); } DownloadTarget(String url, String targetName) { - mNormalDelegate = new DNormalDelegate<>(this, url, targetName); - mHeaderDelegate = new HttpHeaderDelegate<>(this); + mConfigHandler = new DNormalConfigHandler<>(this, url, targetName); + mHttpDelegate = new HttpDelegate<>(this); } /** @@ -48,15 +46,17 @@ public class DownloadTarget extends AbsDTarget */ @CheckResult public PostDelegate asPost() { - return new PostDelegate<>(this); + mHttpDelegate = new PostDelegate<>(this); + return (PostDelegate) mHttpDelegate; } /** - * get参数传递 + * get处理 */ @CheckResult public GetDelegate asGet() { - return new GetDelegate<>(this); + mHttpDelegate = new GetDelegate<>(this); + return (GetDelegate) mHttpDelegate; } /** @@ -80,7 +80,7 @@ public class DownloadTarget extends AbsDTarget */ @CheckResult public DownloadTarget setFilePath(@NonNull String filePath) { - mNormalDelegate.setTempFilePath(filePath); + mConfigHandler.setTempFilePath(filePath); return this; } @@ -94,8 +94,8 @@ public class DownloadTarget extends AbsDTarget */ @CheckResult public DownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) { - mNormalDelegate.setTempFilePath(filePath); - mNormalDelegate.setForceDownload(forceDownload); + mConfigHandler.setTempFilePath(filePath); + mConfigHandler.setForceDownload(forceDownload); return this; } @@ -103,7 +103,7 @@ public class DownloadTarget extends AbsDTarget * 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度 */ public DownloadTarget setFileLenAdapter(IHttpFileLenAdapter adapter) { - return mHeaderDelegate.setFileLenAdapter(adapter); + return mHttpDelegate.setFileLenAdapter(adapter); } /** @@ -114,7 +114,7 @@ public class DownloadTarget extends AbsDTarget } @Override public DownloadTarget updateUrl(String newUrl) { - return mNormalDelegate.updateUrl(newUrl); + return mConfigHandler.updateUrl(newUrl); } @Override public int getTargetType() { @@ -127,29 +127,29 @@ public class DownloadTarget extends AbsDTarget * @param proxy {@link Proxy} */ @CheckResult - @Override public DownloadTarget setUrlProxy(Proxy proxy) { - return mHeaderDelegate.setUrlProxy(proxy); + public DownloadTarget setUrlProxy(Proxy proxy) { + return mHttpDelegate.setUrlProxy(proxy); } @CheckResult - @Override public DownloadTarget addHeader(@NonNull String key, @NonNull String value) { - return mHeaderDelegate.addHeader(key, value); + public DownloadTarget addHeader(@NonNull String key, @NonNull String value) { + return mHttpDelegate.addHeader(key, value); } @CheckResult - @Override public DownloadTarget addHeaders(Map headers) { - return mHeaderDelegate.addHeaders(headers); + public DownloadTarget addHeaders(Map headers) { + return mHttpDelegate.addHeaders(headers); } @Override protected boolean checkEntity() { - return mNormalDelegate.checkEntity(); + return mConfigHandler.checkEntity(); } @Override public boolean isRunning() { - return mNormalDelegate.isRunning(); + return mConfigHandler.isRunning(); } @Override public boolean taskExists() { - return mNormalDelegate.taskExists(); + return mConfigHandler.taskExists(); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirConfigHandler.java new file mode 100644 index 00000000..1d37b712 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirConfigHandler.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.text.TextUtils; +import com.arialyy.aria.core.FtpUrlEntity; +import com.arialyy.aria.core.inf.AbsTaskWrapper; +import com.arialyy.aria.util.ALog; + +/** + * Created by lyy on 2017/4/9. + * ftp文件夹下载功能代理 + */ +class FtpDirConfigHandler extends AbsGroupConfigHandler { + FtpDirConfigHandler(FtpDirDownloadTarget target, DGTaskWrapper wrapper) { + super(target, wrapper); + wrapper.setRequestType(AbsTaskWrapper.D_FTP_DIR); + } + + @Override public boolean checkEntity() { + boolean b = checkDirPath() && checkUrl(); + if (b) { + getEntity().save(); + if (getTaskWrapper().getSubTaskWrapper() != null) { + //初始化子项的登录信息 + FtpUrlEntity tUrlEntity = getTaskWrapper().asFtp().getUrlEntity(); + for (DTaskWrapper wrapper : getTaskWrapper().getSubTaskWrapper()) { + FtpUrlEntity urlEntity = wrapper.asFtp().getUrlEntity(); + urlEntity.needLogin = tUrlEntity.needLogin; + urlEntity.account = tUrlEntity.account; + urlEntity.user = tUrlEntity.user; + urlEntity.password = tUrlEntity.password; + // 处理ftps详细 + if (tUrlEntity.isFtps) { + urlEntity.isFtps = true; + urlEntity.protocol = tUrlEntity.protocol; + urlEntity.storePath = tUrlEntity.storePath; + urlEntity.storePass = tUrlEntity.storePass; + urlEntity.keyAlias = tUrlEntity.keyAlias; + } + } + } + } + if (getTaskWrapper().asFtp().getUrlEntity().isFtps) { + if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().storePath)) { + ALog.e(TAG, "证书路径为空"); + return false; + } + if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().keyAlias)) { + ALog.e(TAG, "证书别名为空"); + return false; + } + } + return b; + } + + /** + * 检查普通任务的下载地址 + * + * @return {@code true}地址合法 + */ + private boolean checkUrl() { + final String url = getGroupHash(); + if (TextUtils.isEmpty(url)) { + ALog.e(TAG, "下载失败,url为null"); + return false; + } else if (!url.startsWith("ftp")) { + ALog.e(TAG, "下载失败,url【" + url + "】错误"); + return false; + } + int index = url.indexOf("://"); + if (index == -1) { + ALog.e(TAG, "下载失败,url【" + url + "】不合法"); + return false; + } + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java index af7c081b..71899fde 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java @@ -1,114 +1,114 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.download; - -import android.support.annotation.CheckResult; -import com.arialyy.aria.core.common.ftp.FTPSDelegate; -import com.arialyy.aria.core.common.ftp.FtpDelegate; -import com.arialyy.aria.core.inf.IFtpTarget; -import com.arialyy.aria.core.manager.TaskWrapperManager; -import java.net.Proxy; - -/** - * Created by Aria.Lao on 2017/7/26. - * ftp文件夹下载 - */ -public class FtpDirDownloadTarget extends AbsDGTarget - implements IFtpTarget { - private FtpDelegate mFtpDelegate; - private FtpDirDelegate mDirDelegate; - - FtpDirDownloadTarget(String url, String targetName) { - setTargetName(targetName); - init(url); - } - - private void init(String key) { - mDirDelegate = new FtpDirDelegate(this, - TaskWrapperManager.getInstance().getFtpTaskWrapper(DGTaskWrapper.class, key)); - mFtpDelegate = new FtpDelegate<>(this); - } - - @Override public int getTargetType() { - return GROUP_FTP_DIR; - } - - @Override protected boolean checkEntity() { - return mDirDelegate.checkEntity(); - } - - @Override public boolean isRunning() { - return mDirDelegate.isRunning(); - } - - @Override public boolean taskExists() { - return mDirDelegate.taskExists(); - } - - /** - * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。 - * 如:groupDirPath = "/mnt/sdcard/download/group_test" - *
-   *   {@code
-   *      + mnt
-   *        + sdcard
-   *          + download
-   *            + group_test
-   *              - task1.apk
-   *              - task2.apk
-   *              - task3.apk
-   *              ....
-   *
-   *   }
-   * 
- * - * @param dirPath 任务组保存文件夹路径 - */ - @CheckResult - public FtpDirDownloadTarget setDirPath(String dirPath) { - return mDirDelegate.setDirPath(dirPath); - } - - /** - * 是否是FTPS协议 - * 如果是FTPS协议,需要使用{@link FTPSDelegate#setStorePath(String)} 、{@link FTPSDelegate#setAlias(String)} - * 设置证书信息 - */ - @CheckResult - public FTPSDelegate asFtps() { - getTaskWrapper().asFtp().getUrlEntity().isFtps = true; - return new FTPSDelegate<>(this); - } - - @CheckResult - @Override public FtpDirDownloadTarget charSet(String charSet) { - return mFtpDelegate.charSet(charSet); - } - - @CheckResult - @Override public FtpDirDownloadTarget login(String userName, String password) { - return mFtpDelegate.login(userName, password); - } - - @CheckResult - @Override public FtpDirDownloadTarget login(String userName, String password, String account) { - return mFtpDelegate.login(userName, password, account); - } - - @Override public FtpDirDownloadTarget setProxy(Proxy proxy) { - return mFtpDelegate.setProxy(proxy); - } -} +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.support.annotation.CheckResult; +import com.arialyy.aria.core.common.ftp.FTPSDelegate; +import com.arialyy.aria.core.common.ftp.FtpDelegate; +import com.arialyy.aria.core.inf.IFtpTarget; +import com.arialyy.aria.core.manager.TaskWrapperManager; +import java.net.Proxy; + +/** + * Created by Aria.Lao on 2017/7/26. + * ftp文件夹下载 + */ +public class FtpDirDownloadTarget extends AbsDGTarget + implements IFtpTarget { + private FtpDelegate mFtpDelegate; + private FtpDirConfigHandler mConfigHandler; + + FtpDirDownloadTarget(String url, String targetName) { + setTargetName(targetName); + init(url); + } + + private void init(String key) { + mConfigHandler = new FtpDirConfigHandler(this, + TaskWrapperManager.getInstance().getFtpTaskWrapper(DGTaskWrapper.class, key)); + mFtpDelegate = new FtpDelegate<>(this); + } + + @Override public int getTargetType() { + return GROUP_FTP_DIR; + } + + @Override protected boolean checkEntity() { + return mConfigHandler.checkEntity(); + } + + @Override public boolean isRunning() { + return mConfigHandler.isRunning(); + } + + @Override public boolean taskExists() { + return mConfigHandler.taskExists(); + } + + /** + * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。 + * 如:groupDirPath = "/mnt/sdcard/download/group_test" + *
+   *   {@code
+   *      + mnt
+   *        + sdcard
+   *          + download
+   *            + group_test
+   *              - task1.apk
+   *              - task2.apk
+   *              - task3.apk
+   *              ....
+   *
+   *   }
+   * 
+ * + * @param dirPath 任务组保存文件夹路径 + */ + @CheckResult + public FtpDirDownloadTarget setDirPath(String dirPath) { + return mConfigHandler.setDirPath(dirPath); + } + + /** + * 是否是FTPS协议 + * 如果是FTPS协议,需要使用{@link FTPSDelegate#setStorePath(String)} 、{@link FTPSDelegate#setAlias(String)} + * 设置证书信息 + */ + @CheckResult + public FTPSDelegate asFtps() { + getTaskWrapper().asFtp().getUrlEntity().isFtps = true; + return new FTPSDelegate<>(this); + } + + @CheckResult + @Override public FtpDirDownloadTarget charSet(String charSet) { + return mFtpDelegate.charSet(charSet); + } + + @CheckResult + @Override public FtpDirDownloadTarget login(String userName, String password) { + return mFtpDelegate.login(userName, password); + } + + @CheckResult + @Override public FtpDirDownloadTarget login(String userName, String password, String account) { + return mFtpDelegate.login(userName, password, account); + } + + @Override public FtpDirDownloadTarget setProxy(Proxy proxy) { + return mFtpDelegate.setProxy(proxy); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java index 632aa368..f94644df 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java @@ -33,21 +33,21 @@ import java.net.Proxy; public class FtpDownloadTarget extends AbsDTarget implements IFtpTarget { private FtpDelegate mFtpDelegate; - private DNormalDelegate mNormalDelegate; + private DNormalConfigHandler mConfigHandler; FtpDownloadTarget(DownloadEntity entity, String targetName) { this(entity.getUrl(), targetName); } FtpDownloadTarget(String url, String targetName) { - mNormalDelegate = new DNormalDelegate<>(this, url, targetName); + mConfigHandler = new DNormalConfigHandler<>(this, url, targetName); init(); } private void init() { - int lastIndex = mNormalDelegate.getUrl().lastIndexOf("/"); - getEntity().setFileName(mNormalDelegate.getUrl().substring(lastIndex + 1)); - getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(mNormalDelegate.getUrl())); + int lastIndex = mConfigHandler.getUrl().lastIndexOf("/"); + getEntity().setFileName(mConfigHandler.getUrl().substring(lastIndex + 1)); + getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(mConfigHandler.getUrl())); getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP); mFtpDelegate = new FtpDelegate<>(this); @@ -75,15 +75,15 @@ public class FtpDownloadTarget extends AbsDTarget return false; } } - return mNormalDelegate.checkEntity(); + return mConfigHandler.checkEntity(); } @Override public boolean isRunning() { - return mNormalDelegate.isRunning(); + return mConfigHandler.isRunning(); } @Override public boolean taskExists() { - return mNormalDelegate.taskExists(); + return mConfigHandler.taskExists(); } /** @@ -106,7 +106,7 @@ public class FtpDownloadTarget extends AbsDTarget */ @CheckResult public FtpDownloadTarget setFilePath(@NonNull String filePath) { - mNormalDelegate.setTempFilePath(filePath); + mConfigHandler.setTempFilePath(filePath); return this; } @@ -120,8 +120,8 @@ public class FtpDownloadTarget extends AbsDTarget */ @CheckResult public FtpDownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) { - mNormalDelegate.setTempFilePath(filePath); - mNormalDelegate.setForceDownload(forceDownload); + mConfigHandler.setTempFilePath(filePath); + mConfigHandler.setForceDownload(forceDownload); return this; } @@ -150,6 +150,6 @@ public class FtpDownloadTarget extends AbsDTarget } @Override public FtpDownloadTarget updateUrl(String newUrl) { - return mNormalDelegate.updateUrl(newUrl); + return mConfigHandler.updateUrl(newUrl); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/HttpGroupConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/download/HttpGroupConfigHandler.java new file mode 100644 index 00000000..b182a875 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/HttpGroupConfigHandler.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.support.annotation.CheckResult; +import android.text.TextUtils; +import com.arialyy.aria.core.common.RequestEnum; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CommonUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by lyy on 2019/4/9. + * + * http组合任务功能代理 + */ +class HttpGroupConfigHandler extends AbsGroupConfigHandler { + + /** + * 子任务下载地址, + */ + private List mUrls = new ArrayList<>(); + + /** + * 子任务文件名 + */ + private List mSubNameTemp = new ArrayList<>(); + + HttpGroupConfigHandler(DownloadGroupTarget target, DGTaskWrapper wrapper) { + super(target, wrapper); + mUrls.addAll(wrapper.getEntity().getUrls()); + } + + @CheckResult + DownloadGroupTarget setGroupUrl(List urls) { + mUrls.clear(); + mUrls.addAll(urls); + return getTarget(); + } + + /** + * 设置子任务文件名,该方法必须在{@link #setDirPath(String)}之后调用,否则不生效 + */ + @CheckResult + DownloadGroupTarget setSubFileName(List subTaskFileName) { + if (subTaskFileName == null || subTaskFileName.isEmpty()) { + ALog.w(TAG, "修改子任务的文件名失败:列表为null"); + return getTarget(); + } + if (subTaskFileName.size() != getTaskWrapper().getSubTaskWrapper().size()) { + ALog.w(TAG, "修改子任务的文件名失败:子任务文件名列表数量和子任务的数量不匹配"); + return getTarget(); + } + mSubNameTemp.clear(); + mSubNameTemp.addAll(subTaskFileName); + return getTarget(); + } + + /** + * 更新组合任务下载地址 + * + * @param urls 新的组合任务下载地址列表 + */ + @CheckResult + DownloadGroupTarget updateUrls(List urls) { + if (urls == null || urls.isEmpty()) { + throw new NullPointerException("下载地址列表为空"); + } + if (urls.size() != mUrls.size()) { + throw new IllegalArgumentException("新下载地址数量和旧下载地址数量不一致"); + } + mUrls.clear(); + mUrls.addAll(urls); + String newHash = CommonUtil.getMd5Code(urls); + setGroupHash(newHash); + getEntity().setGroupHash(newHash); + getEntity().update(); + if (getEntity().getSubEntities() != null && !getEntity().getSubEntities().isEmpty()) { + for (DownloadEntity de : getEntity().getSubEntities()) { + de.setGroupHash(newHash); + de.update(); + } + } + return getTarget(); + } + + @Override public boolean checkEntity() { + if (!checkDirPath()) { + return false; + } + + if (!checkSubName()) { + return false; + } + + if (!checkUrls()) { + return false; + } + + if (!getTaskWrapper().isUnknownSize() && getTaskWrapper().getEntity().getFileSize() == 0) { + ALog.e(TAG, "组合任务必须设置文件文件大小,默认需要强制设置文件大小。如果无法获取到总长度,请调用#unknownSize()来标志该组合任务"); + return false; + } + + if (getTaskWrapper().asHttp().getRequestEnum() == RequestEnum.POST) { + for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) { + subTask.asHttp().setRequestEnum(RequestEnum.POST); + } + } + + if (isNeedModifyPath()) { + reChangeDirPath(getDirPathTemp()); + } + + if (!mSubNameTemp.isEmpty()) { + updateSingleSubFileName(); + } + saveEntity(); + return true; + } + + private void saveEntity() { + getEntity().save(); + DbEntity.saveAll(getEntity().getSubEntities()); + } + + /** + * 更新所有改动的子任务文件名 + */ + private void updateSingleSubFileName() { + List entities = getTaskWrapper().getSubTaskWrapper(); + int i = 0; + for (DTaskWrapper taskWrapper : entities) { + if (i < mSubNameTemp.size()) { + String newName = mSubNameTemp.get(i); + DownloadEntity entity = taskWrapper.getEntity(); + if (!newName.equals(entity.getFileName())) { + String oldPath = getEntity().getDirPath() + "/" + entity.getFileName(); + String newPath = getEntity().getDirPath() + "/" + newName; + if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=? or isComplete='true'", + newPath)) { + ALog.w(TAG, String.format("更新文件名失败,路径【%s】已存在或文件已下载", newPath)); + return; + } + + CommonUtil.modifyTaskRecord(oldPath, newPath); + entity.setDownloadPath(newPath); + entity.setFileName(newName); + } + } + i++; + } + } + + /** + * 检查urls是否合法,并删除不合法的子任务 + * + * @return {@code true} 合法 + */ + private boolean checkUrls() { + if (mUrls.isEmpty()) { + ALog.e(TAG, "下载失败,子任务下载列表为null"); + return false; + } + + Set repeated = new HashSet<>(); + List results = new ArrayList<>(); + for (String url : mUrls) { + if (!repeated.add(url)) { + results.add(url); + } + } + if (!results.isEmpty()) { + ALog.e(TAG, String.format("组合任务中有url重复,重复的url:%s", Arrays.toString(results.toArray()))); + return false; + } + + Set delItem = new HashSet<>(); + + int i = 0; + for (String url : mUrls) { + if (TextUtils.isEmpty(url)) { + ALog.e(TAG, "子任务url为null,即将删除该子任务。"); + delItem.add(i); + continue; + } else if (!url.startsWith("http")) { + ALog.e(TAG, "子任务url【" + url + "】错误,即将删除该子任务。"); + delItem.add(i); + continue; + } + int index = url.indexOf("://"); + if (index == -1) { + ALog.e(TAG, "子任务url【" + url + "】不合法,即将删除该子任务。"); + delItem.add(i); + continue; + } + + i++; + } + + for (int index : delItem) { + mUrls.remove(index); + if (mSubNameTemp != null && !mSubNameTemp.isEmpty()) { + mSubNameTemp.remove(index); + } + } + + getEntity().setGroupHash(CommonUtil.getMd5Code(mUrls)); + + return true; + } + + /** + * 如果用户设置了子任务文件名,检查子任务文件名 + * + * @return {@code true} 合法 + */ + private boolean checkSubName() { + if (mSubNameTemp == null || mSubNameTemp.isEmpty()) { + return true; + } + if (mUrls.size() != mSubNameTemp.size()) { + ALog.e(TAG, "子任务文件名必须和子任务数量一致"); + return false; + } + + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ConnectionHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ConnectionHelp.java index 8d035fac..a3c5920c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ConnectionHelp.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ConnectionHelp.java @@ -19,7 +19,7 @@ import android.text.TextUtils; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.ProtocolType; import com.arialyy.aria.core.common.RequestEnum; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.SSLContextUtil; @@ -52,7 +52,7 @@ class ConnectionHelp { * * @throws MalformedURLException */ - static URL handleUrl(String url, HttpTaskDelegate taskDelegate) throws MalformedURLException { + static URL handleUrl(String url, HttpTaskConfig taskDelegate) throws MalformedURLException { Map params = taskDelegate.getParams(); if (params != null && taskDelegate.getRequestEnum() == RequestEnum.GET) { if (url.contains("?")) { @@ -98,7 +98,7 @@ class ConnectionHelp { * * @throws IOException */ - static HttpURLConnection handleConnection(URL url, HttpTaskDelegate taskDelegate) + static HttpURLConnection handleConnection(URL url, HttpTaskConfig taskDelegate) throws IOException { HttpURLConnection conn; URLConnection urlConn; @@ -130,7 +130,7 @@ class ConnectionHelp { * * @throws ProtocolException */ - static HttpURLConnection setConnectParam(HttpTaskDelegate delegate, HttpURLConnection conn) { + static HttpURLConnection setConnectParam(HttpTaskConfig delegate, HttpURLConnection conn) { if (delegate.getRequestEnum() == RequestEnum.POST) { conn.setDoInput(true); conn.setDoOutput(true); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java index 012395e3..5cb2338e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java @@ -24,7 +24,7 @@ import com.arialyy.aria.core.common.OnFileInfoCallback; import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.core.inf.IHttpFileLenAdapter; import com.arialyy.aria.exception.AriaIOException; import com.arialyy.aria.exception.BaseException; @@ -58,7 +58,7 @@ public class HttpFileInfoThread implements Runnable { private DTaskWrapper mTaskWrapper; private int mConnectTimeOut; private OnFileInfoCallback onFileInfoCallback; - private HttpTaskDelegate mTaskDelegate; + private HttpTaskConfig mTaskDelegate; public HttpFileInfoThread(DTaskWrapper taskWrapper, OnFileInfoCallback callback) { this.mTaskWrapper = taskWrapper; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java index bfca0922..d0c6aad3 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java @@ -22,7 +22,7 @@ import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.config.DownloadConfig; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.exception.AriaIOException; import com.arialyy.aria.exception.TaskException; @@ -71,7 +71,7 @@ final class HttpThreadTask extends AbsThreadTask { //当前子线程的下载位置 mChildCurrentLocation = getConfig().START_LOCATION; try { - HttpTaskDelegate taskDelegate = getTaskWrapper().asHttp(); + HttpTaskConfig taskDelegate = getTaskWrapper().asHttp(); URL url = ConnectionHelp.handleUrl(getConfig().URL, taskDelegate); conn = ConnectionHelp.handleConnection(url, taskDelegate); if (getConfig().SUPPORT_BP) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java index b5e54219..1f537948 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java @@ -18,7 +18,6 @@ package com.arialyy.aria.core.download.group; import android.os.Handler; import android.os.Looper; import com.arialyy.aria.core.common.IUtil; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; import com.arialyy.aria.core.config.Configuration; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java index a953975f..17b6ea11 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java @@ -18,7 +18,7 @@ package com.arialyy.aria.core.download.group; import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.OnFileInfoCallback; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DownloadEntity; @@ -156,8 +156,8 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil { * 子任务使用父包裹器的属性 */ private void cloneHeader(DTaskWrapper taskWrapper) { - HttpTaskDelegate groupDelegate = mGTWrapper.asHttp(); - HttpTaskDelegate subDelegate = taskWrapper.asHttp(); + HttpTaskConfig groupDelegate = mGTWrapper.asHttp(); + HttpTaskConfig subDelegate = taskWrapper.asHttp(); // 设置属性 subDelegate.setFileLenAdapter(groupDelegate.getFileLenAdapter()); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Delegate.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Delegate.java index 08a8a365..a9c03ded 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Delegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Delegate.java @@ -15,8 +15,21 @@ */ package com.arialyy.aria.core.download.m3u8; +import com.arialyy.aria.core.common.BaseDelegate; +import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.inf.AbsTaskWrapper; + /** - * + * m3u8 委托 */ -public class M3U8Delegate { +public class M3U8Delegate extends BaseDelegate { + + public M3U8Delegate(TARGET target) { + super(target); + mTarget.getTaskWrapper().setRequestType(AbsTaskWrapper.M3U8_FILE); + } + + //public M3U8LiveDelegate asLive(){ + // return + //} } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java new file mode 100644 index 00000000..6ddcf18c --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download.m3u8; + +/** + * m3u8直播参数设置 + */ +public class M3U8LiveDelegate { + + M3U8LiveDelegate(M3U8Delegate delegate){ + + } + + /** + * 设置缓存目录 + * @param cacheDir 缓存目录路径 + * @return + */ + public M3U8LiveDelegate setCacheDir(String cacheDir){ + return this; + } + +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskWrapper.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskWrapper.java index 5ed8545e..42a5625e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskWrapper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskWrapper.java @@ -15,8 +15,8 @@ */ package com.arialyy.aria.core.inf; -import com.arialyy.aria.core.common.ftp.FtpTaskDelegate; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; +import com.arialyy.aria.core.common.ftp.FtpTaskConfig; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.core.config.BaseTaskConfig; import com.arialyy.aria.core.config.DGroupConfig; import com.arialyy.aria.core.config.DownloadConfig; @@ -31,8 +31,8 @@ import com.arialyy.aria.core.upload.UploadEntity; public abstract class AbsTaskWrapper implements ITaskWrapper { - private HttpTaskDelegate httpTaskDelegate; - private FtpTaskDelegate ftpTaskDelegate; + private HttpTaskConfig httpTaskConfig; + private FtpTaskConfig ftpTaskConfig; /** * 刷新信息 {@code true} 重新刷新下载信息 @@ -94,21 +94,21 @@ public abstract class AbsTaskWrapper /** * 设置或获取HTTP任务相关参数 */ - public HttpTaskDelegate asHttp() { - if (httpTaskDelegate == null) { - httpTaskDelegate = new HttpTaskDelegate(); + public HttpTaskConfig asHttp() { + if (httpTaskConfig == null) { + httpTaskConfig = new HttpTaskConfig(); } - return httpTaskDelegate; + return httpTaskConfig; } /** * 设置或获取FTP任务相关参数 */ - public FtpTaskDelegate asFtp() { - if (ftpTaskDelegate == null) { - ftpTaskDelegate = new FtpTaskDelegate(); + public FtpTaskConfig asFtp() { + if (ftpTaskConfig == null) { + ftpTaskConfig = new FtpTaskConfig(); } - return ftpTaskDelegate; + return ftpTaskConfig; } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IConfigHandler.java new file mode 100644 index 00000000..4fc3d8aa --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IConfigHandler.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by lyy on 2019/4/5. + * 普通任务配置处理 + */ +public interface IConfigHandler { + + /** + * 获取实体 + */ + AbsEntity getEntity(); + + /** + * 任务是否存在 + * + * @return {@code true}任务存在,{@code false} 任务不存在 + */ + boolean taskExists(); + + /** + * 任务是否在执行 + * + * @return {@code true} 任务正在执行,{@code false} 任务没有执行 + */ + boolean isRunning(); + + /** + * 检查下载实体,判断实体是否合法 合法标准为: + * 1、下载路径不为null,并且下载路径是正常的http或ftp路径 + * 2、保存路径不为null,并且保存路径是android文件系统路径 + * 3、保存路径不能重复 + * + * @return {@code true}合法 + */ + boolean checkEntity(); + + /** + * 检查并设置普通任务的文件保存路径 + * + * @return {@code true}保存路径合法 + */ + boolean checkFilePath(); + + /** + * 检查普通任务的下载地址 + * + * @return {@code true}地址合法 + */ + boolean checkUrl(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IGroupConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IGroupConfigHandler.java new file mode 100644 index 00000000..c5608ae4 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IGroupConfigHandler.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by lyy on 2019/4/5. + * 组合任务配置处理 + */ +public interface IGroupConfigHandler { + + /** + * 获取实体 + */ + AbsEntity getEntity(); + + /** + * 任务是否存在 + * + * @return {@code true}任务存在,{@code false} 任务不存在 + */ + boolean taskExists(); + + /** + * 任务是否在执行 + * + * @return {@code true} 任务正在执行,{@code false} 任务没有执行 + */ + boolean isRunning(); + + /** + * 检查实体是否合法 + * + * @return {@code true}合法 + */ + boolean checkEntity(); + + /** + * 检查文件夹路径 + * 1、文件夹路径不能为空 + * 2、文件夹路径不能是文件 + * + * @return {@code true} 合法 + */ + boolean checkDirPath(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskConfig.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskConfig.java new file mode 100644 index 00000000..72ab22c4 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskConfig.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by AriaL on 2017/6/29. + * 任务信息设置接口 + */ +public interface ITaskConfig { + +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskWrapper.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskWrapper.java index a3e0ccff..feeaced2 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskWrapper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskWrapper.java @@ -49,5 +49,15 @@ public interface ITaskWrapper { */ int U_FTP = 6; + /** + * M3u8文件 + */ + int M3U8_FILE = 7; + + /** + * m3u8直播 + */ + int M3U8_LIVE = 8; + ENTITY getEntity(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java index e9e5e81e..40468674 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java @@ -33,10 +33,10 @@ import java.net.Proxy; public class FtpUploadTarget extends AbsUploadTarget implements IFtpTarget { private FtpDelegate mFtpDelegate; - private UNormalDelegate mNormalDelegate; + private UNormalConfigHandler mConfigHandler; FtpUploadTarget(String filePath, String targetName) { - mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName); + mConfigHandler = new UNormalConfigHandler<>(this, filePath, targetName); initTask(); } @@ -51,7 +51,7 @@ public class FtpUploadTarget extends AbsUploadTarget * @param tempUrl 上传路径 */ public FtpUploadTarget setUploadUrl(String tempUrl) { - mNormalDelegate.setTempUrl(tempUrl); + mConfigHandler.setTempUrl(tempUrl); return this; } @@ -60,7 +60,7 @@ public class FtpUploadTarget extends AbsUploadTarget */ @CheckResult public FtpUploadTarget setUploadInterceptor(@NonNull IFtpUploadInterceptor uploadInterceptor) { - return mNormalDelegate.setUploadInterceptor(uploadInterceptor); + return mConfigHandler.setUploadInterceptor(uploadInterceptor); } /** @@ -88,7 +88,7 @@ public class FtpUploadTarget extends AbsUploadTarget } @Override public FtpUploadTarget login(String userName, String password, String account) { - CheckUtil.checkFtpUploadUrl(mNormalDelegate.getTempUrl()); + CheckUtil.checkFtpUploadUrl(mConfigHandler.getTempUrl()); return mFtpDelegate.login(userName, password, account); } @@ -97,15 +97,15 @@ public class FtpUploadTarget extends AbsUploadTarget } @Override protected boolean checkEntity() { - return mNormalDelegate.checkEntity(); + return mConfigHandler.checkEntity(); } @Override public boolean isRunning() { - return mNormalDelegate.isRunning(); + return mConfigHandler.isRunning(); } @Override public boolean taskExists() { - return mNormalDelegate.taskExists(); + return mConfigHandler.taskExists(); } @Override public int getTargetType() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalConfigHandler.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalConfigHandler.java new file mode 100644 index 00000000..eadd54df --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalConfigHandler.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.text.TextUtils; +import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor; +import com.arialyy.aria.core.inf.IConfigHandler; +import com.arialyy.aria.core.manager.TaskWrapperManager; +import com.arialyy.aria.core.queue.UploadTaskQueue; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.io.File; + +/** + * Created by Aria.Lao on 2019/4/5. + * 普通上传任务通用功能处理 + */ +class UNormalConfigHandler implements IConfigHandler { + private String TAG = "UNormalDelegate"; + private UploadEntity mEntity; + private TARGET mTarget; + /** + * 上传路径 + */ + private String mTempUrl; + + UNormalConfigHandler(TARGET target, String filePath, String targetName) { + mTarget = target; + initTarget(filePath, targetName); + } + + private void initTarget(String filePath, String targetName) { + UTaskWrapper taskWrapper = + TaskWrapperManager.getInstance().getHttpTaskWrapper(UTaskWrapper.class, filePath); + mEntity = taskWrapper.getEntity(); + File file = new File(filePath); + mEntity.setFileName(file.getName()); + mEntity.setFileSize(file.length()); + mTarget.setTargetName(targetName); + mTarget.setTaskWrapper(taskWrapper); + mTempUrl = mEntity.getUrl(); + } + + TARGET updateUrl(String newUrl) { + mTempUrl = newUrl; + return mTarget; + } + + TARGET setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) { + if (uploadInterceptor == null) { + throw new NullPointerException("ftp拦截器为空"); + } + mTarget.getTaskWrapper().asFtp().setUploadInterceptor(uploadInterceptor); + return mTarget; + } + + @Override public AbsEntity getEntity() { + return mEntity; + } + + @Override public boolean taskExists() { + return DbEntity.checkDataExist(UploadEntity.class, "key=?", mEntity.getFilePath()); + } + + @Override public boolean isRunning() { + UploadTask task = UploadTaskQueue.getInstance().getTask(mEntity.getKey()); + return task != null && task.isRunning(); + } + + @Override public boolean checkEntity() { + boolean b = checkUrl() && checkFilePath(); + if (b) { + mEntity.save(); + } + if (mTarget.getTaskWrapper().asFtp().getUrlEntity() != null && mTarget.getTaskWrapper() + .asFtp() + .getUrlEntity().isFtps) { + if (TextUtils.isEmpty(mTarget.getTaskWrapper().asFtp().getUrlEntity().storePath)) { + ALog.e(TAG, "证书路径为空"); + return false; + } + if (TextUtils.isEmpty(mTarget.getTaskWrapper().asFtp().getUrlEntity().keyAlias)) { + ALog.e(TAG, "证书别名为空"); + return false; + } + } + return b; + } + + @Override public boolean checkFilePath() { + String filePath = mEntity.getFilePath(); + if (TextUtils.isEmpty(filePath)) { + ALog.e(TAG, "上传失败,文件路径为null"); + return false; + } else if (!filePath.startsWith("/")) { + ALog.e(TAG, "上传失败,文件路径【" + filePath + "】不合法"); + return false; + } + + File file = new File(mEntity.getFilePath()); + if (!file.exists()) { + ALog.e(TAG, "上传失败,文件【" + filePath + "】不存在"); + return false; + } + if (file.isDirectory()) { + ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹"); + return false; + } + return true; + } + + @Override public boolean checkUrl() { + + final String url = mTempUrl; + if (TextUtils.isEmpty(url)) { + ALog.e(TAG, "上传失败,url为null"); + return false; + } else if (!CheckUtil.checkUrlNotThrow(url)) { + ALog.e(TAG, "上传失败,url【" + url + "】错误"); + return false; + } + int index = url.indexOf("://"); + if (index == -1) { + ALog.e(TAG, "上传失败,url【" + url + "】不合法"); + return false; + } + mEntity.setUrl(url); + return true; + } + + void setTempUrl(String tempUrl) { + this.mTempUrl = tempUrl; + mTarget.getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(tempUrl)); + } + + public String getTempUrl() { + return mTempUrl; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java index 58d5af1c..c622db44 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java @@ -17,10 +17,9 @@ package com.arialyy.aria.core.upload; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; -import com.arialyy.aria.core.common.http.HttpHeaderDelegate; +import com.arialyy.aria.core.common.http.HttpDelegate; import com.arialyy.aria.core.common.http.PostDelegate; import com.arialyy.aria.core.inf.AbsTaskWrapper; -import com.arialyy.aria.core.inf.IHttpHeaderDelegate; import java.net.Proxy; import java.util.Map; @@ -28,13 +27,12 @@ import java.util.Map; * Created by lyy on 2017/2/28. * http 单文件上传 */ -public class UploadTarget extends AbsUploadTarget - implements IHttpHeaderDelegate { - private HttpHeaderDelegate mHeaderDelegate; - private UNormalDelegate mNormalDelegate; +public class UploadTarget extends AbsUploadTarget { + private HttpDelegate mHttpDelegate; + private UNormalConfigHandler mConfigHandler; UploadTarget(String filePath, String targetName) { - mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName); + mConfigHandler = new UNormalConfigHandler<>(this, filePath, targetName); initTask(); } @@ -42,7 +40,7 @@ public class UploadTarget extends AbsUploadTarget //http暂时不支持断点上传 getTaskWrapper().setSupportBP(false); getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP); - mHeaderDelegate = new HttpHeaderDelegate<>(this); + mHttpDelegate = new HttpDelegate<>(this); } /** @@ -51,15 +49,17 @@ public class UploadTarget extends AbsUploadTarget * @param tempUrl 上传路径 */ public UploadTarget setUploadUrl(String tempUrl) { - mNormalDelegate.setTempUrl(tempUrl); + mConfigHandler.setTempUrl(tempUrl); return this; } /** * Post处理 */ + @CheckResult public PostDelegate asPost() { - return new PostDelegate<>(this); + mHttpDelegate = new PostDelegate<>(this); + return (PostDelegate) mHttpDelegate; } /** @@ -94,29 +94,29 @@ public class UploadTarget extends AbsUploadTarget } @CheckResult - @Override public UploadTarget addHeader(@NonNull String key, @NonNull String value) { - return mHeaderDelegate.addHeader(key, value); + public UploadTarget addHeader(@NonNull String key, @NonNull String value) { + return mHttpDelegate.addHeader(key, value); } @CheckResult - @Override public UploadTarget addHeaders(Map headers) { - return mHeaderDelegate.addHeaders(headers); + public UploadTarget addHeaders(Map headers) { + return mHttpDelegate.addHeaders(headers); } - @Override public UploadTarget setUrlProxy(Proxy proxy) { - return mHeaderDelegate.setUrlProxy(proxy); + public UploadTarget setUrlProxy(Proxy proxy) { + return mHttpDelegate.setUrlProxy(proxy); } @Override protected boolean checkEntity() { - return mNormalDelegate.checkEntity(); + return mConfigHandler.checkEntity(); } @Override public boolean isRunning() { - return mNormalDelegate.isRunning(); + return mConfigHandler.isRunning(); } @Override public boolean taskExists() { - return mNormalDelegate.taskExists(); + return mConfigHandler.taskExists(); } @Override public int getTargetType() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java index cda1fe28..ea56024c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java @@ -22,9 +22,7 @@ import aria.apache.commons.net.ftp.OnFtpInputStreamListener; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask; -import com.arialyy.aria.core.common.ftp.FtpTaskDelegate; -import com.arialyy.aria.core.config.BaseTaskConfig; -import com.arialyy.aria.core.config.DownloadConfig; +import com.arialyy.aria.core.common.ftp.FtpTaskConfig; import com.arialyy.aria.core.config.UploadConfig; import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.upload.UploadEntity; @@ -130,7 +128,7 @@ class FtpThreadTask extends AbsFtpThreadTask { } private void initPath() throws UnsupportedEncodingException { - FtpTaskDelegate delegate = getTaskWrapper().asFtp(); + FtpTaskConfig delegate = getTaskWrapper().asFtp(); dir = CommonUtil.convertFtpChar(charSet, delegate.getUrlEntity().remotePath); String fileName = diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java index 48f2712d..e4724188 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java @@ -18,8 +18,7 @@ package com.arialyy.aria.core.upload.uploader; import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; -import com.arialyy.aria.core.common.http.HttpTaskDelegate; -import com.arialyy.aria.core.config.BaseTaskConfig; +import com.arialyy.aria.core.common.http.HttpTaskConfig; import com.arialyy.aria.core.config.UploadConfig; import com.arialyy.aria.core.inf.IUploadListener; import com.arialyy.aria.core.upload.UTaskWrapper; @@ -70,7 +69,7 @@ class HttpThreadTask extends AbsThreadTask { URL url; try { url = new URL(getEntity().getUrl()); - HttpTaskDelegate taskDelegate = getTaskWrapper().asHttp(); + HttpTaskConfig taskDelegate = getTaskWrapper().asHttp(); mHttpConn = (HttpURLConnection) url.openConnection(); mHttpConn.setRequestMethod(taskDelegate.getRequestEnum().name); mHttpConn.setUseCaches(false);