gradle 下载 SMB 文件(实际使用的是 groovy 语法)


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))
            }
            //idea 如: ^.*?(com|bat|txt)$
            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))
            }
            //idea ^.*?(com|bat|txt)$
            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
//                    println("ONLY_EXCLUDE_PATTERN ------path: ${path}, ${expectedPattern.toString()}")
                }
                break
            case ONLY_EXCLUDE_PATTERN:
                println("ONLY_EXCLUDE_PATTERN ------")
                if (!excludePattern.matcher(path)) {
                    shouldAdd = true
//                    println("ONLY_EXCLUDE_PATTERN ------path: ${path}, ${excludePattern.toString()}")
                }
                break
            case BOTH_PATTERN:
                println("BOTH_PATTERN ------")
                if (expectedPattern.matcher(path) && !excludePattern.matcher(path)) {
                    shouldAdd = true
//                    println("ONLY_EXCLUDE_PATTERN ------path: ${path}, expectedPattern:${expectedPattern.toString()}, excludePattern:${excludePattern.toString()}}")
                }
                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) {
        //step 1、将现有的匹配格式生成"正则表达式"

        //step 2、找出对应的起始文件或目录
        final def smbFileRoot = new SmbFile(source, author)

        //step 3、遍历文件夹(如果是的话)列出所有需要下载的文件,并指定下载目标路径
        traverseDir(smbFileRoot)

        //step 4、使用线程池下载文件
        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()
                        }
                    }
                })
            }

            //step 5、等待所有下载任务完成,然后执行预置的 closure (如果有的话)
            endGate.await()
            if (downloadFailureFiles.size() > 0) {
                //idea 有下载失败的文件,那么应该直接抛出异常,现在的要求应该是所有文件都要下载下来
                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()
//            throw new IllegalArgumentException("报错了")
            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 {
//            targetPath = "${target}/${smbFile.getURL().path}"
            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}不符合下载条件")
        }
    }
}

猜你喜欢

转载自blog.csdn.net/lonewolf521125/article/details/79543639