com.baasbox.service.dbmanager.DbManagerService.java Source code

Java tutorial

Introduction

Here is the source code for com.baasbox.service.dbmanager.DbManagerService.java

Source

/*
 * Copyright (c) 2014.
 *
 * BaasBox - info-at-baasbox.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.baasbox.service.dbmanager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.comparator.LastModifiedFileComparator;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.xmlbeans.impl.piccolo.io.FileFormatException;

import play.libs.Akka;
import scala.concurrent.duration.Duration;

import com.baasbox.BBConfiguration;
import com.baasbox.BBInternalConstants;
import com.baasbox.dao.exception.FileNotFoundException;
import com.baasbox.db.DbHelper;
import com.baasbox.db.async.ExportJob;
import com.baasbox.service.logging.BaasBoxLogger;
import com.baasbox.util.FileSystemPathUtil;

public class DbManagerService {
    public static final String backupDir = BBConfiguration.getDBBackupDir();
    public static final String fileSeparator = System.getProperty("file.separator") != null
            ? System.getProperty("file.separator")
            : "/";

    /**
     * This method generate a full dump of the db in an asyncronus task.
     * 
     * The async nature of the method DOES NOT ensure the creation of the file
     * so, querying for the file name with the /admin/db/:filename could return a 404
     * @param appcode
     * @return
     * @throws FileNotFoundException
     */
    public static String exportDb(String appcode) throws FileNotFoundException {
        java.io.File dir = new java.io.File(backupDir);
        if (!dir.exists()) {
            boolean createdDir = dir.mkdirs();
            if (!createdDir) {
                throw new FileNotFoundException("unable to create backup dir");
            }
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
        String fileName = String.format("%s-%s.zip", sdf.format(new Date()),
                FileSystemPathUtil.escapeName(appcode));
        //Async task
        Akka.system().scheduler().scheduleOnce(Duration.create(1, TimeUnit.SECONDS),
                new ExportJob(dir.getAbsolutePath() + fileSeparator + fileName, appcode),
                Akka.system().dispatcher());
        return fileName;
    }

    public static void deleteExport(String fileName) throws FileNotFoundException, IOException {
        java.io.File file = new java.io.File(backupDir + fileSeparator + fileName);
        if (!file.exists()) {
            throw new FileNotFoundException("Export " + fileName + " not found");
        } else {
            boolean deleted = false;
            try {
                FileUtils.forceDelete(file);
                deleted = true;
            } catch (IOException e) {
                deleted = file.delete();
                if (deleted == false) {
                    file.deleteOnExit();
                }
            }
            if (!deleted) {
                throw new IOException("Unable to delete export.It will be deleted on the next reboot." + fileName);
            }
        }
    }

    public static List<String> getExports() {
        java.io.File dir = new java.io.File(backupDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        Collection<java.io.File> files = FileUtils.listFiles(dir, new String[] { "zip" }, false);
        File[] fileArr = files.toArray(new File[files.size()]);

        Arrays.sort(fileArr, LastModifiedFileComparator.LASTMODIFIED_REVERSE);

        List<String> fileNames = new ArrayList<String>();
        for (java.io.File file : fileArr) {
            fileNames.add(file.getName());
        }
        return fileNames;
    }

    public static void importDb(String appcode, ZipInputStream zis) throws FileFormatException, Exception {
        File newFile = null;
        FileOutputStream fout = null;
        try {
            //get the zipped file list entry
            ZipEntry ze = zis.getNextEntry();
            if (ze == null)
                throw new FileFormatException("Looks like the uploaded file is not a valid export.");
            if (ze.isDirectory()) {
                ze = zis.getNextEntry();
            }
            if (ze != null) {
                newFile = File.createTempFile("export", ".json");
                fout = new FileOutputStream(newFile);
                IOUtils.copy(zis, fout, BBConfiguration.getImportExportBufferSize());
                fout.close();
            } else {
                throw new FileFormatException("Looks like the uploaded file is not a valid export.");
            }
            ZipEntry manifest = zis.getNextEntry();
            if (manifest != null) {
                File manifestFile = File.createTempFile("manifest", ".txt");
                fout = new FileOutputStream(manifestFile);
                for (int c = zis.read(); c != -1; c = zis.read()) {
                    fout.write(c);
                }
                fout.close();
                String manifestContent = FileUtils.readFileToString(manifestFile);
                manifestFile.delete();
                Pattern p = Pattern.compile(BBInternalConstants.IMPORT_MANIFEST_VERSION_PATTERN);
                Matcher m = p.matcher(manifestContent);
                if (m.matches()) {
                    String version = m.group(1);
                    if (version.compareToIgnoreCase("0.6.0") < 0) { //we support imports from version 0.6.0
                        throw new FileFormatException(String.format(
                                "Current baasbox version(%s) is not compatible with import file version(%s)",
                                BBConfiguration.getApiVersion(), version));
                    } else {
                        if (BaasBoxLogger.isDebugEnabled())
                            BaasBoxLogger.debug("Version : " + version + " is valid");
                    }
                } else {
                    throw new FileFormatException("The manifest file does not contain a version number");
                }
            } else {
                throw new FileFormatException("Looks like zip file does not contain a manifest file");
            }
            if (newFile != null) {
                DbHelper.importData(appcode, newFile);
                zis.closeEntry();
                zis.close();
            } else {
                throw new FileFormatException("The import file is empty");
            }
        } catch (FileFormatException e) {
            BaasBoxLogger.error(ExceptionUtils.getMessage(e));
            throw e;
        } catch (Throwable e) {
            BaasBoxLogger.error(ExceptionUtils.getStackTrace(e));
            throw new Exception("There was an error handling your zip import file.", e);
        } finally {
            try {
                if (zis != null) {
                    zis.close();
                }
                if (fout != null) {
                    fout.close();
                }
            } catch (IOException e) {
                // Nothing to do here
            }
        }
    }//importDb

}