org.mycontroller.standalone.BackupRestore.java Source code

Java tutorial

Introduction

Here is the source code for org.mycontroller.standalone.BackupRestore.java

Source

/**
 * Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.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 org.mycontroller.standalone;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.ws.rs.BadRequestException;

import org.apache.commons.io.FileUtils;
import org.mycontroller.standalone.api.jaxrs.mapper.BackupFile;
import org.mycontroller.standalone.db.DataBaseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Jeeva Kandasamy (jkandasa)
 * @since 0.0.3
 */
public class BackupRestore {
    private static final Logger _logger = LoggerFactory.getLogger(BackupRestore.class.getName());
    private static final String DATABASE_FILENAME = "database_backup.zip";
    private static final String APP_PROPERTIES_FILENAME = "mycontroller.properties";
    private static final String APP_CONF_LOCATION = "../conf/";
    private static String KEY_STORE_FILE = null;
    public static final String FILE_NAME_IDENTITY = "_mc_backup-";

    private static boolean isbackupRestoreRunning = false;

    public static synchronized void backup(String prefix) {
        //backup database
        //backup configuration file
        //backup certificates
        //backup logback xml file

        if (isbackupRestoreRunning) {
            throw new BadRequestException("A backup or restore is running");
        }

        isbackupRestoreRunning = true;
        String applicationBackupDir = ObjectFactory.getAppProperties().getBackupSettings().getBackupLocation()
                + prefix + FILE_NAME_IDENTITY + new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss").format(new Date());
        //Create parent dir if not exist
        try {
            FileUtils.forceMkdir(FileUtils.getFile(applicationBackupDir));
            String databaseBackup = ObjectFactory.getAppProperties().getTmpLocation() + DATABASE_FILENAME;
            if (DataBaseUtils.backupDatabase(databaseBackup)) {
                //Copy database file
                FileUtils.moveFile(FileUtils.getFile(databaseBackup),
                        FileUtils.getFile(applicationBackupDir + "/" + DATABASE_FILENAME));
                //copy static files
                copyStaticFiles(applicationBackupDir);
                _logger.debug("Copied all the files");
                final ZipOutputStream outZip = new ZipOutputStream(
                        new FileOutputStream(applicationBackupDir + ".zip"));
                //add database file
                MycUtils.addToZipFile(applicationBackupDir + "/" + DATABASE_FILENAME, outZip);
                //add properties file
                MycUtils.addToZipFile(applicationBackupDir + "/" + APP_PROPERTIES_FILENAME, outZip);
                //add keystore file, if https enabled
                if (ObjectFactory.getAppProperties().isWebHttpsEnabled() && KEY_STORE_FILE != null) {
                    MycUtils.addToZipFile(KEY_STORE_FILE, outZip);
                }
                //compress all the files
                outZip.close();
                _logger.debug("zip file creation done");
                //clean temporary files
                FileUtils.deleteDirectory(FileUtils.getFile(applicationBackupDir));
            } else {
                //Throw exception
            }
        } catch (IOException ex) {
            _logger.error("Exception,", ex);
        } finally {
            isbackupRestoreRunning = false;
        }

    }

    public static void restore(BackupFile backupFile) throws IOException {
        if (isbackupRestoreRunning) {
            throw new BadRequestException("A backup or restore is running");
        }

        if (!backupFile.getName().contains(FILE_NAME_IDENTITY)) {
            throw new BadRequestException("backup file name should contain '" + FILE_NAME_IDENTITY
                    + "'. Your input:" + backupFile.getName());
        }

        isbackupRestoreRunning = true;

        String extractedLocation = ObjectFactory.getAppProperties().getTmpLocation()
                + backupFile.getName().replaceAll(".zip", "");
        try {

            String oldDatabaseLocation = ObjectFactory.getAppProperties().getDbH2DbLocation();
            //Extract zip file
            _logger.debug("Zip file:{}", backupFile.getAbsolutePath());

            extractZipFile(backupFile.getAbsolutePath(), extractedLocation);
            _logger.debug("All the files extracted to '{}'", extractedLocation);

            //Validate required files
            if (!FileUtils.getFile(extractedLocation + "/" + DATABASE_FILENAME).exists()) {
                _logger.error("Unable to continue restore opration! selected file not found! File:{}",
                        extractedLocation + "/" + DATABASE_FILENAME);
                return;
            }

            //Stop all services
            StartApp.stopServices();

            //Remove old properties file
            FileUtils.deleteQuietly(FileUtils.getFile(APP_CONF_LOCATION + APP_PROPERTIES_FILENAME));

            //Restore properties file
            FileUtils.moveFile(FileUtils.getFile(extractedLocation + "/" + APP_PROPERTIES_FILENAME),
                    FileUtils.getFile(APP_CONF_LOCATION + APP_PROPERTIES_FILENAME));
            //Load initial properties
            StartApp.loadInitialProperties();

            //Remove old files
            FileUtils.deleteQuietly(FileUtils.getFile(ObjectFactory.getAppProperties().getWebSslKeystoreFile()));

            if (ObjectFactory.getAppProperties().isWebHttpsEnabled()) {
                //restore key store file
                FileUtils.moveFile(
                        FileUtils.getFile(extractedLocation + "/"
                                + FileUtils.getFile(ObjectFactory.getAppProperties().getWebSslKeystoreFile())
                                        .getName()),
                        FileUtils.getFile(ObjectFactory.getAppProperties().getWebSslKeystoreFile()));
            }

            //remove old database
            if (FileUtils.deleteQuietly(FileUtils.getFile(oldDatabaseLocation + ".h2.db"))) {
                _logger.debug("Old database removed successfully");
            } else {
                _logger.warn("Unable to remove old database");
            }
            //restore database
            if (DataBaseUtils.restoreDatabase(extractedLocation + "/" + DATABASE_FILENAME)) {
                _logger.info("Restore completed successfully. Start '{}' server manually",
                        AppProperties.APPLICATION_NAME);
            } else {
                _logger.error("Restore failed!");
            }

        } finally {
            //clean tmp file
            FileUtils.deleteQuietly(FileUtils.getFile(extractedLocation));
            _logger.debug("Tmp location[{}] clean success", extractedLocation);
            isbackupRestoreRunning = false;
        }
        //Stop application
        System.exit(0);
    }

    private static void copyStaticFiles(String applicationBackupDir) {
        //Copy mycontroller.properties file
        try {
            FileUtils.copyFile(FileUtils.getFile(System.getProperty("mc.conf.file")),
                    FileUtils.getFile(applicationBackupDir + "/" + APP_PROPERTIES_FILENAME));
            if (ObjectFactory.getAppProperties().isWebHttpsEnabled()) {
                KEY_STORE_FILE = applicationBackupDir + "/"
                        + FileUtils.getFile(ObjectFactory.getAppProperties().getWebSslKeystoreFile()).getName();
                FileUtils.copyFile(FileUtils.getFile(ObjectFactory.getAppProperties().getWebSslKeystoreFile()),
                        FileUtils.getFile(KEY_STORE_FILE));
            }

        } catch (IOException ex) {
            _logger.error("Static file backup failed!", ex);
        }
    }

    private static void extractZipFile(String zipFileName, String destination)
            throws FileNotFoundException, IOException {
        ZipFile zipFile = new ZipFile(zipFileName);
        Enumeration<?> enu = zipFile.entries();
        //create destination if not exists
        FileUtils.forceMkdir(FileUtils.getFile(destination));
        while (enu.hasMoreElements()) {
            ZipEntry zipEntry = (ZipEntry) enu.nextElement();
            String name = zipEntry.getName();
            long size = zipEntry.getSize();
            long compressedSize = zipEntry.getCompressedSize();
            _logger.debug("name:{} | size:{} | compressed size:{}", name, size, compressedSize);
            File file = FileUtils.getFile(destination + "/" + name);
            //Create destination if it's not available
            if (name.endsWith("/")) {
                file.mkdirs();
                continue;
            }

            File parent = file.getParentFile();
            if (parent != null) {
                parent.mkdirs();
            }

            InputStream is = zipFile.getInputStream(zipEntry);
            FileOutputStream fos = new FileOutputStream(file);
            byte[] bytes = new byte[1024];
            int length;
            while ((length = is.read(bytes)) >= 0) {
                fos.write(bytes, 0, length);
            }
            is.close();
            fos.close();
        }
        zipFile.close();
    }
}