loader 重构

This commit is contained in:
laoyuyu
2020-01-01 14:43:52 +08:00
170 changed files with 2862 additions and 21661 deletions

View File

@@ -28,8 +28,8 @@ import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.loader.IInfoTask;
import com.arialyy.aria.core.loader.ILoaderVisitor;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.TaskException;
@@ -47,28 +47,24 @@ import javax.net.ssl.SSLContext;
/**
* Created by Aria.Lao on 2017/7/25. 获取ftp文件夹信息
*/
public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>>
implements Runnable {
public abstract class AbsFtpInfoTask<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>>
implements Runnable, IInfoTask {
protected final String TAG = CommonUtil.getClassName(getClass());
protected ENTITY mEntity;
protected TASK_WRAPPER mTaskWrapper;
protected FtpTaskOption mTaskOption;
private int mConnectTimeOut;
protected OnFileInfoCallback mCallback;
protected long mSize = 0;
protected String charSet = "UTF-8";
private boolean isUpload = false;
protected boolean isUpload = false;
protected Callback callback;
public AbsFtpInfoThread(TASK_WRAPPER taskWrapper, OnFileInfoCallback callback) {
public AbsFtpInfoTask(TASK_WRAPPER taskWrapper) {
mTaskWrapper = taskWrapper;
mEntity = taskWrapper.getEntity();
mTaskOption = (FtpTaskOption) taskWrapper.getTaskOption();
mConnectTimeOut = AriaConfig.getInstance().getDConfig().getConnectTimeOut();
mCallback = callback;
if (mEntity instanceof UploadEntity) {
isUpload = true;
}
}
/**
@@ -78,6 +74,10 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
*/
protected abstract String getRemotePath();
@Override public void setCallback(Callback callback) {
this.callback = callback;
}
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -91,7 +91,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
String remotePath = CommonUtil.convertFtpChar(charSet, getRemotePath());
FTPFile[] files = client.listFiles(remotePath);
FTPFile[] files = client.listFiles(getRemotePath());
boolean isExist = files.length != 0;
if (!isExist && !isUpload) {
int i = remotePath.lastIndexOf(File.separator);
@@ -360,7 +360,6 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
for (FTPFile file : files) {
if (file.isFile()) {
size += file.getSize();
ALog.d(TAG, "isValid = " + file.isValid());
handleFile(path + file.getName(), file);
} else {
String remotePath = CommonUtil.convertFtpChar(charSet, path + file.getName());
@@ -380,7 +379,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
protected void failDownload(FTPClient client, String msg, Exception e, boolean needRetry) {
if (mCallback != null) {
if (callback != null) {
if (client == null) {
msg = "创建ftp客户端失败";
needRetry = false;
@@ -390,10 +389,14 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
needRetry = needRetry && !CheckUtil.ftpIsBadRequest(client.getReplyCode());
}
mCallback.onFail(mEntity, new AriaIOException(TAG, msg), needRetry);
callback.onFail(mEntity, new AriaIOException(TAG, msg), needRetry);
}
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
/**
* 获取可用IP的超时线程InetAddress.getByName没有超时功能需要自己处理超时
*/

View File

@@ -31,7 +31,7 @@ import java.util.ArrayList;
* @Author lyy
* @Date 2019-09-19
*/
public class FtpRecordHandler extends RecordHandler {
public final class FtpRecordHandler extends RecordHandler {
public FtpRecordHandler(AbsTaskWrapper wrapper) {
super(wrapper);
@@ -61,10 +61,10 @@ public class FtpRecordHandler extends RecordHandler {
tr.threadType = getWrapper().getEntity().getTaskType();
//最后一个线程的结束位置即为文件的总长度
if (threadId == (record.threadNum - 1)) {
endL = getEntity().getFileSize();
endL = getFileSize();
}
tr.endLocation = endL;
tr.blockLen = RecordUtil.getBlockLen(getEntity().getFileSize(), threadId, record.threadNum);
tr.blockLen = RecordUtil.getBlockLen(getFileSize(), threadId, record.threadNum);
return tr;
}
@@ -96,7 +96,7 @@ public class FtpRecordHandler extends RecordHandler {
int requestType = getWrapper().getRequestType();
if (requestType == ITaskWrapper.D_FTP || requestType == ITaskWrapper.D_FTP_DIR) {
int threadNum = Configuration.getInstance().downloadCfg.getThreadNum();
return getEntity().getFileSize() <= IRecordHandler.SUB_LEN
return getFileSize() <= IRecordHandler.SUB_LEN
|| getEntity().isGroupChild()
|| threadNum == 1
? 1

View File

@@ -27,7 +27,7 @@ import java.net.Proxy;
/**
* fTP任务设置的信息用户名、密码、端口等信息
*/
public class FtpTaskOption implements ITaskOption {
public final class FtpTaskOption implements ITaskOption {
/**
* 账号和密码
@@ -72,6 +72,15 @@ public class FtpTaskOption implements ITaskOption {
*/
private String activeExternalIPAddress;
//---------------- ftp client 配置信息 start
private String defaultDateFormatStr = null;
private String recentDateFormatStr = null;
private String serverLanguageCode = null;
private String shortMonthNames = null;
private String serverTimeZoneId = null;
private String systemKey = FTPClientConfig.SYST_UNIX;
//---------------- ftp client 配置信息 end
public String getActiveExternalIPAddress() {
return activeExternalIPAddress;
}
@@ -105,6 +114,24 @@ public class FtpTaskOption implements ITaskOption {
}
public FTPClientConfig getClientConfig() {
if (clientConfig == null) {
clientConfig = new FTPClientConfig(systemKey);
if (defaultDateFormatStr != null) {
clientConfig.setDefaultDateFormatStr(defaultDateFormatStr);
}
if (recentDateFormatStr != null) {
clientConfig.setRecentDateFormatStr(recentDateFormatStr);
}
if (serverLanguageCode != null) {
clientConfig.setServerLanguageCode(serverLanguageCode);
}
if (shortMonthNames != null) {
clientConfig.setShortMonthNames(shortMonthNames);
}
if (serverTimeZoneId != null) {
clientConfig.setServerTimeZoneId(serverTimeZoneId);
}
}
return clientConfig;
}

View File

@@ -1,52 +0,0 @@
package com.arialyy.aria.ftp;
import aria.apache.commons.net.ftp.FTPSClient;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Locale;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
public class SSLSessionReuseFTPSClient extends FTPSClient {
SSLSessionReuseFTPSClient(boolean b, SSLContext context) {
super(b, context);
}
// adapted from:
// https://trac.cyberduck.io/browser/trunk/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java
@Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
if (socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket) _socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
//final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
final Field sessionHostPortCache =
context.getClass().getDeclaredField("sessionsByHostAndPort");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method method =
cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
method.setAccessible(true);
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostName(),
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session);
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostAddress(),
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session);
} catch (NoSuchFieldException e) {
throw new IOException(e);
} catch (Exception e) {
throw new IOException(e);
}
} else {
throw new IOException("Invalid SSL Session");
}
}
}
}

View File

@@ -19,9 +19,8 @@ import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.ftp.AbsFtpInfoThread;
import com.arialyy.aria.ftp.AbsFtpInfoTask;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.FileUtil;
@@ -29,17 +28,16 @@ import com.arialyy.aria.util.FileUtil;
* Created by Aria.Lao on 2017/7/25.
* 获取ftp文件信息
*/
class FtpDFileInfoThread extends AbsFtpInfoThread<DownloadEntity, DTaskWrapper> {
private final String TAG = "FtpFileInfoThread";
final class FtpDFileInfoTask extends AbsFtpInfoTask<DownloadEntity, DTaskWrapper> {
FtpDFileInfoThread(DTaskWrapper taskEntity, OnFileInfoCallback callback) {
super(taskEntity, callback);
FtpDFileInfoTask(DTaskWrapper taskEntity) {
super(taskEntity);
}
@Override protected void handleFile(String remotePath, FTPFile ftpFile) {
super.handleFile(remotePath, ftpFile);
if (!FileUtil.checkSDMemorySpace(mEntity.getFilePath(), ftpFile.getSize())) {
mCallback.onFail(mEntity, new AriaIOException(TAG,
if (!FileUtil.checkMemorySpace(mEntity.getFilePath(), ftpFile.getSize())) {
callback.onFail(mEntity, new AriaIOException(TAG,
String.format("获取ftp文件信息失败内存空间不足, filePath: %s", mEntity.getFilePath())),
false);
}
@@ -56,6 +54,6 @@ class FtpDFileInfoThread extends AbsFtpInfoThread<DownloadEntity, DTaskWrapper>
mTaskWrapper.setNewTask(true);
}
mEntity.setFileSize(mSize);
mCallback.onComplete(mEntity.getUrl(), new CompleteInfo(code, mTaskWrapper));
callback.onSucceed(mEntity.getUrl(), new CompleteInfo(code, mTaskWrapper));
}
}

View File

@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.ftp;
package com.arialyy.aria.ftp.download;
import android.net.Uri;
import android.text.TextUtils;
import aria.apache.commons.net.ftp.FTPClient;
import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.FtpUrlEntity;
@@ -23,8 +25,9 @@ import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.ftp.AbsFtpInfoTask;
import com.arialyy.aria.ftp.FtpTaskOption;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.RecordUtil;
import java.nio.charset.Charset;
@@ -33,10 +36,18 @@ import java.util.ArrayList;
/**
* Created by Aria.Lao on 2017/7/25. 获取ftp文件夹信息
*/
public class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTaskWrapper> {
final class FtpDGInfoTask extends AbsFtpInfoTask<DownloadGroupEntity, DGTaskWrapper> {
public FtpDirInfoThread(DGTaskWrapper taskEntity, OnFileInfoCallback callback) {
super(taskEntity, callback);
FtpDGInfoTask(DGTaskWrapper wrapper) {
super(wrapper);
}
@Override public void run() {
if (mTaskWrapper.getEntity().getFileSize() > 1) {
callback.onSucceed(mEntity.getKey(), new CompleteInfo(200, mTaskWrapper));
} else {
super.run();
}
}
@Override protected String getRemotePath() {
@@ -51,7 +62,29 @@ public class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTa
@Override protected void onPreComplete(int code) {
super.onPreComplete(code);
mEntity.setFileSize(mSize);
mCallback.onComplete(mEntity.getKey(), new CompleteInfo(code, mTaskWrapper));
for (DTaskWrapper wrapper : mTaskWrapper.getSubTaskWrapper()) {
cloneInfo(wrapper);
}
callback.onSucceed(mEntity.getKey(), new CompleteInfo(code, mTaskWrapper));
}
private void cloneInfo(DTaskWrapper subWrapper) {
FtpTaskOption option = (FtpTaskOption) mTaskWrapper.getTaskOption();
FtpUrlEntity urlEntity = option.getUrlEntity().clone();
Uri uri = Uri.parse(subWrapper.getEntity().getUrl());
String remotePath = uri.getPath();
urlEntity.remotePath = TextUtils.isEmpty(remotePath) ? "/" : remotePath;
FtpTaskOption subOption = new FtpTaskOption();
subOption.setUrlEntity(urlEntity);
subOption.setCharSet(option.getCharSet());
subOption.setProxy(option.getProxy());
subOption.setClientConfig(option.getClientConfig());
subOption.setNewFileName(option.getNewFileName());
subOption.setProxy(option.getProxy());
subOption.setUploadInterceptor(option.getUploadInterceptor());
subWrapper.setTaskOption(subOption);
}
/**

View File

@@ -0,0 +1,82 @@
/*
* 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.ftp.download;
import android.os.Looper;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsSubDLoadUtil;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.IInfoTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog;
/**
* ftp 组合任务加载器
*/
final class FtpDGLoader extends AbsGroupLoader {
FtpDGLoader(AbsTaskWrapper groupWrapper, IEventListener listener) {
super(groupWrapper, listener);
}
@Override protected void handlerTask(Looper looper) {
if (isBreak()) {
return;
}
mInfoTask.run();
}
@Override
protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) {
return new FtpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo);
}
/**
* 启动子任务下载
*/
private void startSub() {
// ftp需要获取完成只任务信息才更新只任务数量
getState().setSubSize(getWrapper().getSubTaskWrapper().size());
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
startSubLoader(createSubLoader(wrapper, false));
}
}
}
@Override public void addComponent(IInfoTask infoTask) {
mInfoTask = infoTask;
infoTask.setCallback(new IInfoTask.Callback() {
@Override public void onSucceed(String key, CompleteInfo info) {
if (info.code >= 200 && info.code < 300) {
startSub();
} else {
ALog.e(TAG, "获取任务信息失败code" + info.code);
mListener.onFail(false, null);
}
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
mListener.onFail(needRetry, e);
}
});
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.ftp.download;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.ftp.FtpTaskOption;
/**
* Created by Aria.Lao on 2017/7/27.
* ftp文件夹下载工具
*/
public final class FtpDGLoaderUtil extends AbsGroupLoaderUtil {
public FtpDGLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override protected AbsGroupLoader getLoader() {
return mLoader == null ? new FtpDGLoader(getTaskWrapper(), getListener()) : mLoader;
}
@Override protected LoaderStructure buildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new FtpDGInfoTask((DGTaskWrapper) getTaskWrapper()));
structure.accept(getLoader());
return structure;
}
}

View File

@@ -15,46 +15,39 @@
*/
package com.arialyy.aria.ftp.download;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsLoader;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.ftp.FtpRecordHandler;
import com.arialyy.aria.ftp.FtpTaskOption;
/**
* @Author lyy
* @Date 2019-09-19
*/
public class FtpDLoaderUtil extends AbsNormalLoaderUtil {
public final class FtpDLoaderUtil extends AbsNormalLoaderUtil {
public FtpDLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override protected AbsLoader createLoader() {
NormalLoader loader = new NormalLoader(getListener(), getTaskWrapper());
loader.setAdapter(new FtpDLoaderAdapter(getTaskWrapper()));
return loader;
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new NormalLoader(getTaskWrapper(), getListener()) : mLoader;
}
@Override protected Runnable createInfoThread() {
return new FtpDFileInfoThread((DTaskWrapper) getTaskWrapper(), new OnFileInfoCallback() {
@Override public void onComplete(String url, CompleteInfo info) {
((NormalLoader) getLoader()).updateTempFile();
getLoader().start();
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
fail(e, needRetry);
getLoader().closeTimer();
}
});
public LoaderStructure BuildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new FtpRecordHandler(getTaskWrapper()))
.addComponent(new NormalThreadStateManager(getListener()))
.addComponent(new FtpDFileInfoTask((DTaskWrapper) getTaskWrapper()))
.addComponent(new FtpDTTBuilder(getTaskWrapper()));
structure.accept(getLoader());
return structure;
}
}

View File

@@ -16,15 +16,11 @@
package com.arialyy.aria.ftp.download;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.loader.AbsNormalTTBuilder;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.task.AbsNormalLoaderAdapter;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.task.ThreadTask;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.ftp.FtpRecordHandler;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
@@ -33,12 +29,16 @@ import java.io.File;
* @Author lyy
* @Date 2019-09-19
*/
public class FtpDLoaderAdapter extends AbsNormalLoaderAdapter {
final class FtpDTTBuilder extends AbsNormalTTBuilder {
public FtpDLoaderAdapter(ITaskWrapper wrapper) {
FtpDTTBuilder(AbsTaskWrapper wrapper) {
super(wrapper);
}
@Override public IThreadTaskAdapter getAdapter(SubThreadConfig config) {
return new FtpDThreadTaskAdapter(config);
}
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
if (!record.isBlock) {
if (getTempFile().exists()) {
@@ -57,18 +57,4 @@ public class FtpDLoaderAdapter extends AbsNormalLoaderAdapter {
}
return true;
}
@Override public IThreadTask createThreadTask(SubThreadConfig config) {
ThreadTask threadTask = new ThreadTask(config);
FtpDThreadTaskAdapter adapter = new FtpDThreadTaskAdapter(config);
threadTask.setAdapter(adapter);
return threadTask;
}
@Override public IRecordHandler recordHandler(AbsTaskWrapper wrapper) {
FtpRecordHandler adapter = new FtpRecordHandler(wrapper);
RecordHandler handler = new RecordHandler(wrapper);
handler.setAdapter(adapter);
return handler;
}
}

View File

@@ -1,124 +0,0 @@
/*
* 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.ftp.download;
import android.net.Uri;
import android.text.TextUtils;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
import com.arialyy.aria.core.group.AbsSubDLoadUtil;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.ftp.FtpDirInfoThread;
import com.arialyy.aria.ftp.FtpTaskOption;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by Aria.Lao on 2017/7/27.
* ftp文件夹下载工具
*/
public class FtpDirDLoaderUtil extends AbsGroupLoaderUtil {
private ReentrantLock LOCK = new ReentrantLock();
private Condition condition = LOCK.newCondition();
public FtpDirDLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override
protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) {
return new FtpSubDLoaderUtil(getScheduler(), wrapper, needGetFileInfo);
}
@Override protected boolean onStart() {
super.onStart();
if (getWrapper().getEntity().getFileSize() > 1) {
startDownload(true);
} else {
FtpDirInfoThread infoThread = new FtpDirInfoThread(getWrapper(), new OnFileInfoCallback() {
@Override public void onComplete(String url, CompleteInfo info) {
if (info.code >= 200 && info.code < 300) {
startDownload(false);
}
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
mListener.onFail(needRetry, e);
}
});
new Thread(infoThread).start();
try {
LOCK.lock();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
LOCK.unlock();
}
}
return true;
}
/**
* @param needCloneInfo 第一次下载,信息已经在{@link FtpDirInfoThread}中clone了
*/
private void startDownload(boolean needCloneInfo) {
// ftp需要获取完成只任务信息才更新只任务数量
getState().setSubSize(getWrapper().getSubTaskWrapper().size());
try {
LOCK.lock();
condition.signalAll();
} finally {
LOCK.unlock();
}
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
if (needCloneInfo) {
cloneInfo(wrapper);
}
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
startSubLoader(createSubLoader(wrapper, true));
}
}
}
private void cloneInfo(DTaskWrapper subWrapper) {
FtpTaskOption option = (FtpTaskOption) getWrapper().getTaskOption();
FtpUrlEntity urlEntity = option.getUrlEntity().clone();
Uri uri = Uri.parse(subWrapper.getEntity().getUrl());
String remotePath = uri.getPath();
urlEntity.remotePath = TextUtils.isEmpty(remotePath) ? "/" : remotePath;
FtpTaskOption subOption = new FtpTaskOption();
subOption.setUrlEntity(urlEntity);
subOption.setCharSet(option.getCharSet());
subOption.setProxy(option.getProxy());
subOption.setClientConfig(option.getClientConfig());
subOption.setNewFileName(option.getNewFileName());
subOption.setProxy(option.getProxy());
subOption.setUploadInterceptor(option.getUploadInterceptor());
subWrapper.setTaskOption(subOption);
}
}

View File

@@ -18,30 +18,37 @@ package com.arialyy.aria.ftp.download;
import android.os.Handler;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.group.AbsSubDLoadUtil;
import com.arialyy.aria.core.group.ChildDLoadListener;
import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.SubLoader;
import com.arialyy.aria.ftp.FtpRecordHandler;
/**
* @Author lyy
* @Date 2019-09-28
*/
class FtpSubDLoaderUtil extends AbsSubDLoadUtil {
final class FtpSubDLoaderUtil extends AbsSubDLoadUtil {
/**
* @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息
*/
FtpSubDLoaderUtil(Handler schedulers, DTaskWrapper taskWrapper, boolean needGetInfo) {
super(schedulers, taskWrapper, needGetInfo);
FtpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo) {
super(taskWrapper, schedulers, needGetInfo);
}
@Override protected NormalLoader createLoader(ChildDLoadListener listener, DTaskWrapper wrapper) {
NormalLoader loader = new NormalLoader(listener, wrapper);
FtpDLoaderAdapter adapter = new FtpDLoaderAdapter(wrapper);
loader.setAdapter(adapter);
return loader;
@Override protected SubLoader getLoader() {
if (mDLoader == null) {
mDLoader = new SubLoader(getWrapper(), getSchedulers());
mDLoader.setNeedGetInfo(isNeedGetInfo());
}
return mDLoader;
}
@Override public void start() {
getDownloader().start();
@Override protected LoaderStructure buildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new FtpRecordHandler(getWrapper()))
.addComponent(new FtpDTTBuilder(getWrapper()))
.addComponent(new FtpDFileInfoTask(getWrapper()));
structure.accept(getLoader());
return structure;
}
}

View File

@@ -21,12 +21,11 @@ import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.ftp.AbsFtpInfoThread;
import com.arialyy.aria.ftp.AbsFtpInfoTask;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DbDataHelper;
@@ -38,13 +37,14 @@ import java.util.List;
* Created by Aria.Lao on 2017/9/26.
* 单任务上传远程服务器文件信息
*/
class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
final class FtpUFileInfoTask extends AbsFtpInfoTask<UploadEntity, UTaskWrapper> {
static final int CODE_COMPLETE = 0xab1;
private boolean isComplete = false;
private String remotePath;
FtpUFileInfoThread(UTaskWrapper taskEntity, OnFileInfoCallback callback) {
super(taskEntity, callback);
FtpUFileInfoTask(UTaskWrapper taskEntity) {
super(taskEntity);
isUpload = true;
}
@Override protected String getRemotePath() {
@@ -161,7 +161,7 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
@Override protected void onPreComplete(int code) {
super.onPreComplete(code);
mCallback.onComplete(mEntity.getKey(),
callback.onSucceed(mEntity.getKey(),
new CompleteInfo(isComplete ? CODE_COMPLETE : code, mTaskWrapper));
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.ftp.upload;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.IInfoTask;
import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
final class FtpULoader extends NormalLoader {
FtpULoader(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
}
@Override public void addComponent(IInfoTask infoTask) {
mInfoTask = infoTask;
infoTask.setCallback(new IInfoTask.Callback() {
@Override public void onSucceed(String key, CompleteInfo info) {
if (info.code == FtpUFileInfoTask.CODE_COMPLETE) {
getListener().onComplete();
} else {
startThreadTask();
}
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
getListener().onFail(needRetry, e);
}
});
}
}

View File

@@ -15,50 +15,38 @@
*/
package com.arialyy.aria.ftp.upload;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.listener.IUploadListener;
import com.arialyy.aria.core.loader.AbsLoader;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.ftp.FtpRecordHandler;
import com.arialyy.aria.ftp.FtpTaskOption;
/**
* @Author lyy
* @Date 2019-09-19
*/
public class FtpULoaderUtil extends AbsNormalLoaderUtil {
public final class FtpULoaderUtil extends AbsNormalLoaderUtil {
public FtpULoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override protected AbsLoader createLoader() {
NormalLoader loader = new NormalLoader(getListener(), getTaskWrapper());
loader.setAdapter(new FtpULoaferAdapter(getTaskWrapper()));
return loader;
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new FtpULoader(getTaskWrapper(), getListener()) : mLoader;
}
@Override protected Runnable createInfoThread() {
return new FtpUFileInfoThread((UTaskWrapper) getTaskWrapper(), new OnFileInfoCallback() {
@Override public void onComplete(String url, CompleteInfo info) {
if (info.code == FtpUFileInfoThread.CODE_COMPLETE) {
getListener().onComplete();
} else {
getLoader().start();
}
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
fail(e, needRetry);
}
});
@Override public LoaderStructure BuildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new FtpRecordHandler(getTaskWrapper()))
.addComponent(new NormalThreadStateManager(getListener()))
.addComponent(new FtpUFileInfoTask((UTaskWrapper) getTaskWrapper()))
.addComponent(new FtpUTTBuilder(getTaskWrapper()));
structure.accept(getLoader());
return structure;
}
}

View File

@@ -16,41 +16,26 @@
package com.arialyy.aria.ftp.upload;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.task.AbsNormalLoaderAdapter;
import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.task.ThreadTask;
import com.arialyy.aria.core.loader.AbsNormalTTBuilder;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.ftp.FtpRecordHandler;
/**
* @Author lyy
* @Date 2019-09-19
*/
class FtpULoaferAdapter extends AbsNormalLoaderAdapter {
final class FtpUTTBuilder extends AbsNormalTTBuilder {
FtpULoaferAdapter(ITaskWrapper wrapper) {
FtpUTTBuilder(AbsTaskWrapper wrapper) {
super(wrapper);
}
@Override public IThreadTaskAdapter getAdapter(SubThreadConfig config) {
return new FtpUThreadTaskAdapter(config);
}
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
return true;
}
@Override public IThreadTask createThreadTask(SubThreadConfig config) {
ThreadTask threadTask = new ThreadTask(config);
FtpUThreadTaskAdapter adapter = new FtpUThreadTaskAdapter(config);
threadTask.setAdapter(adapter);
return threadTask;
}
@Override public IRecordHandler recordHandler(AbsTaskWrapper wrapper) {
FtpRecordHandler adapter = new FtpRecordHandler(wrapper);
RecordHandler handler = new RecordHandler(wrapper);
handler.setAdapter(adapter);
return handler;
}
}

View File

@@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit;
/**
* Created by Aria.Lao on 2017/7/28. D_FTP 单线程上传任务需要FTP 服务器给用户打开append和write的权限
*/
class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
private String dir, remotePath;
private boolean storeFail = false;
private ScheduledThreadPoolExecutor timer;