com.openkm.servlet.RepositoryStartupServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.openkm.servlet.RepositoryStartupServlet.java

Source

/**
 * OpenKM, Open Document Management System (http://www.openkm.com)
 * Copyright (c) 2006-2015 Paco Avila & Josep Llort
 * 
 * No bytes were intentionally harmed during the development of this application.
 * 
 * This program 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 2 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.openkm.servlet;

import java.io.File;
import java.io.FileReader;
import java.util.Calendar;
import java.util.Properties;
import java.util.Timer;
import java.util.concurrent.TimeUnit;

import javax.servlet.GenericServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.jbpm.JbpmContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;

import com.cybozu.labs.langdetect.DetectorFactory;
import com.cybozu.labs.langdetect.LangDetectException;
import com.openkm.core.Config;
import com.openkm.core.Cron;
import com.openkm.core.MimeTypeConfig;
import com.openkm.core.UINotification;
import com.openkm.core.UpdateInfo;
import com.openkm.dao.HibernateUtil;
import com.openkm.extension.core.ExtensionManager;
import com.openkm.kea.RDFREpository;
import com.openkm.module.db.DbRepositoryModule;
import com.openkm.module.db.stuff.FsDataStore;
import com.openkm.module.jcr.JcrRepositoryModule;
import com.openkm.spring.SystemAuthentication;
import com.openkm.util.CronTabUtils;
import com.openkm.util.DocConverter;
import com.openkm.util.ExecutionUtils;
import com.openkm.util.FormUtils;
import com.openkm.util.JBPMUtils;
import com.openkm.util.UserActivity;
import com.openkm.util.WarUtils;
import com.openkm.util.pendtask.PendingTaskExecutor;

/**
 * Servlet Startup Class
 */
public class RepositoryStartupServlet extends HttpServlet {
    private static Logger log = LoggerFactory.getLogger(RepositoryStartupServlet.class);
    private static final long serialVersionUID = 1L;
    private static Timer uiTimer; // Update Info (OpenKM Update Information)
    private static Timer cronTimer; // CRON Manager
    private static Timer uinTimer; // User Interface Notification (Create From Administration)
    private static Cron cron;
    private static UINotification uin;
    private static UpdateInfo ui;
    private static boolean hasConfiguredDataStore = false;
    private static boolean running = false;

    @Override
    public void init() throws ServletException {
        super.init();
        ServletContext sc = getServletContext();

        // Read configuration file
        Properties config = Config.load(sc);

        // Call only once during initialization time of your application
        // @see http://issues.openkm.com/view.php?id=1577
        SLF4JBridgeHandler.install();

        // Get OpenKM version
        WarUtils.readAppVersion(sc);
        log.info("*** Application version: {} ***", WarUtils.getAppVersion());

        // Database initialize
        log.info("*** Hibernate initialize ***");
        HibernateUtil.getSessionFactory();

        // Create missing directories
        // NOTE: Should be executed AFTER Hibernate initialization because if in created mode
        // initialization will drop these directories
        createMissingDirs();

        try {
            // Initialize property groups
            log.info("*** Initialize property groups... ***");
            FormUtils.parsePropertyGroupsForms(Config.PROPERTY_GROUPS_XML);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // Initialize language detection engine
        try {
            log.info("*** Initialize language detection engine... ***");
            DetectorFactory.loadProfile(Config.LANG_PROFILES_BASE);
        } catch (LangDetectException e) {
            log.error(e.getMessage(), e);
        }

        // Load database configuration
        Config.reload(sc, config);

        // Invoke start
        start();

        // Activity log
        UserActivity.log(Config.SYSTEM_USER, "MISC_OPENKM_START", null, null, null);
    }

    @Override
    public void destroy() {
        super.destroy();

        // Activity log
        UserActivity.log(Config.SYSTEM_USER, "MISC_OPENKM_STOP", null, null, null);

        // Invoke stop
        stop(this);

        try {
            // Database shutdown
            log.info("*** Hibernate shutdown ***");
            HibernateUtil.closeSessionFactory();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        try {
            // Call only once during destroy time of your application
            // @see http://issues.openkm.com/view.php?id=1577
            SLF4JBridgeHandler.uninstall();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * Start OpenKM and possible repository and database initialization
     */
    public static synchronized void start() throws ServletException {
        SystemAuthentication systemAuth = new SystemAuthentication();

        if (running) {
            throw new IllegalStateException("OpenKM already started");
        }

        try {
            log.info("*** Repository initializing... ***");

            if (Config.REPOSITORY_NATIVE) {
                systemAuth.enable();
                DbRepositoryModule.initialize();
                systemAuth.disable();
            } else {
                JcrRepositoryModule.initialize();
            }

            log.info("*** Repository initialized ***");
        } catch (Exception e) {
            throw new ServletException(e.getMessage(), e);
        }

        log.info("*** User database initialized ***");

        if (!Config.REPOSITORY_NATIVE) {
            // Test for datastore
            SessionImpl si = (SessionImpl) JcrRepositoryModule.getSystemSession();

            if (((RepositoryImpl) si.getRepository()).getDataStore() == null) {
                hasConfiguredDataStore = false;
            } else {
                hasConfiguredDataStore = true;
            }
        }

        // Create timers
        uiTimer = new Timer("Update Info", true);
        cronTimer = new Timer("Crontab Manager", true);
        uinTimer = new Timer("User Interface Notification", true);

        // Workflow
        log.info("*** Initializing workflow engine... ***");
        JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
        jbpmContext.setSessionFactory(HibernateUtil.getSessionFactory());
        jbpmContext.getGraphSession();
        jbpmContext.getJbpmConfiguration().getJobExecutor().start(); // startJobExecutor();
        jbpmContext.close();

        // Mime types
        log.info("*** Initializing MIME types... ***");
        MimeTypeConfig.loadMimeTypes();

        log.info("*** Activating update info ***");
        ui = new UpdateInfo();
        uiTimer.schedule(ui, TimeUnit.MINUTES.toMillis(5), TimeUnit.HOURS.toMillis(24)); // First in 5 min, next each 24 hours

        log.info("*** Activating cron ***");
        cron = new Cron();
        Calendar calCron = Calendar.getInstance();
        calCron.add(Calendar.MINUTE, 1);
        calCron.set(Calendar.SECOND, 0);
        calCron.set(Calendar.MILLISECOND, 0);

        // Round begin to next minute, 0 seconds, 0 miliseconds
        cronTimer.scheduleAtFixedRate(cron, calCron.getTime(), 60 * 1000); // First in 1 min, next each 1 min

        log.info("*** Activating UI Notification ***");
        uin = new UINotification();

        // First in 1 second next in x minutes
        uinTimer.scheduleAtFixedRate(uin, 1000, TimeUnit.MINUTES.toMillis(Config.SCHEDULE_UI_NOTIFICATION));

        try {
            // General maintenance works
            String dapContent = "com.openkm.dao.DashboardActivityDAO.purge();";
            CronTabUtils.createOrUpdate("Dashboard Activity Purge", "@daily", dapContent);

            String uisContent = "com.openkm.cache.UserItemsManager.serialize();";
            CronTabUtils.createOrUpdate("User Items Serialize", "@hourly", uisContent);

            String ruiContent = "com.openkm.cache.UserItemsManager.refreshDbUserItems();";
            CronTabUtils.createOrUpdate("Refresh User Items", "@weekly", ruiContent);

            String umiContent = "new com.openkm.core.UserMailImporter().run();";
            CronTabUtils.createOrUpdate("User Mail Importer", "*/30 * * * *", umiContent);

            String tewContent = "new com.openkm.extractor.TextExtractorWorker().run();";
            CronTabUtils.createOrUpdate("Text Extractor Worker", "*/5 * * * *", tewContent);

            String swdContent = "new com.openkm.core.Watchdog().run();";
            CronTabUtils.createOrUpdate("Session Watchdog", "*/5 * * * *", swdContent);

            String pptContent = "new com.openkm.util.pendtask.PendingTaskExecutor().run();";
            CronTabUtils.createOrUpdate("Process Pending Tasks", "*/5 * * * *", pptContent);

            // Datastore garbage collection
            if (!Config.REPOSITORY_NATIVE && hasConfiguredDataStore) {
                String dgcContent = "new com.openkm.module.jcr.stuff.DataStoreGarbageCollector().run();";
                CronTabUtils.createOrUpdate("Datastore Garbage Collector", "@daily", dgcContent);
            }
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }

        try {
            log.info("*** Activating thesaurus repository ***");
            RDFREpository.getInstance();
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }

        try {
            if (Config.REMOTE_CONVERSION_SERVER.equals("")) {
                if (!Config.SYSTEM_OPENOFFICE_PATH.equals("")) {
                    log.info("*** Start OpenOffice manager ***");
                    DocConverter.getInstance().start();
                } else if (!Config.SYSTEM_OPENOFFICE_SERVER.equals("")) {
                    log.info("*** Using OpenOffice conversion server ***");
                } else {
                    log.warn("*** No OpenOffice manager nor server configured ***");
                }
            } else {
                log.info("*** Remote conversion configured ***");
            }
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        // Initialize plugin framework
        ExtensionManager.getInstance();

        try {
            log.info("*** Execute start script ***");
            File script = new File(Config.HOME_DIR + File.separatorChar + Config.START_SCRIPT);
            ExecutionUtils.runScript(script);
            File jar = new File(Config.HOME_DIR + File.separatorChar + Config.START_JAR);
            ExecutionUtils.getInstance().runJar(jar);
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        try {
            log.info("*** Execute start SQL ***");
            File sql = new File(Config.HOME_DIR + File.separatorChar + Config.START_SQL);

            if (sql.exists() && sql.canRead()) {
                FileReader fr = new FileReader(sql);
                HibernateUtil.executeSentences(fr);
                IOUtils.closeQuietly(fr);
            } else {
                log.warn("Unable to read sql: {}", sql.getPath());
            }
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        // OpenKM is started
        running = true;
    }

    /**
     * Close OpenKM and free resources
     */
    public static synchronized void stop(GenericServlet gs) {
        if (!running) {
            throw new IllegalStateException("OpenKM not started");
        }

        // Shutdown plugin framework
        ExtensionManager.getInstance().shutdown();

        try {
            if (Config.REMOTE_CONVERSION_SERVER.equals("")) {
                if (!Config.SYSTEM_OPENOFFICE_PATH.equals("")) {
                    log.info("*** Shutting down OpenOffice manager ***");
                    DocConverter.getInstance().stop();
                }
            }
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        log.info("*** Shutting down UI Notification... ***");
        uin.cancel();

        log.info("*** Shutting down cron... ***");
        cron.cancel();

        if (Config.UPDATE_INFO) {
            log.info("*** Shutting down update info... ***");
            ui.cancel();
        }

        // Cancel timers
        cronTimer.cancel();
        uinTimer.cancel();
        uiTimer.cancel();

        // Shutdown pending task executor
        log.info("*** Shutting pending task executor... ***");
        PendingTaskExecutor.shutdown();

        log.info("*** Shutting down repository... ***");

        try {
            // Preserve system user config
            if (!Config.REPOSITORY_NATIVE) {
                JcrRepositoryModule.shutdown();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        log.info("*** Repository shutted down ***");

        try {
            log.info("*** Execute stop script ***");
            File script = new File(Config.HOME_DIR + File.separatorChar + Config.STOP_SCRIPT);
            ExecutionUtils.runScript(script);
            File jar = new File(Config.HOME_DIR + File.separatorChar + Config.STOP_JAR);
            ExecutionUtils.getInstance().runJar(jar);
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        try {
            log.info("*** Execute stop SQL ***");
            File sql = new File(Config.HOME_DIR + File.separatorChar + Config.STOP_SQL);

            if (sql.exists() && sql.canRead()) {
                FileReader fr = new FileReader(sql);
                HibernateUtil.executeSentences(fr);
                IOUtils.closeQuietly(fr);
            } else {
                log.warn("Unable to read sql: {}", sql.getPath());
            }
        } catch (Throwable e) {
            log.warn(e.getMessage(), e);
        }

        log.info("*** Shutting down workflow engine... ***");
        JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
        jbpmContext.getJbpmConfiguration().getJobExecutor().stop();
        jbpmContext.getJbpmConfiguration().close();
        jbpmContext.close();

        // OpenKM is stopped
        running = false;
    }

    /**
     * Create missing needed directories.
     */
    private static void createMissingDirs() {
        // Initialize DXF cache folder
        File dxfCacheFolder = new File(Config.REPOSITORY_CACHE_DXF);
        if (!dxfCacheFolder.exists()) {
            log.info("Create missing directory {}", dxfCacheFolder.getPath());
            dxfCacheFolder.mkdirs();
        }

        // Initialize PDF cache folder
        File pdfCacheFolder = new File(Config.REPOSITORY_CACHE_PDF);
        if (!pdfCacheFolder.exists()) {
            log.info("Create missing directory {}", pdfCacheFolder.getPath());
            pdfCacheFolder.mkdirs();
        }

        // Initialize SWF cache folder
        File swfCacheFolder = new File(Config.REPOSITORY_CACHE_SWF);
        if (!swfCacheFolder.exists()) {
            log.info("Create missing directory {}", swfCacheFolder.getPath());
            swfCacheFolder.mkdirs();
        }

        // Initialize chroot folder
        if (Config.SYSTEM_MULTIPLE_INSTANCES) {
            File chrootFolder = new File(Config.INSTANCE_CHROOT_PATH);
            if (!chrootFolder.exists()) {
                log.info("Create missing directory {}", chrootFolder.getPath());
                chrootFolder.mkdirs();
            }
        }

        // Initialize purgatory home
        if (Config.REPOSITORY_PURGATORY_HOME != null && !Config.REPOSITORY_PURGATORY_HOME.isEmpty()) {
            File purgatoryFolder = new File(Config.REPOSITORY_PURGATORY_HOME);
            if (!purgatoryFolder.exists()) {
                log.info("Create missing directory {}", purgatoryFolder.getPath());
                purgatoryFolder.mkdirs();
            }
        }

        if (FsDataStore.DATASTORE_BACKEND_FS.equals(Config.REPOSITORY_DATASTORE_BACKEND)) {
            // Initialize datastore
            File repoDatastoreFolder = new File(Config.REPOSITORY_DATASTORE_HOME);
            if (!repoDatastoreFolder.exists()) {
                log.info("Create missing directory {}", repoDatastoreFolder.getPath());
                repoDatastoreFolder.mkdirs();
            }
        }

        // Initialize Hibernate Search indexes
        // NOTE: This is already created on Hibernate initialization
        File hSearchIndexesFolder = new File(Config.HIBERNATE_SEARCH_INDEX_HOME);
        if (!hSearchIndexesFolder.exists()) {
            log.info("Create missing directory {}", hSearchIndexesFolder.getPath());
            hSearchIndexesFolder.mkdirs();
        }
    }
}