Package org.apache.sling.scripting.core.impl

Source Code of org.apache.sling.scripting.core.impl.SlingScriptAdapterFactory

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.sling.scripting.core.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

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

import org.apache.sling.api.adapter.AdapterFactory;
import org.apache.sling.api.resource.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*  AdapterFactory that adapts Resources to the DefaultSlingScript servlet,
*  which executes the Resources as scripts.
*
* @scr.component metatype="no"
* @scr.property name="service.vendor" value="The Apache Software Foundation"
* @scr.property name="service.description" value="Default SlingScriptResolver"
*
* @scr.property name="adaptables"
*               value="org.apache.sling.api.resource.Resource";
* @scr.property name="adapters"
*               values.0="org.apache.sling.api.scripting.SlingScript"
*               values.1="javax.servlet.Servlet"
*
* @scr.service interface="org.apache.sling.api.adapter.AdapterFactory"
*
* @scr.reference name="ScriptEngineFactory"
*                interface="javax.script.ScriptEngineFactory"
*                cardinality="0..n" policy="dynamic"
*/
public class SlingScriptAdapterFactory implements AdapterFactory,
        BundleListener {

    private static final Logger log = LoggerFactory.getLogger(SlingScriptAdapterFactory.class);

    /**
     * jcr:encoding
     */
    public static final String JCR_ENCODING = "jcr:encoding";

    private static final String ENGINE_FACTORY_SERVICE = "META-INF/services/"
        + ScriptEngineFactory.class.getName();

    private ScriptEngineManager scriptEngineManager;

    private List<Bundle> engineSpiBundles = new LinkedList<Bundle>();

    private List<ScriptEngineFactory> engineSpiServices = new LinkedList<ScriptEngineFactory>();

    private BundleContext bundleContext;

    //---------- AdapterFactory -----------------------------------------------

    @SuppressWarnings("unchecked")
    public <AdapterType> AdapterType getAdapter(Object adaptable,
            Class<AdapterType> type) {

        Resource resource = (Resource) adaptable;
        String path = resource.getPath();
        String ext = path.substring(path.lastIndexOf('.') + 1);

        ScriptEngine engine = getScriptEngineManager().getEngineByExtension(
            ext);
        if (engine != null) {
            // unchecked cast
            return (AdapterType) new DefaultSlingScript(this.bundleContext, resource, engine);
        }

        return null;
    }

    private ScriptEngineManager getScriptEngineManager() {
        if (scriptEngineManager == null) {

            // create (empty) script engine manager
            ClassLoader loader = getClass().getClassLoader();
            ScriptEngineManager tmp = new ScriptEngineManager(loader);

            // register script engines from bundles
            for (Bundle bundle : engineSpiBundles) {
                registerFactories(tmp, bundle);
            }

            // register script engines from registered services
            for (ScriptEngineFactory factory : engineSpiServices) {
                registerFactory(tmp, factory);
            }

            scriptEngineManager = tmp;
        }
        return scriptEngineManager;
    }

    private void registerFactories(ScriptEngineManager mgr, Bundle bundle) {
        URL url = bundle.getEntry(ENGINE_FACTORY_SERVICE);
        InputStream ins = null;
        try {
            ins = url.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                ins));
            String line;
            while ((line = reader.readLine()) != null) {
                try {
                    @SuppressWarnings("unchecked")
                    Class<ScriptEngineFactory> clazz = bundle.loadClass(line);
                    ScriptEngineFactory spi = clazz.newInstance();
                    registerFactory(mgr, spi);
                } catch (Throwable t) {
                    log.error("Cannot register ScriptEngineFactory " + line, t);
                }
            }
        } catch (IOException ioe) {
        } finally {
            if (ins != null) {
                try {
                    ins.close();
                } catch (IOException ioe) {
                }
            }
        }
    }

    private void registerFactory(ScriptEngineManager mgr,
            ScriptEngineFactory factory) {
        log.info("Adding ScriptEngine {}, {} for language {}, {}",
            new Object[] { factory.getEngineName(), factory.getEngineVersion(),
                factory.getLanguageName(), factory.getLanguageVersion() });

        for (Object ext : factory.getExtensions()) {
            mgr.registerEngineExtension((String) ext, factory);
        }

        for (Object mime : factory.getMimeTypes()) {
            mgr.registerEngineMimeType((String) mime, factory);
        }

        for (Object name : factory.getNames()) {
            mgr.registerEngineName((String) name, factory);
        }
    }

    // ---------- BundleListener interface -------------------------------------

    public void bundleChanged(BundleEvent event) {
        if (event.getType() == BundleEvent.STARTED
            && event.getBundle().getEntry(ENGINE_FACTORY_SERVICE) != null) {

            engineSpiBundles.add(event.getBundle());
            scriptEngineManager = null;

        } else if (event.getType() == BundleEvent.STOPPED
            && engineSpiBundles.remove(event.getBundle())) {

            scriptEngineManager = null;

        }
    }

    // ---------- SCR integration ----------------------------------------------

    protected void activate(ComponentContext context) {
        this.bundleContext = context.getBundleContext();
        this.bundleContext.addBundleListener(this);

        Bundle[] bundles = this.bundleContext.getBundles();
        for (Bundle bundle : bundles) {
            if (bundle.getState() == Bundle.ACTIVE
                && bundle.getEntry(ENGINE_FACTORY_SERVICE) != null) {
                engineSpiBundles.add(bundle);
            }
        }
    }

    protected void deactivate(ComponentContext context) {
        context.getBundleContext().removeBundleListener(this);

        engineSpiBundles.clear();
        engineSpiServices.clear();
        scriptEngineManager = null;
        this.bundleContext = null;
    }

    protected void bindScriptEngineFactory(
            ScriptEngineFactory scriptEngineFactory) {
        engineSpiServices.add(scriptEngineFactory);
        scriptEngineManager = null;
    }

    protected void unbindScriptEngineFactory(
            ScriptEngineFactory scriptEngineFactory) {
        engineSpiServices.remove(scriptEngineFactory);
        scriptEngineManager = null;
    }

}
TOP

Related Classes of org.apache.sling.scripting.core.impl.SlingScriptAdapterFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.