com.polyvi.xface.extension.zip.XZipExt.java Source code

Java tutorial

Introduction

Here is the source code for com.polyvi.xface.extension.zip.XZipExt.java

Source

/*
 Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
 This program is distributed under the terms of the GNU General Public License.
    
 This file is part of xFace.
    
 xFace is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 xFace is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with xFace.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.polyvi.xface.extension.zip;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;

import com.polyvi.xface.util.XAssetsFileUtils;
import com.polyvi.xface.util.XConstant;
import com.polyvi.xface.util.XFileUtils;
import com.polyvi.xface.util.XLog;
import com.polyvi.xface.util.XPathResolver;
import com.polyvi.xface.view.XAppWebView;

import android.content.Context;
import android.net.Uri;

public class XZipExt extends CordovaPlugin {
    // ?
    private static final int FILE_NOT_EXIST = 1;
    // 
    private static final int COMPRESS_FILE_ERROR = 2;
    // 
    private static final int UNZIP_FILE_ERROR = 3;
    private static final int UNKNOWN_ERR = 5;

    private static final String CLASS_NAME = XZipExt.class.getSimpleName();
    private static final String COMMAND_ZIP = "zip";
    private static final String COMMAND_ZIP_FILES = "zipFiles";
    private static final String COMMAND_UNZIP = "unzip";
    private CordovaResourceApi mResourceApi;
    private Context mContext;

    private interface ZipOp {
        void run() throws Exception;
    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        mContext = cordova.getActivity();
        super.initialize(cordova, webView);
    }

    @Override
    public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext)
            throws JSONException {
        mResourceApi = webView.getResourceApi();
        if (COMMAND_ZIP.equals(action)) {
            threadHelper(new ZipOp() {

                @Override
                public void run() throws Exception {
                    zipDir(args.getString(0), args.getString(1));
                }
            }, callbackContext, action);
        } else if (COMMAND_ZIP_FILES.equals(action)) {
            threadHelper(new ZipOp() {

                @Override
                public void run() throws Exception {
                    zipFiles(args.getJSONArray(0), args.getString(1));
                }
            }, callbackContext, action);
        } else if (COMMAND_UNZIP.equals(action)) {
            threadHelper(new ZipOp() {

                @Override
                public void run() throws Exception {
                    unzip(args.getString(0), args.getString(1));
                }
            }, callbackContext, action);
        }
        return true;
    }

    /**
     * ?
     *
     * @param zipOp
     * @param callbackContext
     * @param action
     */
    private void threadHelper(final ZipOp zipOp, final CallbackContext callbackContext, final String action) {
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                try {
                    zipOp.run();
                    callbackContext.success();
                } catch (Exception e) {
                    XLog.e(CLASS_NAME, e.getMessage());
                    e.printStackTrace();
                    if (e instanceof IllegalArgumentException) {
                        callbackContext.error(FILE_NOT_EXIST);
                    } else if (e instanceof FileNotFoundException) {
                        callbackContext.error(FILE_NOT_EXIST);
                    } else if (e instanceof IOException) {
                        if (COMMAND_UNZIP.equals(action)) {
                            callbackContext.error(UNZIP_FILE_ERROR);
                        } else {
                            callbackContext.error(COMPRESS_FILE_ERROR);
                        }
                    } else {
                        callbackContext.error(UNKNOWN_ERR);
                    }
                }
            }
        });
    }

    /**
     * ???
     *
     * @return ?
     */
    private String getWorkspacePath() {
        XAppWebView xAppWebView = (XAppWebView) this.webView;
        return xAppWebView.getOwnerApp().getWorkSpace();
    }

    /**
     * Uri???
     *
     * @param fileAbsPath
     * @return true: ??false: 
     */
    private boolean isFileUriValid(Uri fileUri) {
        return XFileUtils.isFilePathValid(fileUri.getPath());
    }

    /**
     * 2???
     *
     * @param srcFileUri
     *            uri
     * @param targetUri
     *            uri
     * @return true: ?false: ??
     */
    private boolean areFilesSame(Uri srcFileUri, Uri targetUri) {
        return srcFileUri.equals(targetUri);
    }

    /**
     * ?uri
     *
     * @param filePath
     *            URL?
     * @return ?
     */
    private Uri getFileUri(String filePath) throws IllegalArgumentException {
        Uri fileUri = new XPathResolver(filePath, getWorkspacePath()).getUri(this.webView.getResourceApi());
        if (!isFileUriValid(fileUri)) {
            throw new IllegalArgumentException();
        }
        return fileUri;
    }

    /**
     * ?
     *
     * @param srcFileURL
     *            URL
     * @param zipFileURL
     *            ?zip??URL
     * @throws FileNotFoundException
     * @throws IOException
     * @throws IllegalArgumentException
     */
    private void zipDir(String srcFileURL, String zipFileURL)
            throws FileNotFoundException, IOException, IllegalArgumentException {
        Uri srcFileUri = getFileUri(srcFileURL);
        Uri dstFileUri = getFileUri(zipFileURL);

        if (areFilesSame(srcFileUri, dstFileUri)) {
            throw new IllegalArgumentException();
        }
        prepareForZipDir(dstFileUri);

        ZipOutputStream zos = new ZipOutputStream(mResourceApi.openOutputStream(dstFileUri));
        compressDir(srcFileUri, zos, "");
        zos.close();
    }

    /**
     * ?zip?
     *
     * @param dstFileUri
     */
    private void prepareForZipDir(Uri dstFileUri) {
        File zipFile = new File(dstFileUri.getPath());
        if (zipFile.exists()) {
            zipFile.delete();
        }
        File zipFileParent = zipFile.getParentFile();
        if (!zipFileParent.exists()) {
            zipFileParent.mkdirs();
        }
    }

    /**
     * 
     *
     * @param srcFileUri
     * @param zos
     * @param entry
     * @throws IOException
     * @throws IllegalArgumentException
     */
    private void compressDir(Uri srcFileUri, ZipOutputStream zos, String entry)
            throws IOException, IllegalArgumentException {
        if (null == zos) {
            XLog.e(CLASS_NAME, "Method compressDir: param is null!");
            throw new IllegalArgumentException();
        }
        if (srcFileUri.getPath().startsWith(XConstant.ANDROID_ASSET)) {
            compressAssetsFile(srcFileUri, zos, entry);
        } else {
            compressNormalFile(srcFileUri, zos, entry);
        }
    }

    /**
     * assets
     *
     * @param srcFileUri
     * @param zos
     * @param entry
     * @throws IOException
     */
    private void compressAssetsFile(Uri srcFileUri, ZipOutputStream zos, String entry)
            throws IOException, FileNotFoundException {
        srcFileUri = handleUri(srcFileUri);
        String srcPath = srcFileUri.getPath().substring(XConstant.ANDROID_ASSET.length());
        if (XAssetsFileUtils.isFile(mContext, srcPath)) {
            zipFile(srcFileUri, zos, entry + srcFileUri.getLastPathSegment());
        } else {
            String childrens[] = mContext.getAssets().list(srcPath);
            if (null == childrens || 0 == childrens.length) {
                XLog.e(CLASS_NAME, "Method compressAssetsFile: Source file path does not exist!");
                throw new FileNotFoundException();
            }
            Uri srcRootUri = srcFileUri;
            for (int index = 0; index < childrens.length; index++) {
                srcFileUri = Uri.parse(srcRootUri.toString() + File.separator + childrens[index]);
                if (XAssetsFileUtils.isFile(mContext, srcPath + File.separator + childrens[index])) {
                    zipFile(srcFileUri, zos, entry + childrens[index]);
                } else {
                    compressAssetsFile(srcFileUri, zos, entry + childrens[index] + File.separator);
                }
            }
        }
    }

    /**
     * ?uri'/'?'/'
     *
     * @param srcFileUri
     * @return
     */
    private Uri handleUri(Uri srcFileUri) {
        String srcFile = srcFileUri.toString();
        if (srcFile.endsWith(File.separator)) {
            srcFileUri = Uri.parse(srcFile.substring(0, srcFile.length() - 1));
        }
        return srcFileUri;
    }

    /**
     * ?assets
     *
     * @param srcFileUri
     * @param zos
     * @param entry
     * @throws IOException
     * @throws FileNotFoundException
     */
    private void compressNormalFile(Uri srcFileUri, ZipOutputStream zos, String entry)
            throws IOException, FileNotFoundException {
        File srcFile = new File(srcFileUri.getPath());
        if (null == srcFile || !srcFile.exists()) {
            XLog.e(CLASS_NAME, "Method compressNormalFile:Source file path does not exist!");
            throw new FileNotFoundException();
        }
        String[] dirList = srcFile.list();
        if ((null == dirList || 1 > dirList.length) && srcFile.isFile()) {
            // ??
            zipFile(srcFileUri, zos, srcFile.getName());
        } else {
            // ?
            String srcRootPath = srcFileUri.toString();
            String srcFilePath = null;
            for (String pathName : dirList) {
                srcFilePath = srcRootPath + File.separator + pathName;
                srcFileUri = Uri.parse(srcFilePath);
                File f = new File(srcFileUri.getPath());
                if (f.isDirectory()) {
                    compressNormalFile(srcFileUri, zos, entry + f.getName() + File.separator);
                    continue;
                }
                zipFile(srcFileUri, zos, entry + f.getName());
            }
        }
    }

    /**
     * ?
     *
     * @param srcFileUri
     * @param zos
     * @param zipEntryPath
     * @throws IOException
     */
    private void zipFile(Uri srcFileUri, ZipOutputStream zos, String zipEntryPath) throws IOException {
        InputStream srcIs = mResourceApi.openForRead(srcFileUri).inputStream;
        ZipEntry zipEntry = new ZipEntry(zipEntryPath);
        zos.putNextEntry(zipEntry);
        writeToZip(srcIs, zos);
    }

    /**
     * ??zip
     *
     * @param srcIs
     * @param zos
     * @throws IOException
     * @throws IllegalArgumentException
     */
    private void writeToZip(InputStream srcIs, ZipOutputStream zos) throws IOException, IllegalArgumentException {
        if (null == srcIs || null == zos) {
            XLog.e(CLASS_NAME, "Method writeToZip: param is null!");
            throw new IllegalArgumentException();
        }
        try {
            byte[] readBuffer = new byte[XConstant.BUFFER_LEN];
            int bytesIn = 0;
            bytesIn = srcIs.read(readBuffer);
            while (bytesIn != -1) {
                zos.write(readBuffer, 0, bytesIn);
                bytesIn = srcIs.read(readBuffer);
            }
        } catch (IOException e) {
            XLog.e(CLASS_NAME, "Zip file failed!");
            throw new IOException();
        } finally {
            srcIs.close();
            zos.closeEntry();
        }
    }

    /**
     * ?
     *
     * @param srcEntries
     *            ????
     * @param destZipFile
     *            ??test.zip?a/b/c/test.zip
     * @return ??
     * @throws FileNotFoundException
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws JSONException
     */
    private void zipFiles(JSONArray srcEntries, String destZipFile)
            throws FileNotFoundException, IOException, IllegalArgumentException, JSONException {
        Uri destFileUri = getFileUri(destZipFile);
        prepareForZipDir(destFileUri);

        ZipOutputStream zos = new ZipOutputStream(mResourceApi.openOutputStream(destFileUri));
        Uri[] paths = new Uri[srcEntries.length()];
        String path = null;
        for (int i = 0; i < srcEntries.length(); i++) {
            path = srcEntries.getString(i);
            paths[i] = getFileUri(path);
            compressDir(paths[i], zos, "");
        }
        zos.close();
    }

    /**
     * unzip
     *
     * @param zipFileURL
     *            zipURL
     * @param destFileURL
     *            ?URLWorkspace
     * @return ??
     * @throws FileNotFoundException
     * @throws IOException
     * @throws IllegalArgumentException
     */
    private void unzip(String zipFileURL, String destFileURL)
            throws FileNotFoundException, IOException, IllegalArgumentException {
        Uri zipFileUri = getFileUri(zipFileURL);
        Uri dstFileUri = getFileUri(destFileURL);
        InputStream is = mResourceApi.openForRead(zipFileUri).inputStream;
        unzipFileFromStream(dstFileUri, is);
    }

    /**
     * ??zip?
     *
     * @param dstFileUri
     *            
     * @param is
     *            ?zip?
     * @return ??
     * @throws IOException
     * @throws FileNotFoundException
     * @throws IllegalArgumentException
     */
    private void unzipFileFromStream(Uri dstFileUri, InputStream is)
            throws IOException, FileNotFoundException, IllegalArgumentException {
        if (null == dstFileUri || null == is) {
            XLog.e(CLASS_NAME, "Method unzipFileFromStream: params is null");
            throw new IllegalArgumentException();
        }
        ZipInputStream zis = new ZipInputStream(is);
        ZipEntry entry = null;
        Uri unZipUri = null;
        while (null != (entry = zis.getNextEntry())) {
            File unZipFile = new File(dstFileUri.getPath() + File.separator + entry.getName());
            unZipUri = Uri.fromFile(unZipFile);
            if (entry.isDirectory()) {
                if (!unZipFile.exists()) {
                    unZipFile.mkdirs();
                }
            } else {
                // ???
                prepareForZipDir(unZipUri);
                OutputStream fos = mResourceApi.openOutputStream(unZipUri);
                int readLen = 0;
                byte buffer[] = new byte[XConstant.BUFFER_LEN];
                while (-1 != (readLen = zis.read(buffer))) {
                    fos.write(buffer, 0, readLen);
                }
                fos.close();
            }
        }
        zis.close();
        is.close();
    }
}