import java.util.concurrent.CountDownLatch
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
/**
26/07/2017
*/
abstract class ADownloader {
static class Type {
/**
* 文件类型,需要文件的绝对地址
*/
public static int FILE = 1
/**
* smb 共享文件
*/
public static int SMB = 2
/**
* http 网络资源
*/
public static int HTTP = 3
}
/**
* 源地址
*/
final String source
/**
* 目标地址
*/
final String target
/**
* CPU 数量
*/
private final int CPU_COUNT = Runtime.getRuntime().availableProcessors()
/**
* 下载任务的执行器;I/O 操作,暂定线程数量为 cpu 数量的 2 倍
*/
protected ExecutorService mExecutor = Executors.newFixedThreadPool(CPU_COUNT * 2)
protected CountDownLatch endGate
ADownloader(String source, String target) {
this.source = source
this.target = target
}
/**
* 执行下载方法
* @param closure 下载完成之后要执行的代码
*/
abstract void download(Closure closure)
}
import com.sun.istack.internal.Nullable
import java.util.regex.Pattern
/**
26/07/2017
*/
abstract class AFileDownloader<T> extends ADownloader{
private static final int NONE_PATTERN = 0
private static final int ONLY_EXPECTED_PATTERN = 3
private static final int ONLY_EXCLUDE_PATTERN = 5
private static final int BOTH_PATTERN = 8
/**
* 期望下载的文件类型,比如只下载 pdf 和 mp3 类型的文件,而不下载其他的
*/
private List<String> expectedTypes
/**
* 要排除的文件类型;比如不想下载 txt 类型的文件
*/
private List<String> excludeTypes
private Pattern expectedPattern
private Pattern excludePattern
private int patternCount = 0
AFileDownloader(String source, String target) {
super(source, target)
}
private void preparePattern() {
final String expectedRegulex = genExpectedRegulex()
if (expectedRegulex != null && expectedRegulex.size() != 0) {
expectedPattern = Pattern.compile(expectedRegulex)
patternCount += ONLY_EXPECTED_PATTERN
}
final String excludeRegulex = genExcludeRegulex()
if (excludeRegulex != null && excludeRegulex.size() != 0) {
excludePattern = Pattern.compile(excludeRegulex)
patternCount += ONLY_EXCLUDE_PATTERN
}
}
/**
* 添加期望下载的文件类型
*/
void addExpectedType(String expectedType) {
if (expectedTypes == null) {
expectedTypes = new ArrayList<>()
}
if (getExcludeTypes().contains(expectedType)) {
throw new IllegalArgumentException(String.format("此文件类型(%s)已经被设置为排除,无法再设置为期望下载类型", expectedType))
}
if (!expectedTypes.contains(expectedType)) {
expectedTypes.add(expectedType)
}
}
/**
* 添加期望排除的文件类型
*/
void addExcludeType(String excludeType) {
if (excludeTypes == null) {
excludeTypes = new ArrayList<>()
}
if (getExpectedTypes().contains(excludeType)) {
throw new IllegalArgumentException(String.format("此文件类型(%s)已经被设置为期望下载的类型,无法再设置为排除类型了", excludeType))
}
if (!excludeTypes.contains(excludeType)) {
excludeTypes.add(excludeType)
}
}
List<String> getExpectedTypes() {
if (expectedTypes != null) {
return expectedTypes
} else {
Collections.emptyList()
}
}
List<String> getExcludeTypes() {
if (excludeTypes != null) {
return excludeTypes
} else {
Collections.emptyList()
}
}
String genExpectedRegulex() {
if (expectedTypes != null && expectedTypes.size() > 0) {
StringBuilder resultRegulex = new StringBuilder()
for (int i = 0; i < expectedTypes.size(); i++) {
if (i > 0) {
resultRegulex.append("|")
}
resultRegulex.append(expectedTypes.get(i))
}
return String.format("^.*?(%s)\$", resultRegulex.toString())
} else {
return null
}
}
/**
* 此为包含的,需要取反
* @return
*/
String genExcludeRegulex() {
if (excludeTypes != null && excludeTypes.size() > 0) {
StringBuilder resultRegulex = new StringBuilder()
for (int i = 0; i < excludeTypes.size(); i++) {
if (i > 0) {
resultRegulex.append("|")
}
resultRegulex.append(excludeTypes.get(i))
}
return String.format("^.*?(%s)\$", resultRegulex.toString())
} else {
return null
}
}
@Override
void download(@Nullable Closure closure) {
preDownload()
downloadInner(closure)
}
abstract void downloadInner(Closure closure)
void preDownload(){
preparePattern()
}
/**
* 是否应该将其加入到待下载的条目当中
* @param path 待校验的路径
*/
protected boolean shouldAddItem(String path) {
boolean shouldAdd = false
switch (patternCount) {
case NONE_PATTERN:
println("NONE_PATTERN ------")
shouldAdd = true
break
case ONLY_EXPECTED_PATTERN:
println("ONLY_EXPECTED_PATTERN ------")
if (expectedPattern.matcher(path)) {
shouldAdd = true
}
break
case ONLY_EXCLUDE_PATTERN:
println("ONLY_EXCLUDE_PATTERN ------")
if (!excludePattern.matcher(path)) {
shouldAdd = true
}
break
case BOTH_PATTERN:
println("BOTH_PATTERN ------")
if (expectedPattern.matcher(path) && !excludePattern.matcher(path)) {
shouldAdd = true
}
break
}
return shouldAdd
}
/**
* 遍历文件夹找出要下载的文件路径
* @param rootDir
*/
abstract void traverseDir(T rootDir)
abstract String generateTargetPath(T t)
}
import bean.User
import jcifs.smb.NtlmPasswordAuthentication
import jcifs.smb.SmbFile
import jcifs.smb.SmbFileInputStream
import org.gradle.api.GradleException
import utils.TextUtil
import java.util.concurrent.CountDownLatch
/**
26/07/2017
*/
class SMBDownloader extends AFileDownloader<SmbFile> {
private static final Object SYNC_OBJ = new Object()
private NtlmPasswordAuthentication author
private Map<SmbFile, String> filesNeedDownload
private Closure pathGenerateCls
SMBDownloader(String source, String target, User user) {
super(source, target)
println("user>>>${user}")
author = new NtlmPasswordAuthentication("${user.domain}", "${user.uName}", "${user.uPwd}")
}
void setPathGenerateCls(Closure pathGenerateCls) {
this.pathGenerateCls = pathGenerateCls
}
@Override
void downloadInner(Closure closure) {
final def smbFileRoot = new SmbFile(source, author)
traverseDir(smbFileRoot)
downloadWithExecutors(closure)
}
private void downloadWithExecutors(Closure closureAfterDownload) {
final int filesSize = filesNeedDownload == null ? 0 : filesNeedDownload.size()
if (filesSize > 0) {
endGate = new CountDownLatch(filesSize)
long timeBegin = System.currentTimeMillis()
def downloadFailureFiles = new ArrayList()
filesNeedDownload.each { Map.Entry<SmbFile, String> entry ->
mExecutor.execute(new Runnable() {
@Override
void run() {
try {
downloadSmbFile(entry.key, entry.value)
} catch (Exception e) {
downloadFailureFiles.add(entry.key.path)
e.printStackTrace()
println("下载此文件${entry.key.path}时抛出异常了")
} finally {
endGate.countDown()
}
}
})
}
endGate.await()
if (downloadFailureFiles.size() > 0) {
throw new GradleException(String.format("有文件下载失败了:${downloadFailureFiles}"))
}
println("******************* ^_^ 所有的文件都下载完成了 ^_^ *******************")
println("\t耗时:${System.currentTimeMillis() - timeBegin} ms")
if (closureAfterDownload != null) {
closureAfterDownload.call()
}
} else {
println("没有需要下载的文件")
}
}
static downloadSmbFile(final SmbFile smbFile, final String targetPath) {
if (smbFile.exists()) {
final SmbFileInputStream inputStream = new SmbFileInputStream(smbFile)
final byte[] buffer = new byte[1024]
int length
synchronized (SYNC_OBJ) {
println(">>>>>>>>开始下载\r\n\t源件地址:${smbFile.path},\r\n\t目标地址为:${targetPath}")
}
final def targetFile = new File(targetPath)
if (!targetFile.exists()) {
targetFile.parentFile.mkdirs()
}
final FileOutputStream output = new FileOutputStream(targetFile)
while ((length = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, length)
}
output.close()
println("\t下载结束对应下载地址:${smbFile.path}")
} else {
println("---此文件不存在:${smbFile.path}")
}
}
@Override
String generateTargetPath(SmbFile smbFile) {
def targetPath
if (pathGenerateCls != null) {
targetPath = pathGenerateCls.call(smbFile.path, target)
} else {
throw new IllegalArgumentException("尚未制定文件名命名规则")
}
return TextUtil.fixSlashes(targetPath.toString())
}
@Override
void traverseDir(SmbFile smbFileRoot) {
if (smbFileRoot.exists()) {
if (smbFileRoot.isDirectory()) {
smbFileRoot.listFiles().each { SmbFile smbFileInner ->
if (smbFileInner.isDirectory()) {
println("现在想遍历文件夹${smbFileInner.path}")
traverseDir(smbFileInner)
} else {
addDownloadItem(smbFileInner)
}
}
} else {
addDownloadItem(smbFileRoot)
}
} else {
println("此文件不存在:${smbFileRoot.getPath()}")
}
}
void addDownloadItem(SmbFile sourceFile) {
final String path = sourceFile.path
boolean shouldAdd = shouldAddItem(path)
if (shouldAdd) {
if (filesNeedDownload == null) {
filesNeedDownload = new HashMap<>()
}
filesNeedDownload.put(sourceFile, generateTargetPath(sourceFile))
} else {
println("\t此文件:${path}不符合下载条件")
}
}
}