/*******************************************************************************
 * Copyright (c) 2008 IGA Tosiki, NTT DATA BUSINESS BRAINS Corp.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IGA Tosiki (NTT DATA BUSINESS BRAINS Corp.) - initial API and implementation
 *******************************************************************************/
/*
 * blanco Framework
 * Copyright (C) 2008 NTT DATA BUSINESS BRAINS CORPORATION
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.nlpack.generator;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import blanco.commons.util.BlancoStreamUtil;
import blanco.nlpack.generator.message.BlancoNLpackGeneratorMessage;
import blanco.nlpack.generator.task.valueobject.BlancoNLpackGeneratorPluginDirectory2JarProcessInput;

/**
 * プラグインディレクトリを入力して、プラグインjarを出力します。
 * 
 * @author IGA Tosiki
 */
public class BlancoNLpackGeneratorPluginDirectory2Jar {
    /**
     * メッセージオブジェクト。
     */
    private final BlancoNLpackGeneratorMessage fMsg = new BlancoNLpackGeneratorMessage();

    private BlancoNLpackGeneratorPluginDirectory2JarProcessInput fInput = null;

    /**
     * プラグインディレクトリを プラグインjarに変換します。
     * 
     * @param argInput
     *            処理への入力パラメータ。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void process(
            final BlancoNLpackGeneratorPluginDirectory2JarProcessInput argInput)
            throws IOException {
        fInput = argInput;

        System.out
                .println("babel: plugin dir->jar begin: ["
                        + fInput.getSourcedir() + "]->["
                        + fInput.getTargetdir() + "].");

        final File sourceDir = new File(fInput.getSourcedir());

        if (sourceDir.exists() == false) {
            throw new IllegalArgumentException(fMsg.getMbebmj01(sourceDir
                    .getAbsolutePath()));
        }
        if (new File(fInput.getSourcedir()).isDirectory() == false) {
            throw new IllegalArgumentException(fMsg.getMbebmj02(sourceDir
                    .getAbsolutePath()));
        }

        // 出力先ディレクトリを作成。
        new File(fInput.getTargetdir()).mkdirs();

        final File[] dirs = sourceDir.listFiles();
        if (dirs != null) {
            for (int index = 0; index < dirs.length; index++) {
                if (dirs[index].isDirectory()) {
                    // ディレクトリだけを処理します。
                    processPluginDir(dirs[index]);
                }
            }
        }

        System.out.println("babel: plugin dir->jar end.");
    }

    private void processPluginDir(final File dirPlugin) throws IOException {
        final ZipOutputStream outStream = new ZipOutputStream(
                new BufferedOutputStream(new FileOutputStream(new File(fInput
                        .getTargetdir()
                        + "/" + dirPlugin.getName() + ".jar"))));
        try {
            processEvery(dirPlugin, "", outStream);

            outStream.flush();
        } finally {
            outStream.close();
        }
    }

    private void processEvery(final File dirTarget, final String subDir,
            final ZipOutputStream outStream) throws IOException {

        final File[] files = dirTarget.listFiles();
        if (files != null) {
            for (int index = 0; index < files.length; index++) {
                if (files[index].isDirectory()) {
                    String nextDir = subDir;
                    if (nextDir.length() > 0) {
                        nextDir += "/";
                    }
                    nextDir += files[index].getName();
                    processEvery(files[index], nextDir, outStream);
                } else {
                    String fileName = files[index].getName();
                    if (subDir.length() > 0) {
                        fileName = subDir + "/" + fileName;
                    }

                    final ZipEntry entry = new ZipEntry(fileName);
                    outStream.putNextEntry(entry);

                    final InputStream inStream = new BufferedInputStream(
                            new FileInputStream(files[index]));

                    BlancoStreamUtil.copy(inStream, outStream);

                    inStream.close();

                    outStream.closeEntry();
                }
            }
        }
    }
}
