com.runwaysdk.dataaccess.io.Backup.java Source code

Java tutorial

Introduction

Here is the source code for com.runwaysdk.dataaccess.io.Backup.java

Source

/**
 * Copyright (c) 2015 TerraFrame, Inc. All rights reserved.
 *
 * This file is part of Runway SDK(tm).
 *
 * Runway SDK(tm) 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 3 of the
 * License, or (at your option) any later version.
 *
 * Runway SDK(tm) 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Runway SDK(tm).  If not, see <http://www.gnu.org/licenses/>.
 */
package com.runwaysdk.dataaccess.io;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.runwaysdk.ServerExceptionMessageLocalizer;
import com.runwaysdk.business.Business;
import com.runwaysdk.business.BusinessQuery;
import com.runwaysdk.constants.DeployProperties;
import com.runwaysdk.constants.ServerProperties;
import com.runwaysdk.constants.VaultInfo;
import com.runwaysdk.constants.VaultProperties;
import com.runwaysdk.dataaccess.cache.globalcache.ehcache.CacheShutdown;
import com.runwaysdk.dataaccess.database.Database;
import com.runwaysdk.query.OIterator;
import com.runwaysdk.query.QueryFactory;
import com.runwaysdk.session.Request;
import com.runwaysdk.session.Session;
import com.runwaysdk.system.metadata.CreateBackupException;
import com.runwaysdk.util.FileIO;

public class Backup {
    public static final String WEBAPP_DIR_NAME = "webapp";

    public static final String PROVILE_DIR_NAME = "profiles";

    public static final String VAULT_DIR_NAME = "vaults";

    public static final String WEBFILE_DIR_NAME = "webfiles";

    public static final String CACHE = "cache";

    public static final String SQL = "sql";

    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss");

    private PrintStream logPrintStream;

    private String backupFileRootName;

    private String backupFileLocation;

    private String tempBackupFileLocation;

    private File tempBackupDir;

    private boolean backupVaults;
    //
    // private boolean backupWebFiles;

    private String timeStampedName;

    private String cacheDir;

    private String cacheName;

    private java.util.Date now = new java.util.Date();

    private List<BackupAgent> agents;

    private Log log;

    public Backup(PrintStream logPrintStream, String backupFileRootName, String backupFileLocationDir,
            boolean backupVaults, boolean backupWebFiles) {
        log = LogFactory.getLog(this.getClass());

        this.logPrintStream = logPrintStream;

        this.backupFileRootName = backupFileRootName;
        this.backupFileLocation = backupFileLocationDir;

        this.backupVaults = backupVaults;
        // this.backupWebFiles = backupWebFiles;

        this.timeStampedName = this.backupFileRootName + "-" + formatter.format(now);
        this.tempBackupFileLocation = backupFileLocationDir + File.separator + "_temp_" + this.timeStampedName;

        this.tempBackupDir = new File(this.tempBackupFileLocation);
        this.tempBackupDir.mkdirs();

        this.cacheDir = ServerProperties.getGlobalCacheFileLocation();
        this.cacheName = ServerProperties.getGlobalCacheName();

        this.agents = new LinkedList<BackupAgent>();
    }

    /**
     * Returns the name and location of the zip file.
     * 
     * @return name and location of the zip file.
     */
    public String backup() {
        return backup(true);
    }

    /**
     * Returns the name and location of the zip file.
     * 
     * @param useNamespace
     *          flag for backing up database by schema or by list of application
     *          tables
     * 
     * @return name and location of the zip file.
     */
    public String backup(boolean useNamespace) {
        this.log.trace("Starting backup for [" + backupFileLocation + "][" + backupFileRootName + "].");

        for (BackupAgent agent : agents) {
            agent.preBackup();
        }

        // backupCacheFile();

        backupDatabase(useNamespace);

        backupWebapp();

        backupVaults();

        if (this.backupVaults) {
            backupVaults();
        }

        /*
         * // backup the profiles backupProfiles();
         * 
         * if (this.backupWebFiles) { backupWebFilesVaults(); }
         */
        now = new java.util.Date();
        String zipBackupFileName = this.timeStampedName + ".zip";

        String zipFileNameAndLocation = zipFiles(zipBackupFileName);

        try {
            FileIO.deleteDirectory(this.tempBackupDir);
        } catch (IOException e) {
            CreateBackupException cbe = new CreateBackupException(e);
            cbe.setLocation(this.tempBackupDir.getAbsolutePath());
            throw cbe;
        }

        this.logPrintStream
                .println(ServerExceptionMessageLocalizer.backupCompleteMessage(Session.getCurrentLocale()));

        for (BackupAgent agent : agents) {
            agent.postBackup();
        }

        this.log.trace("Finished backup file [" + zipFileNameAndLocation + "]");

        return zipFileNameAndLocation;
    }

    private void backupVaults() {
        log.trace("Starting backup of vaults.");

        QueryFactory qf = new QueryFactory();
        BusinessQuery vaultQ = qf.businessQuery(VaultInfo.CLASS);

        String backupVaultFileLocation = this.tempBackupFileLocation + File.separator + VAULT_DIR_NAME
                + File.separator;

        OIterator<Business> i = vaultQ.getIterator();
        try {
            for (Business vault : i) {
                String vaultName = vault.getValue(VaultInfo.VAULT_NAME);
                String vaultLocation = VaultProperties.getPath(vaultName);

                File vaultLocationFile = new File(vaultLocation);

                if (vaultLocationFile != null && vaultLocationFile.exists()) {
                    log.debug("Backing up vault [" + vaultName + "] at location [" + vaultLocation + "].");

                    FileIO.copyFolder(new File(vaultLocation),
                            new File(backupVaultFileLocation + File.separator + vault.getId() + File.separator));
                } else {
                    log.warn("Skipped backup of vault [" + vaultName + "] at location [" + vaultLocation
                            + "] because it does not exist.");
                }
            }
        } finally {
            i.close();
        }
    }

    private void backupWebapp() {
        File backupProfileLocationFile = new File(
                this.tempBackupFileLocation + File.separator + WEBAPP_DIR_NAME + File.separator);

        String webappRootDir = DeployProperties.getDeployPath();

        File webappRootFile = new File(webappRootDir);

        FilenameFilter filenameFilter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                if (name.endsWith(".svn") || dir.getName().startsWith(".")) {
                    return false;
                }

                return true;
            }
        };

        boolean success = FileIO.copyFolder(webappRootFile, backupProfileLocationFile, filenameFilter);
        if (!success) {
            // TODO : This success stuff is garbage, I want the actual IOException why swallow it
            CreateBackupException cbe = new CreateBackupException();
            cbe.setLocation(backupProfileLocationFile.getAbsolutePath());
            throw cbe;
        }
    }

    @SuppressWarnings("unused")
    private void backupCacheFile() {
        this.logPrintStream
                .println(ServerExceptionMessageLocalizer.backingUpCacheMessage(Session.getCurrentLocale()));
        try {
            // Make the temp cache directory
            File directory = new File(this.tempBackupFileLocation + File.separator + CACHE + File.separator);
            String copyTo = directory.getAbsolutePath();
            directory.mkdirs();

            File cacheDir = new File(this.cacheDir);
            this.log.trace("Backing up cache files from [" + cacheDir + "] to [" + copyTo + "].");

            FileFilter filter = new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.getName().startsWith(Backup.this.cacheName);
                }
            };

            File[] files = cacheDir.listFiles(filter);

            if (files != null) {
                for (File file : files) {
                    this.log.debug("Backing up cache file [" + file + "].");

                    FileInputStream iStream = new FileInputStream(file);
                    FileOutputStream oStream = new FileOutputStream(
                            new File(copyTo + File.separator + file.getName()));

                    FileIO.write(oStream, iStream);
                }
            }
        } catch (IOException e) {
            CreateBackupException cbe = new CreateBackupException(e);
            cbe.setLocation(new File(this.tempBackupFileLocation + File.separator + CACHE + File.separator)
                    .getAbsolutePath());
            throw cbe;
        }

        this.log.trace("Finished backing up the cache files.");
    }

    private void backupDatabase(boolean useNamespace) {
        this.logPrintStream
                .println(ServerExceptionMessageLocalizer.backingUpDatabaseMessage(Session.getCurrentLocale()));

        // Make the temp sql directory
        File directory = new File(this.tempBackupFileLocation + File.separator + SQL + File.separator);
        directory.mkdirs();

        String createdFile;
        if (useNamespace) {
            String namespace = Database.getApplicationNamespace();

            this.log.debug("Backing up the database with namespace [" + namespace + "]");

            createdFile = Database.backup(namespace, directory.getAbsolutePath(), this.timeStampedName, false);
        } else {
            List<String> tableNames = Database.getAllApplicationTables();

            createdFile = Database.backup(tableNames, directory.getAbsolutePath(), backupFileRootName, false);
        }

        this.log.debug("Finished backing up the database without output file [" + createdFile + "]");
    }

    /**
     * Zips the directory and then returns the name and location of the zip file.
     * 
     * @param zipBackupFileName
     * @return the name and location of the zip file.
     */
    private String zipFiles(String zipBackupFileName) {
        this.logPrintStream.println(ServerExceptionMessageLocalizer
                .compressingDirectoryMessage(Session.getCurrentLocale(), this.tempBackupFileLocation));

        String zipFileNameAndLocation = this.backupFileLocation + File.separator + zipBackupFileName;

        this.log.trace("Creating zipfile [" + zipBackupFileName + "]");

        try {
            FileFilter fileFilter = new FileFilter() {
                public boolean accept(File file) {
                    return true;
                }
            };

            FileIO.zip(this.tempBackupDir, fileFilter, new File(zipFileNameAndLocation));
        } catch (IOException e) {
            CreateBackupException cbe = new CreateBackupException(e);
            cbe.setLocation(this.tempBackupDir.getAbsolutePath());
            throw cbe;
        }

        this.log.trace("Finished creating zipfile [" + zipBackupFileName + "]");

        return zipFileNameAndLocation;
    }

    public void addAgents(BackupAgent agent) {
        agents.add(agent);
    }

    /*
     * private void backupWebFilesVaults() { QueryFactory qf = new QueryFactory();
     * BusinessDAOQuery webFileQ = qf.businessDAOQuery(WebFileInfo.CLASS);
     * 
     * String backupWebFileFileLocation =
     * this.tempBackupFileLocation+File.separator+WEBFILE_DIR_NAME+File.separator;
     * 
     * // Create the web file dir File backupWebFileFile = new
     * File(backupWebFileFileLocation); backupWebFileFile.mkdir();
     * 
     * OIterator<BusinessDAOIF> i = webFileQ.getIterator(); try { for
     * (BusinessDAOIF businessDAOIF : i) { WebFileDAOIF webFileDAOIF =
     * (WebFileDAOIF)businessDAOIF;
     * 
     * InputStream inputStream = webFileDAOIF.getFile();
     * 
     * File thisBackupWebFileFile = new
     * File(backupWebFileFileLocation+webFileDAOIF.getId());
     * 
     * if (thisBackupWebFileFile != null && thisBackupWebFileFile.exists()) { try
     * { BufferedOutputStream outputStream = new BufferedOutputStream(new
     * FileOutputStream(thisBackupWebFileFile)); FileIO.write(outputStream,
     * inputStream); } catch (IOException e) { throw new
     * FileWriteException(thisBackupWebFileFile, e); } }
     * 
     * } } finally { i.close(); } }
     */
    /*
     * private void backupProfiles() { File backupProfileLocationFile = new
     * File(this
     * .tempBackupFileLocation+File.separator+PROVILE_DIR_NAME+File.separator);
     * 
     * String profileRootDir = ProfileManager.getProfileRootDir().toString();
     * 
     * File profileRootFile = new File(profileRootDir);
     * 
     * FilenameFilter filenameFilter = new FilenameFilter() { public boolean
     * accept(File dir, String name) { if (name.endsWith(".properties") ||
     * name.endsWith(".xml") || name.endsWith(".xsd") ) { return true; }
     * 
     * if (dir.isDirectory() && !dir.getName().startsWith(".")) { return true; }
     * 
     * return false; } };
     * 
     * FileIO.copyFolder(profileRootFile, backupProfileLocationFile,
     * filenameFilter); }
     */

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            Backup.start(args);
        } finally {
            CacheShutdown.shutdown();
        }
    }

    @Request
    private static void start(String[] args) {
        if (args.length != 2) {
            String errMessage = "Invalid number of arguments given.  Please provide 1) the root file name of the backup and 2) the backup file location.\n"
                    + "The name of the backup file will include the root file name, a timestamp, and will contain the \".zip\" extension.";
            throw new RuntimeException(errMessage);
        } else {
            Backup backup = new Backup(System.out, args[0], args[1], true, true);
            backup.backup();
        }
    }
}