All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.manydesigns.portofino.modules.PageactionsModule Maven / Gradle / Ivy

/*
 * Copyright (C) 2005-2017 ManyDesigns srl.  All rights reserved.
 * http://www.manydesigns.com/
 *
 * This 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.
 *
 * This software 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 this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package com.manydesigns.portofino.modules;

import com.manydesigns.elements.util.ElementsFileUtils;
import com.manydesigns.portofino.PortofinoProperties;
import com.manydesigns.portofino.cache.CacheResetEvent;
import com.manydesigns.portofino.cache.CacheResetListener;
import com.manydesigns.portofino.cache.CacheResetListenerRegistry;
import com.manydesigns.portofino.di.Inject;
import com.manydesigns.portofino.dispatcher.DispatcherLogic;
import com.manydesigns.portofino.pageactions.activitystream.ActivityStreamAction;
import com.manydesigns.portofino.pageactions.custom.CustomAction;
import com.manydesigns.portofino.pageactions.form.FormAction;
import com.manydesigns.portofino.pageactions.form.TableFormAction;
import com.manydesigns.portofino.pageactions.registry.PageActionRegistry;
import com.manydesigns.portofino.pageactions.registry.TemplateRegistry;
import com.manydesigns.portofino.pageactions.text.TextAction;
import com.manydesigns.portofino.shiro.SecurityGroovyRealm;
import groovy.util.GroovyScriptEngine;
import net.sf.ehcache.CacheManager;
import org.apache.commons.configuration.Configuration;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.util.LifecycleUtils;
import org.apache.shiro.web.env.EnvironmentLoader;
import org.apache.shiro.web.env.WebEnvironment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContext;
import java.io.File;

/*
* @author Paolo Predonzani     - [email protected]
* @author Angelo Lupo          - [email protected]
* @author Giampiero Granatella - [email protected]
* @author Alessio Stalla       - [email protected]
*/
public class PageactionsModule implements Module {
    public static final String copyright =
            "Copyright (C) 2005-2017 ManyDesigns srl";

    //**************************************************************************
    // Fields
    //**************************************************************************

    @Inject(BaseModule.SERVLET_CONTEXT)
    public ServletContext servletContext;

    @Inject(BaseModule.PORTOFINO_CONFIGURATION)
    public Configuration configuration;

    @Inject(BaseModule.APPLICATION_DIRECTORY)
    public File applicationDirectory;

    @Inject(BaseModule.GROOVY_SCRIPT_ENGINE)
    public GroovyScriptEngine groovyScriptEngine;

    @Inject(BaseModule.GROOVY_CLASS_PATH)
    public File groovyClasspath;

    @Inject(BaseModule.CACHE_RESET_LISTENER_REGISTRY)
    public CacheResetListenerRegistry cacheResetListenerRegistry;

    protected EnvironmentLoader environmentLoader = new EnvironmentLoader();

    protected CacheManager cacheManager;

    protected ModuleStatus status = ModuleStatus.CREATED;

    //**************************************************************************
    // Constants
    //**************************************************************************

    public static final String PAGES_DIRECTORY = "PAGES_DIRECTORY";
    public static final String EHCACHE_MANAGER = "portofino.ehcache.manager";
    public static final String PAGE_ACTIONS_REGISTRY =
            "com.manydesigns.portofino.pageactions.registry.PageActionRegistry";
    public static final String TEMPLATES_REGISTRY =
            "com.manydesigns.portofino.pageactions.templates.registry";

    //**************************************************************************
    // Logging
    //**************************************************************************

    public static final Logger logger =
            LoggerFactory.getLogger(PageactionsModule.class);

    @Override
    public String getModuleVersion() {
        return ModuleRegistry.getPortofinoVersion();
    }

    @Override
    public int getMigrationVersion() {
        return 1;
    }

    @Override
    public double getPriority() {
        return 10;
    }

    @Override
    public String getId() {
        return "pageactions";
    }

    @Override
    public String getName() {
        return "Pageactions";
    }

    @Override
    public int install() {
        return 1;
    }

    @Override
    public void init() {
        logger.debug("Initializing dispatcher");
        DispatcherLogic.init(configuration);

        logger.info("Initializing ehcache service");
        cacheManager = CacheManager.newInstance();
        servletContext.setAttribute(EHCACHE_MANAGER, cacheManager);

        File pagesDirectory = new File(applicationDirectory, "pages");
        logger.info("Pages directory: " + pagesDirectory);
        ElementsFileUtils.ensureDirectoryExistsAndWarnIfNotWritable(pagesDirectory);

        if(configuration.getBoolean(PortofinoProperties.GROOVY_PRELOAD_PAGES, false)) {
            logger.info("Preloading pages");
            preloadPageActions(pagesDirectory);
        }
        if(configuration.getBoolean(PortofinoProperties.GROOVY_PRELOAD_CLASSES, false)) {
            logger.info("Preloading Groovy classes");
            preloadGroovyClasses(groovyClasspath);
        }
        servletContext.setAttribute(PAGES_DIRECTORY, pagesDirectory);

        logger.debug("Creating pageactions registry");
        PageActionRegistry pageActionRegistry = new PageActionRegistry();
        pageActionRegistry.register(ActivityStreamAction.class);
        pageActionRegistry.register(CustomAction.class);
        pageActionRegistry.register(FormAction.class);
        pageActionRegistry.register(TableFormAction.class);
        pageActionRegistry.register(TextAction.class);
        servletContext.setAttribute(PAGE_ACTIONS_REGISTRY, pageActionRegistry);

        servletContext.setAttribute(TEMPLATES_REGISTRY, new TemplateRegistry());

        cacheResetListenerRegistry.getCacheResetListeners().add(new ConfigurationCacheResetListener());

        status = ModuleStatus.ACTIVE;
    }

    protected void preloadPageActions(File directory) {
        for(File file : directory.listFiles()) {
            logger.debug("visit {}", file);
            if(file.isDirectory()) {
                if(!file.equals(directory) && !file.equals(directory.getParentFile())) {
                    preloadPageActions(file);
                }
            } else if("action.groovy".equals(file.getName())) {
                logger.debug("Preloading page: {}", file);
                try {
                    Class clazz = DispatcherLogic.getActionClass(configuration, directory);
                    clazz.newInstance();
                } catch(Throwable t) {
                    logger.warn("PageAction preload failed for page " + file.getAbsolutePath(), t);
                }
            }
        }
    }

    protected void preloadGroovyClasses(File directory) {
        for(File file : directory.listFiles()) {
            logger.debug("visit {}", file);
            if(file.isDirectory()) {
                if(!file.equals(directory) && !file.equals(directory.getParentFile())) {
                    preloadGroovyClasses(file);
                }
            } else {
                String scriptName = file.toURI().toString();
                logger.debug("Preloading " + scriptName);
                try {
                    groovyScriptEngine.loadScriptByName(scriptName);
                } catch(Throwable t) {
                    logger.warn("Groovy class preload failed for " + scriptName, t);
                }
            }
        }
    }

    @Override
    public void start() {
        logger.info("Initializing Shiro environment");
        WebEnvironment environment = environmentLoader.initEnvironment(servletContext);
        RealmSecurityManager rsm = (RealmSecurityManager) environment.getWebSecurityManager();
        logger.debug("Creating SecurityGroovyRealm");
        try {
            String securityGroovy = new File(groovyClasspath, "Security.groovy").toURI().toString();
            logger.debug("Security.groovy URL: {}", securityGroovy);
            SecurityGroovyRealm realm = new SecurityGroovyRealm(groovyScriptEngine, securityGroovy, servletContext);
            LifecycleUtils.init(realm);
            rsm.setRealm(realm);
            status = ModuleStatus.STARTED;
        } catch (Exception  e) {
            logger.error("Security.groovy not found or invalid; installing dummy realm", e);
            SimpleAccountRealm realm = new SimpleAccountRealm();
            LifecycleUtils.init(realm);
            rsm.setRealm(realm);
            status = ModuleStatus.FAILED;
        }
    }

    @Override
    public void stop() {
        status = ModuleStatus.STOPPED;
    }

    @Override
    public void destroy() {
        logger.info("Destroying Shiro environment...");
        environmentLoader.destroyEnvironment(servletContext);
        logger.info("Shutting down cache...");
        cacheManager.shutdown();
        status = ModuleStatus.DESTROYED;
    }

    @Override
    public ModuleStatus getStatus() {
        return status;
    }

    private static class ConfigurationCacheResetListener implements CacheResetListener {
        @Override
        public void handleReset(CacheResetEvent e) {
            DispatcherLogic.clearConfigurationCache();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy