cn.clxy.codes.upload.UploadFileService.java Source code

Java tutorial

Introduction

Here is the source code for cn.clxy.codes.upload.UploadFileService.java

Source

/**
 * Copyright (C) 2013 CLXY Studio.
 * This content is released under the (Link Goes Here) MIT License.
 * http://en.wikipedia.org/wiki/MIT_License
 */
package cn.clxy.codes.upload;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class UploadFileService {

    private File file;
    private Uploader uploader = new ApacheHCUploader();
    private ExecutorService executor = Executors.newFixedThreadPool(Config.MAX_UPLOAD);

    private static final Log log = LogFactory.getLog(UploadFileService.class);

    public UploadFileService(String fileName) {
        file = new File(fileName);
        if (!file.exists() || !file.isFile()) {
            throw new RuntimeException("File:" + file + " isn't correct!");
        }
    }

    public void upload() {
        try {
            doUpload(null);
        } finally {
            stop();
        }
    }

    public void retry(Integer... indexes) {

        // sort first.
        List<Integer> list = Arrays.asList(indexes);
        Collections.sort(list);

        try {
            doUpload(list);
        } finally {
            stop();
        }
    }

    public void stop() {
        if (executor != null) {
            executor.shutdown();
        }
    }

    private void doUpload(final List<Integer> indexes) {

        log.debug("Start! ===--------------------");

        BlockingQueue<Part> parts = new ArrayBlockingQueue<Part>(Config.MAX_READ);
        CompletionService<String> cs = new ExecutorCompletionService<String>(executor);

        log.debug("Reading started.");
        cs.submit(new ReadTask(file, indexes, parts));

        log.debug("Uploading started.");

        for (int i = 0; i < Config.MAX_UPLOAD; i++) {
            cs.submit(new UploadTask("upload." + i, uploader, parts));
        }

        // Wait all done. total count = maxUpload + 1.
        for (int i = 0; i <= Config.MAX_UPLOAD; i++) {
            Future<String> future = null;
            try {
                future = cs.take();
                checkFuture(future);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        // Notify sever all done.
        Future<String> result = executor.submit(new NotifyTask(file, uploader));
        checkFuture(result);

        log.debug("End! ===--------------------");
    }

    private static String checkFuture(Future<String> future) {

        try {
            String result = future.get();
            log.debug(result + " is done.");
            return result;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } catch (ExecutionException e) {
            throw new RuntimeException(e.getCause());
        }
    }

    public static class Part {

        private byte[] content;
        private String fileName;
        public static final Part NULL = new Part();

        public Part() {
            this(null, null);
        }

        public Part(String fileName, byte[] content) {
            this.content = content;
            this.fileName = fileName;
        }

        public byte[] getContent() {
            return content;
        }

        public String getFileName() {
            return fileName;
        }
    }
}