com.luna.showcase.excel.service.ExcelDataService.java Source code

Java tutorial

Introduction

Here is the source code for com.luna.showcase.excel.service.ExcelDataService.java

Source

/**
 * Copyright (c) 2005-2012 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.luna.showcase.excel.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.luna.common.entity.search.SearchOperator;
import com.luna.common.entity.search.Searchable;
import com.luna.common.repository.RepositoryHelper;
import com.luna.common.service.BaseService;
import com.luna.common.utils.FileCharset;
import com.luna.maintain.editor.web.controller.utils.CompressUtils;
import com.luna.maintain.notification.service.NotificationApi;
import com.luna.showcase.excel.entity.ExcelData;
import com.luna.showcase.excel.repository.ExcelDataRepository;
import com.luna.sys.user.entity.User;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import java.io.*;
import java.util.*;

/**
 * 
 * <p>Date: 13-2-4 ?3:01
 * <p>Version: 1.0
 */
@Service
public class ExcelDataService extends BaseService<ExcelData, Long> {

    private final Logger log = LoggerFactory.getLogger(ExcelDataService.class);

    private int batchSize = 1000; //??
    private int pageSize = 1000;//??

    /**
     * ? ?
     */
    private final int MAX_EXPORT_FILE_SIZE = 10 * 1024 * 1024; //10MB

    private ExcelDataRepository getExcelDataRepository() {
        return (ExcelDataRepository) baseRepository;
    }

    @Autowired
    private NotificationApi notificationApi;

    private final String storePath = "upload/excel";
    private final String EXPORT_FILENAME_PREFIX = "excel";

    public void setNotificationApi(final NotificationApi notificationApi) {
        this.notificationApi = notificationApi;
    }

    @Async
    public void initOneMillionData(final User user) {

        ExcelDataService proxy = (ExcelDataService) AopContext.currentProxy();

        long beginTime = System.currentTimeMillis();

        getExcelDataRepository().truncate();

        final int ONE_MILLION = 1000000; //100w
        for (int i = batchSize; i <= ONE_MILLION; i += batchSize) {
            //?AopContext.currentProxy() task:annotation-drivenproxy
            proxy.doBatchSave(i - batchSize);
        }

        long endTime = System.currentTimeMillis();

        Map<String, Object> context = Maps.newHashMap();
        context.put("seconds", (endTime - beginTime) / 1000);
        notificationApi.notify(user.getId(), "excelInitDataSuccess", context);

    }

    public void doBatchSave(final int fromId) {
        for (int i = 1; i <= batchSize; i++) {
            Long id = Long.valueOf(fromId + i);
            String content = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
            getExcelDataRepository().save(id, content);
        }
    }

    /**
     * ? ?
     * @param dataList
     * @throws Exception 
     */
    public void doBatchSave(final List<ExcelData> dataList) throws Exception {
        for (ExcelData data : dataList) {
            ExcelData dbData = findOne(data.getId());
            if (dbData == null) {
                getExcelDataRepository().save(data.getId(), data.getContent());
            } else {
                dbData.setContent(data.getContent());
                update(dbData);
            }
        }
    }

    /**
     * csv?
     * @param user
     * @param is
     */
    @Async
    public void importCvs(final User user, final InputStream is) {

        ExcelDataService proxy = ((ExcelDataService) AopContext.currentProxy());
        BufferedInputStream bis = null;
        try {
            long beginTime = System.currentTimeMillis();

            bis = new BufferedInputStream(is);
            String encoding = FileCharset.getCharset(bis);

            LineIterator iterator = IOUtils.lineIterator(bis, encoding);

            String separator = ",";
            int totalSize = 0; //?

            final List<ExcelData> dataList = Lists.newArrayList();

            if (iterator.hasNext()) {
                iterator.nextLine();//
            }

            while (iterator.hasNext()) {

                totalSize++;

                String line = iterator.nextLine();
                String[] dataArray = StringUtils.split(line, separator);

                ExcelData data = new ExcelData();
                data.setId(Long.valueOf(dataArray[0]));
                data.setContent(dataArray[1]);
                dataList.add(data);

                if (totalSize % batchSize == 0) {
                    try {
                        proxy.doBatchSave(dataList);
                    } catch (Exception e) {
                        Long fromId = dataList.get(0).getId();
                        Long endId = dataList.get(dataList.size() - 1).getId();
                        log.error("from " + fromId + " to " + endId + ", error", e);
                    }
                    dataList.clear();
                }
            }

            if (dataList.size() > 0) {
                proxy.doBatchSave(dataList);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            notificationApi.notify(user.getId(), "excelImportSuccess", context);
        } catch (Exception e) {
            log.error("excel import error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelImportError", context);
        } finally {
            IOUtils.closeQuietly(bis);
        }
    }

    /**
     *  excel 2003 biff?
     * xml? ?SAX
     * @param user
     * @param is
     */
    @Async
    public void importExcel2003(final User user, final InputStream is) {

        ExcelDataService proxy = ((ExcelDataService) AopContext.currentProxy());

        BufferedInputStream bis = null;
        InputStream dis = null;
        try {
            long beginTime = System.currentTimeMillis();

            List<ExcelData> dataList = Lists.newArrayList();

            //?
            bis = new BufferedInputStream(is);
            //  org.apache.poi.poifs.filesystem.Filesystem
            POIFSFileSystem poifs = new POIFSFileSystem(bis);
            // ?  Workbook(excel )?
            dis = poifs.createDocumentInputStream("Workbook");
            //  HSSFRequest
            HSSFRequest req = new HSSFRequest();

            // ?
            req.addListenerForAllRecords(new Excel2003ImportListener(proxy, dataList, batchSize));
            //  
            HSSFEventFactory factory = new HSSFEventFactory();
            // ???
            factory.processEvents(req, dis);

            //??batchSize?
            if (dataList.size() > 0) {
                proxy.doBatchSave(dataList);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            notificationApi.notify(user.getId(), "excelImportSuccess", context);
        } catch (Exception e) {
            log.error("excel import error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelImportError", context);
        } finally {
            // ?
            IOUtils.closeQuietly(bis);
            // ?
            IOUtils.closeQuietly(dis);
        }
    }

    @Async
    public void importExcel2007(final User user, final InputStream is) {

        ExcelDataService proxy = ((ExcelDataService) AopContext.currentProxy());

        BufferedInputStream bis = null;
        try {
            long beginTime = System.currentTimeMillis();

            List<ExcelData> dataList = Lists.newArrayList();

            bis = new BufferedInputStream(is);
            OPCPackage pkg = OPCPackage.open(bis);
            XSSFReader r = new XSSFReader(pkg);

            XMLReader parser = XMLReaderFactory.createXMLReader();
            ContentHandler handler = new Excel2007ImportSheetHandler(proxy, dataList, batchSize);
            parser.setContentHandler(handler);

            Iterator<InputStream> sheets = r.getSheetsData();
            while (sheets.hasNext()) {
                InputStream sheet = null;
                try {
                    sheet = sheets.next();
                    InputSource sheetSource = new InputSource(sheet);
                    parser.parse(sheetSource);
                } catch (Exception e) {
                    throw e;
                } finally {
                    IOUtils.closeQuietly(sheet);
                }
            }

            //??batchSize?
            if (dataList.size() > 0) {
                proxy.doBatchSave(dataList);
            }

            long endTime = System.currentTimeMillis();
            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            notificationApi.notify(user.getId(), "excelImportSuccess", context);
        } catch (Exception e) {
            log.error("excel import error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelImportError", context);
        } finally {
            IOUtils.closeQuietly(bis);
        }
    }

    @Async
    public void exportCvs(final User user, final String contextRootPath, final Searchable searchable) {
        String encoding = "gbk";
        int perSheetRows = 60000; //?sheet 6w?
        int totalRows = 0;
        String separator = ",";
        Long maxId = 0L;

        String fileName = generateFilename(user, contextRootPath, "csv");
        File file = new File(fileName);
        BufferedOutputStream out = null;
        try {
            long beginTime = System.currentTimeMillis();

            out = new BufferedOutputStream(new FileOutputStream(file));
            out.write("?,\n".getBytes(encoding));

            while (true) {
                totalRows = 0;
                Page<ExcelData> page = null;
                do {
                    searchable.setPage(0, pageSize);
                    //
                    if (!searchable.containsSearchKey("id_in")) {
                        searchable.addSearchFilter("id", SearchOperator.gt, maxId);
                    }
                    page = findAll(searchable);
                    for (ExcelData data : page.getContent()) {
                        out.write(String.valueOf(data.getId()).getBytes(encoding));
                        out.write(separator.getBytes(encoding));
                        out.write((data.getContent()).replace(separator, ";").getBytes(encoding));
                        out.write("\n".getBytes(encoding));
                        maxId = Math.max(maxId, data.getId());
                        totalRows++;
                    }
                    //clear entity manager
                    RepositoryHelper.clear();
                } while (page.hasNextPage() && totalRows <= perSheetRows);

                if (!page.hasNextPage()) {
                    break;
                }
            }

            IOUtils.closeQuietly(out);

            if (needCompress(file)) {
                fileName = compressAndDeleteOriginal(fileName);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            notificationApi.notify(user.getId(), "excelExportSuccess", context);
        } catch (Exception e) {
            IOUtils.closeQuietly(out);
            log.error("excel export error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelExportError", context);
        }
    }

    /**
     * workbook
     * 1?vbs ?
     * 2?c#??
     * ? ????office 2007 ?
     * @param user
     * @param contextRootPath
     * @param searchable
     */
    @Async
    public void exportExcel2003WithOneSheetPerWorkBook(final User user, final String contextRootPath,
            final Searchable searchable) {
        int workbookCount = 0;
        List<String> workbookFileNames = new ArrayList<String>();
        int perSheetRows = 60000; //?sheet 6w?
        int totalRows = 0;
        String extension = "xls";

        int pageSize = 1000;
        Long maxId = 0L;

        BufferedOutputStream out = null;
        try {
            long beginTime = System.currentTimeMillis();

            while (true) {
                workbookCount++;
                String fileName = generateFilename(user, contextRootPath, workbookCount, extension);
                workbookFileNames.add(fileName);
                File file = new File(fileName);

                HSSFWorkbook wb = new HSSFWorkbook();
                Sheet sheet = wb.createSheet();
                Row headerRow = sheet.createRow(0);
                Cell idHeaderCell = headerRow.createCell(0);
                idHeaderCell.setCellValue("?");
                Cell contentHeaderCell = headerRow.createCell(1);
                contentHeaderCell.setCellValue("");

                totalRows = 1;

                Page<ExcelData> page = null;

                do {
                    searchable.setPage(0, pageSize);
                    //
                    if (!searchable.containsSearchKey("id_in")) {
                        searchable.addSearchFilter("id", SearchOperator.gt, maxId);
                    }
                    page = findAll(searchable);

                    for (ExcelData data : page.getContent()) {
                        Row row = sheet.createRow(totalRows);
                        Cell idCell = row.createCell(0);
                        idCell.setCellValue(data.getId());
                        Cell contentCell = row.createCell(1);
                        contentCell.setCellValue(data.getContent());
                        maxId = Math.max(maxId, data.getId());
                        totalRows++;
                    }
                    //clear entity manager
                    RepositoryHelper.clear();
                } while (page.hasNextPage() && totalRows <= perSheetRows);

                out = new BufferedOutputStream(new FileOutputStream(file));
                wb.write(out);

                IOUtils.closeQuietly(out);

                if (!page.hasNextPage()) {
                    break;
                }
            }

            String fileName = workbookFileNames.get(0);
            if (workbookCount > 1 || needCompress(new File(fileName))) {
                fileName = fileName.substring(0, fileName.lastIndexOf("_")) + ".zip";
                //
                compressAndDeleteOriginal(fileName, workbookFileNames.toArray(new String[0]));
            } else {
                String newFileName = fileName.substring(0, fileName.lastIndexOf("_")) + "." + extension;
                FileUtils.moveFile(new File(fileName), new File(newFileName));
                fileName = newFileName;
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            notificationApi.notify(user.getId(), "excelExportSuccess", context);
        } catch (Exception e) {
            e.printStackTrace();
            //
            IOUtils.closeQuietly(out);
            log.error("excel export error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelExportError", context);
        }
    }

    /**
     * excel 2003
     * 1????XML
     * 2??????excel???????
     * 3????testExportExcel2003_3
     * <p/>
     * ?
     * <p/>
     * ?html??sheet
     * @param user
     * @param contextRootPath
     * @param searchable
     */
    @Async
    public void exportExcel2003WithXml(final User user, final String contextRootPath, final Searchable searchable) {

        int perSheetRows = 60000; //?sheet 6w?
        int totalSheets = 0;
        int totalRows = 0;
        Long maxId = 0L;
        String templateEncoding = "utf-8";

        String fileName = generateFilename(user, contextRootPath, "xls");
        File file = new File(fileName);
        BufferedOutputStream out = null;
        try {
            long beginTime = System.currentTimeMillis();

            String workBookHeader = IOUtils
                    .toString(ExcelDataService.class.getResourceAsStream("excel_2003_xml_workbook_header.txt"));
            String workBookFooter = IOUtils
                    .toString(ExcelDataService.class.getResourceAsStream("excel_2003_xml_workbook_footer.txt"));
            String sheetHeader = IOUtils
                    .toString(ExcelDataService.class.getResourceAsStream("excel_2003_xml_sheet_header.txt"));
            String sheetFooter = IOUtils
                    .toString(ExcelDataService.class.getResourceAsStream("excel_2003_xml_sheet_footer.txt"));
            String rowTemplate = IOUtils
                    .toString(ExcelDataService.class.getResourceAsStream("excel_2003_xml_row.txt"));

            out = new BufferedOutputStream(new FileOutputStream(file));

            out.write(workBookHeader.getBytes(templateEncoding));

            while (true) {
                totalSheets++;

                out.write(sheetHeader.replace("{sheetName}", "Sheet" + totalSheets).getBytes(templateEncoding));

                Page<ExcelData> page = null;

                totalRows = 1;
                do {
                    searchable.setPage(0, pageSize);
                    //
                    if (!searchable.containsSearchKey("id_in")) {
                        searchable.addSearchFilter("id", SearchOperator.gt, maxId);
                    }
                    page = findAll(searchable);

                    for (ExcelData data : page.getContent()) {
                        out.write(rowTemplate.replace("{id}", String.valueOf(data.getId()))
                                .replace("{content}", data.getContent()).getBytes(templateEncoding));
                        maxId = Math.max(maxId, data.getId());
                        totalRows++;
                    }
                    //clear entity manager
                    RepositoryHelper.clear();
                } while (page.hasNextPage() && totalRows <= perSheetRows);

                out.write(sheetFooter.getBytes(templateEncoding));

                if (!page.hasNextPage()) {
                    break;
                }
            }

            out.write(workBookFooter.getBytes(templateEncoding));

            IOUtils.closeQuietly(out);

            if (needCompress(file)) {
                fileName = compressAndDeleteOriginal(fileName);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            notificationApi.notify(user.getId(), "excelExportSuccess", context);
        } catch (Exception e) {
            e.printStackTrace();
            IOUtils.closeQuietly(out);
            log.error("excel export error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelExportError", context);
        }
    }

    /**
     * excel 2003
     * ????
     * ?sheet65536(usermodel? ?flush ????)
     * @param user
     * @param contextRootPath
     * @param searchable
     */
    @Async
    public void exportExcel2003WithUsermodel(final User user, final String contextRootPath,
            final Searchable searchable) {
        int perSheetRows = 60000; //?sheet 6w?
        int totalRows = 0;
        Long maxId = 0L;

        String fileName = generateFilename(user, contextRootPath, "xls");
        File file = new File(fileName);
        BufferedOutputStream out = null;
        try {
            long beginTime = System.currentTimeMillis();

            HSSFWorkbook wb = new HSSFWorkbook();
            while (true) {
                Sheet sheet = wb.createSheet();
                Row headerRow = sheet.createRow(0);
                Cell idHeaderCell = headerRow.createCell(0);
                idHeaderCell.setCellValue("?");
                Cell contentHeaderCell = headerRow.createCell(1);
                contentHeaderCell.setCellValue("");

                totalRows = 1;
                Page<ExcelData> page = null;
                do {
                    searchable.setPage(0, pageSize);
                    //
                    if (!searchable.containsSearchKey("id_in")) {
                        searchable.addSearchFilter("id", SearchOperator.gt, maxId);
                    }
                    page = findAll(searchable);

                    for (ExcelData data : page.getContent()) {
                        Row row = sheet.createRow(totalRows);
                        Cell idCell = row.createCell(0);
                        idCell.setCellValue(data.getId());
                        Cell contentCell = row.createCell(1);
                        contentCell.setCellValue(data.getContent());
                        maxId = Math.max(maxId, data.getId());
                        totalRows++;
                    }
                    //clear entity manager
                    RepositoryHelper.clear();
                } while (page.hasNextPage() && totalRows <= perSheetRows);

                if (!page.hasNextPage()) {
                    break;
                }
            }

            out = new BufferedOutputStream(new FileOutputStream(file));
            wb.write(out);

            IOUtils.closeQuietly(out);

            if (needCompress(file)) {
                fileName = compressAndDeleteOriginal(fileName);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            notificationApi.notify(user.getId(), "excelExportSuccess", context);
        } catch (Exception e) {
            IOUtils.closeQuietly(out);
            log.error("excel export error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelExportError", context);
        }
    }

    /**
     * ???
     * excel 2007 ?sheet1048576
     * @param user
     * @param contextRootPath
     * @param searchable
     */
    @Async
    public void exportExcel2007(final User user, final String contextRootPath, final Searchable searchable) {

        int rowAccessWindowSize = 1000; //???
        int perSheetRows = 100000; //?sheet 10w?
        int totalRows = 0; //
        Long maxId = 0L;//??id 

        String fileName = generateFilename(user, contextRootPath, "xlsx");
        File file = new File(fileName);
        BufferedOutputStream out = null;
        SXSSFWorkbook wb = null;
        try {
            long beginTime = System.currentTimeMillis();

            wb = new SXSSFWorkbook(rowAccessWindowSize);
            wb.setCompressTempFiles(true);//?gzip

            while (true) {

                Sheet sheet = wb.createSheet();
                Row headerRow = sheet.createRow(0);
                Cell idHeaderCell = headerRow.createCell(0);
                idHeaderCell.setCellValue("?");
                Cell contentHeaderCell = headerRow.createCell(1);
                contentHeaderCell.setCellValue("");

                totalRows = 1;

                Page<ExcelData> page = null;

                do {
                    searchable.setPage(0, pageSize);
                    //
                    if (!searchable.containsSearchKey("id_in")) {
                        searchable.addSearchFilter("id", SearchOperator.gt, maxId);
                    }
                    page = findAll(searchable);

                    for (ExcelData data : page.getContent()) {
                        Row row = sheet.createRow(totalRows);
                        Cell idCell = row.createCell(0);
                        idCell.setCellValue(data.getId());
                        Cell contentCell = row.createCell(1);
                        contentCell.setCellValue(data.getContent());
                        maxId = Math.max(maxId, data.getId());
                        totalRows++;
                    }
                    //clear entity manager
                    RepositoryHelper.clear();
                } while (page.hasNextPage() && totalRows <= perSheetRows);

                if (!page.hasNextPage()) {
                    break;
                }
            }
            out = new BufferedOutputStream(new FileOutputStream(file));
            wb.write(out);

            IOUtils.closeQuietly(out);

            if (needCompress(file)) {
                fileName = compressAndDeleteOriginal(fileName);
            }

            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            notificationApi.notify(user.getId(), "excelExportSuccess", context);
        } catch (Exception e) {
            IOUtils.closeQuietly(out);
            log.error("excel export error", e);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
            notificationApi.notify(user.getId(), "excelExportError", context);
        } finally {
            // ?
            wb.dispose();
        }
    }

    private String compressAndDeleteOriginal(final String filename) {
        String newFileName = FilenameUtils.removeExtension(filename) + ".zip";
        compressAndDeleteOriginal(newFileName, filename);
        return newFileName;
    }

    private void compressAndDeleteOriginal(final String newFileName, final String... needCompressFilenames) {
        CompressUtils.zip(newFileName, needCompressFilenames);
        for (String needCompressFilename : needCompressFilenames) {
            FileUtils.deleteQuietly(new File(needCompressFilename));
        }
    }

    private boolean needCompress(final File file) {
        return file.length() > MAX_EXPORT_FILE_SIZE;
    }

    /**
     * ????
     * @param user
     * @param contextRootPath
     * @param extension
     * @return
     */
    private String generateFilename(final User user, final String contextRootPath, final String extension) {
        return generateFilename(user, contextRootPath, null, extension);
    }

    private String generateFilename(final User user, final String contextRootPath, Integer index,
            final String extension) {
        String path = FilenameUtils.concat(contextRootPath, storePath);
        path = FilenameUtils.concat(path, user.getUsername());
        path = FilenameUtils.concat(path,
                EXPORT_FILENAME_PREFIX + "_" + DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS")
                        + (index != null ? ("_" + index) : "") + "." + extension);

        File file = new File(path);
        if (!file.exists()) {
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            return path;
        }
        return generateFilename(user, contextRootPath, extension);
    }

}