org.geoserver.script.ScriptManager.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.script.ScriptManager.java

Source

/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved.
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.script;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;

import org.apache.commons.io.FilenameUtils;
import org.geoserver.config.GeoServerDataDirectory;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.script.app.AppHook;
import org.geoserver.script.function.FunctionHook;
import org.geoserver.script.wfs.WfsTxHook;
import org.geoserver.script.wps.WpsHook;
import org.geotools.util.logging.Logging;
import org.springframework.beans.factory.InitializingBean;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

/**
 * Facade for the scripting subsystem, providing methods for obtaining script context and managing
 * scripts. 
 * 
 * @author Justin Deoliveira, OpenGeo
 *
 */
public class ScriptManager implements InitializingBean {

    static Logger LOGGER = Logging.getLogger(ScriptManager.class);

    GeoServerDataDirectory dataDir;
    ScriptEngineManager engineMgr;

    volatile List<ScriptPlugin> plugins;
    Cache<Long, ScriptSession> sessions;

    public ScriptManager(GeoServerDataDirectory dataDir) {
        this.dataDir = dataDir;
        engineMgr = new ScriptEngineManager();
        sessions = CacheBuilder.newBuilder().maximumSize(10).expireAfterAccess(10, TimeUnit.MINUTES).build();
    }

    public GeoServerDataDirectory getDataDirectory() {
        return dataDir;
    }

    /**
     * Returns the underlying engine manager used to create and manage script engines.
     */
    public ScriptEngineManager getEngineManager() {
        return engineMgr;
    }

    /**
     * Returns list of available script plugins.
     */
    public List<ScriptPlugin> getPlugins() {
        return plugins();
    }

    /**
     * The root "scripts" directory, located directly under the root of the data directory. 
     */
    public File getScriptRoot() throws IOException {
        return dataDir.findOrCreateDir("scripts");
    }

    /**
     * Finds a script directory located at the specified path, returning <code>null</code> if no 
     * such directory exists.
     * 
     */
    public File findScriptDir(String path) throws IOException {
        File f = new File(getScriptRoot(), path);
        if (f.exists() && f.isDirectory()) {
            return f;
        }
        return null;
    }

    /**
     * Finds a script directory located at the specified path, creating the directory if it does not
     * already exist.
     * 
     */
    public File findOrCreateScriptDir(String path) throws IOException {
        File f = findScriptDir(path);
        if (f != null) {
            return f;
        }

        f = new File(getScriptRoot(), path);
        if (!f.mkdirs()) {
            throw new IOException("Unable to create directory " + f.getPath());
        }

        return f;
    }

    /**
     * Finds a script file with the specified filename located  in the specified directory path, 
     * returning <code>null</code> if the file does not exist.
     */
    public File findScriptFile(String dirPath, String filename) throws IOException {
        return findScriptFile(dirPath + File.separator + filename);
    }

    /**
     * Finds a script file at the specified path, returning <code>null</code> if the file does not 
     * exist.
     */
    public File findScriptFile(String path) throws IOException {
        File f = new File(getScriptRoot(), path);
        return f.exists() ? f : null;
    }

    /**
     * The root "apps" directory, located directly under {@link #getScriptRoot()}.
     */
    public File getAppRoot() throws IOException {
        return dataDir.findOrCreateDir("scripts", "apps");
    }

    /**
     * Finds a named app dir, returning <code>null</code> if the directory does not exist.
     */
    public File findAppDir(String app) throws IOException {
        return findScriptDir("apps" + File.separator + app);
    }

    /**
     * Finds a named app dir, creating if it does not already exist.
     */
    public File findOrCreateAppDir(String app) throws IOException {
        return findOrCreateScriptDir("apps" + File.separator + app);
    }

    /**
     * The root "wps" directory, located directly under {@link #getScriptRoot()} 
     */
    public File getWpsRoot() throws IOException {
        return dataDir.findOrCreateDir("scripts", "wps");
    }

    /**
     * The root "wfs/tx" directory, located directly under {@link #getScriptRoot()} 
     */
    public File getWfsTxRoot() throws IOException {
        return dataDir.findOrCreateDir("scripts", "wfs", "tx");
    }

    /**
     * The root "function" directory, located directly under {@link #getScriptRoot()} 
     */
    public File getFunctionRoot() throws IOException {
        return dataDir.findOrCreateDir("scripts", "function");
    }

    public File getLibRoot(String ext) throws IOException {
        return findOrCreateScriptDir("lib/" + ext);
    }

    /**
     * Creates a new script engine for the specified script file.
     */
    public ScriptEngine createNewEngine(File script) {
        return createNewEngine(ext(script));
    }

    /**
     * Creates a new script engine for the specified file extension.
     */
    public ScriptEngine createNewEngine(String ext) {
        if (ext == null) {
            return null;
        }
        return initEngine(engineMgr.getEngineByExtension(ext));
    }

    public ScriptSession createNewSession(String ext) {
        ScriptSession session = new ScriptSession(createNewEngine(ext), ext);
        sessions.put(session.getId(), session);
        return session;
    }

    public ScriptSession findSession(long id) {
        return sessions.getIfPresent(id);
    }

    public List<ScriptSession> findSessions(String ext) {
        List<ScriptSession> sids = new ArrayList<ScriptSession>();
        for (Map.Entry<Long, ScriptSession> e : sessions.asMap().entrySet()) {
            if (ext != null && !ext.equalsIgnoreCase(e.getValue().getExtension())) {
                continue;
            }

            sids.add(e.getValue());
        }

        return sids;
    }

    /*
     * Initializes a new script engine by looking up the plugin matching the engines factory. 
     */
    ScriptEngine initEngine(ScriptEngine engine) {
        if (engine == null) {
            return null;
        }

        for (ScriptPlugin plugin : plugins()) {
            if (plugin.getScriptEngineFactoryClass().isInstance(engine.getFactory())) {
                plugin.initScriptEngine(engine);
                break;
            }
        }

        return engine;
    }

    /**
     * Looks up the app hook for the specified script returning <code>null</code> if no such 
     * hook can be found.
     * <p>
     * This method works by looking up all {@link ScriptPlugin} instances and delegating to 
     * {@link ScriptPlugin#createAppHook()}.
     * </p>
     */
    public AppHook lookupAppHook(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.createAppHook() : new AppHook(null);
    }

    /**
     * Looks up the wps hook for the specified script returning <code>null</code> if no such 
     * hook can be found.
     * <p>
     * This method works by looking up all {@link ScriptPlugin} instances and delegating to 
     * {@link ScriptPlugin#createWpsHook()}.
     * </p>
     */
    public WpsHook lookupWpsHook(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.createWpsHook() : null;
    }

    /**
     * Looks up the filter hook for the specified script returning <code>null</code> if no such 
     * hook can be found.
     * <p>
     * This method works by looking up all {@link ScriptPlugin} instances and delegating to 
     * {@link ScriptPlugin#createFunctionHook()}.
     * </p>
     */
    public FunctionHook lookupFilterHook(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.createFunctionHook() : new FunctionHook(null);
    }

    /**
     * Looks up the wfs tx hook for the specified script returning <code>null</code> if no such 
     * hook can be found.
     * <p>
     * This method works by looking up all {@link ScriptPlugin} instances and delegating to 
     * {@link ScriptPlugin#createWfsTxHook()}.
     * </p>
     */
    public WfsTxHook lookupWfsTxHook(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.createWfsTxHook() : new WfsTxHook(null);
    }

    public String lookupPluginId(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.getId() : null;
    }

    public String lookupPluginDisplayName(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.getDisplayName() : null;
    }

    public String lookupPluginEditorMode(File script) {
        ScriptPlugin p = plugin(script);
        return p != null ? p.getEditorMode() : null;
    }

    public boolean hasEngineForExtension(String ext) {
        for (ScriptEngineFactory f : engineMgr.getEngineFactories()) {
            if (f.getExtensions().contains(ext)) {
                return true;
            }
        }
        return false;
    }

    /*
     * Looks up all {@link ScriptPlugin} instances in the application context.
     */
    List<ScriptPlugin> plugins() {
        if (plugins == null) {
            synchronized (this) {
                if (plugins == null) {
                    plugins = GeoServerExtensions.extensions(ScriptPlugin.class);
                    for (ScriptPlugin plugin : plugins) {
                        try {
                            plugin.init(this);
                        } catch (Exception e) {
                            LOGGER.log(Level.SEVERE, "Error initializing plugin", e);
                        }
                    }
                }
            }
        }
        return plugins;
    }

    /*
     * Looks up the plugin for the specified script.
     */
    ScriptPlugin plugin(File script) {
        String ext = ext(script);

        for (ScriptPlugin plugin : plugins()) {
            if (ext.equalsIgnoreCase(plugin.getExtension())) {
                return plugin;
            }
        }

        return null;
    }

    /*
     * Helper method for extracting extension from filename throwing exception if the file has no
     * extension. 
     */
    String ext(File script) throws IllegalArgumentException {
        String ext = FilenameUtils.getExtension(script.getName());
        if (ext == null) {
            throw new IllegalArgumentException(script.getName() + " has no extension");
        }
        return ext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        plugins();
    }
}