com.acgist.snail.protocol.Protocol Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snail Show documentation
Show all versions of snail Show documentation
基于Java开发的下载工具,支持下载协议:BT(BitTorrent、磁力链接、种子文件)、HLS(M3U8)、FTP、HTTP。
package com.acgist.snail.protocol;
import java.io.File;
import com.acgist.snail.config.DownloadConfig;
import com.acgist.snail.config.SymbolConfig;
import com.acgist.snail.context.EntityContext;
import com.acgist.snail.context.exception.DownloadException;
import com.acgist.snail.downloader.IDownloader;
import com.acgist.snail.pojo.ITaskSession;
import com.acgist.snail.pojo.ITaskSessionStatus.Status;
import com.acgist.snail.pojo.entity.TaskEntity;
import com.acgist.snail.pojo.session.TaskSession;
import com.acgist.snail.utils.FileUtils;
import com.acgist.snail.utils.StringUtils;
/***
* 下载协议
*
* @author acgist
*/
public abstract class Protocol {
/**
* 磁力链接(标准):{@value}
*/
private static final String MAGNET_BASIC = "magnet:\\?.+";
/**
* 磁力链接(32位Hash):{@value}
*/
private static final String MAGNET_HASH_32 = "[a-zA-Z0-9]{32}";
/**
* 磁力链接(40位Hash):{@value}
*/
private static final String MAGNET_HASH_40 = "[a-zA-Z0-9]{40}";
/**
* 协议类型
*
* @author acgist
*/
public enum Type {
/**
* UDP
*/
UDP(
new String[] {"udp://.+"},
new String[] {"udp://"},
new String[] {},
"udp://",
""
),
/**
* TCP
*/
TCP(
new String[] {"tcp://.+"},
new String[] {"tcp://"},
new String[] {},
"tcp://",
""
),
/**
* FTP
*/
FTP(
new String[] {"ftp://.+"},
new String[] {"ftp://"},
new String[] {},
"ftp://",
""
),
/**
* HLS
*/
HLS(
new String[] {"http://.+\\.m3u8", "https://.+\\.m3u8"},
new String[] {},
new String[] {".m3u8"},
"",
".m3u8"
),
/**
* HTTP、HTTPS
*/
HTTP(
new String[] {"http://.+", "https://.+"},
new String[] {"http://", "https://"},
new String[] {},
"http://",
""
),
/**
* 磁力链接
*/
MAGNET(
new String[] {MAGNET_BASIC, MAGNET_HASH_32, MAGNET_HASH_40},
new String[] {"magnet:?xt=urn:btih:"},
new String[] {},
"magnet:?xt=urn:btih:",
""
),
/**
* 迅雷链接
*/
THUNDER(
new String[] {"thunder://.+"},
new String[] {"thunder://"},
new String[] {},
"thunder://",
""
),
/**
* BT:BitTorrent
*/
TORRENT(
new String[] {".+\\.torrent"},
new String[] {},
new String[] {".torrent"},
"",
".torrent"
);
/**
* 正则表达式
*/
private final String[] regexs;
/**
* 前缀
*/
private final String[] prefix;
/**
* 后缀
*/
private final String[] suffix;
/**
* 默认前缀
*/
private final String defaultPrefix;
/**
* 默认后缀
*/
private final String defaultSuffix;
/**
* @param regexs 正则表达式
* @param prefix 前缀
* @param suffix 后缀
* @param defaultPrefix 默认前缀
* @param defaultSuffix 默认后缀
*/
private Type(String[] regexs, String[] prefix, String[] suffix, String defaultPrefix, String defaultSuffix) {
this.regexs = regexs;
this.prefix = prefix;
this.suffix = suffix;
this.defaultPrefix = defaultPrefix;
this.defaultSuffix = defaultSuffix;
}
/**
* 获取正则表达式
*
* @return 正则表达式
*/
public String[] regexs() {
return this.regexs;
}
/**
* 获取前缀
*
* @return 前缀
*/
public String[] prefix() {
return this.prefix;
}
/**
* 获取链接前缀
*
* @param url 链接
*
* @return 前缀
*/
public String prefix(String url) {
for (String value : this.prefix) {
if(StringUtils.startsWith(url, value)) {
return value;
}
}
return null;
}
/**
* 获取后缀
*
* @return 后缀
*/
public String[] suffix() {
return this.suffix;
}
/**
* 获取链接后缀
*
* @param url 链接
*
* @return 后缀
*/
public String suffix(String url) {
for (String value : this.suffix) {
if(StringUtils.endsWith(url, value)) {
return value;
}
}
return null;
}
/**
* 获取默认前缀
*
* @return 默认前缀
*/
public String defaultPrefix() {
return this.defaultPrefix;
}
/**
* 获取默认后缀
*
* @return 默认后缀
*/
public String defaultSuffix() {
return this.defaultSuffix;
}
/**
* 判断协议是否支持下载链接
*
* @param url 链接
*
* @return 是否支持下载链接
*/
public boolean verify(String url) {
for (String regex : this.regexs) {
if(StringUtils.regex(url, regex, true)) {
return true;
}
}
return false;
}
/**
* 将Hash转为完整磁力链接
*
* @param hash Hash
*
* @return 完整磁力链接
*/
public static final String buildMagnet(String hash) {
if(verifyMagnet(hash)) {
return hash;
}
return Type.MAGNET.defaultPrefix + hash.toLowerCase();
}
/**
* 判断是否是完整磁力链接
*
* @param url 磁力链接
*
* @return 是否是完整磁力链接
*/
public static final boolean verifyMagnet(String url) {
return StringUtils.regex(url, MAGNET_BASIC, true);
}
/**
* 判断是否是32位磁力链接Hash
*
* @param url 磁力链接
*
* @return 是否是32位磁力链接Hash
*/
public static final boolean verifyMagnetHash32(String url) {
return StringUtils.regex(url, MAGNET_HASH_32, true);
}
/**
* 判断是否是40位磁力链接Hash
*
* @param url 磁力链接
*
* @return 是否是40位磁力链接Hash
*/
public static final boolean verifyMagnetHash40(String url) {
return StringUtils.regex(url, MAGNET_HASH_40, true);
}
}
/**
* 协议类型
*/
protected final Type type;
/**
* 协议名称
*/
protected final String name;
/**
* 下载链接
*/
protected String url;
/**
* 下载任务
*/
protected TaskEntity taskEntity;
/**
* @param type 协议类型
* @param name 协议名称
*/
protected Protocol(Type type, String name) {
this.type = type;
this.name = name;
}
/**
* 获取协议类型
*
* @return 协议类型
*/
public final Type type() {
return this.type;
}
/**
* 获取协议名称
*
* @return 协议名称
*/
public final String name() {
return this.name;
}
/**
* 判断协议是否支持下载链接
*
* @param url 下载链接
*
* @return 是否支持下载链接
*/
public boolean verify(String url) {
if(this.type == null) {
return false;
}
return this.type.verify(url);
}
/**
* 判断是否可用
*
* @return 是否可用
*/
public abstract boolean available();
/**
* 新建下载器
*
* @param taskSession 下载任务
*
* @return 下载器
*/
public abstract IDownloader buildDownloader(ITaskSession taskSession);
/**
* 新建下载任务
*
* @param url 下载链接
*
* @return 任务信息
*
* @throws DownloadException 下载异常
*/
public synchronized ITaskSession buildTaskSession(String url) throws DownloadException {
this.url = url.trim();
boolean success = true;
try {
this.buildTaskEntity();
return TaskSession.newInstance(this.taskEntity);
} catch (DownloadException e) {
success = false;
throw e;
} catch (Exception e) {
success = false;
throw new DownloadException("下载失败", e);
} finally {
if(success) {
this.success();
}
this.release(success);
}
}
/**
* 新建下载任务
*
* @throws DownloadException 下载异常
*/
protected void buildTaskEntity() throws DownloadException {
this.taskEntity = new TaskEntity();
this.prep();
this.buildUrl();
this.buildType();
this.buildStatus();
final String fileName = this.buildFileName();
this.buildName(fileName);
this.buildFile(fileName);
this.buildFileType(fileName);
this.buildSize();
this.done();
this.persistentTaskEntity();
}
/**
* 预处理
*
* @throws DownloadException 下载异常
*/
protected void prep() throws DownloadException {
}
/**
* 设置URL
*
* @throws DownloadException 下载异常
*/
protected void buildUrl() throws DownloadException {
this.taskEntity.setUrl(this.url);
}
/**
* 设置下载类型
*
* @throws DownloadException 下载异常
*/
protected void buildType() throws DownloadException {
this.taskEntity.setType(this.type);
}
/**
* 设置任务状态
*
* @throws DownloadException 下载异常
*/
protected void buildStatus() throws DownloadException {
this.taskEntity.setStatus(Status.AWAIT);
}
/**
* 获取文件名称
*
* @return 文件名称
*
* @throws DownloadException 下载异常
*/
protected String buildFileName() throws DownloadException {
return FileUtils.fileName(this.url);
}
/**
* 设置任务名称
*
* @param fileName 文件名称
*
* @throws DownloadException 下载异常
*/
protected void buildName(String fileName) throws DownloadException {
String taskName = fileName;
// 去掉后缀
final int index = fileName.lastIndexOf(SymbolConfig.Symbol.DOT.toChar());
if(index != -1) {
taskName = fileName.substring(0, index);
}
this.taskEntity.setName(taskName);
}
/**
* 设置下载文件、目录
*
* @param fileName 文件名称
*
* @throws DownloadException 下载异常
*/
protected void buildFile(String fileName) throws DownloadException {
final String filePath = DownloadConfig.getPath(fileName);
final File file = new File(filePath);
if(file.exists()) {
throw new DownloadException("下载文件已经存在:" + file);
}
this.taskEntity.setFile(filePath);
}
/**
* 设置任务文件类型
*
* @param fileName 文件名称
*
* @throws DownloadException 下载异常
*/
protected void buildFileType(String fileName) throws DownloadException {
this.taskEntity.setFileType(FileUtils.fileType(fileName));
}
/**
* 设置任务大小
*
* @throws DownloadException 下载异常
*/
protected void buildSize() throws DownloadException {
}
/**
* 完成处理
*
* @throws DownloadException 下载异常
*/
protected void done() throws DownloadException {
}
/**
* 持久化任务
*
* @throws DownloadException 下载异常
*/
protected void persistentTaskEntity() throws DownloadException {
EntityContext.getInstance().save(this.taskEntity);
}
/**
* 成功处理
*/
protected void success() {
}
/**
* 释放资源
*
* @param success 是否成功
*/
protected void release(boolean success) {
this.url = null;
this.taskEntity = null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy