blob: c7bc7667213677e785facc9a72ac821464fe6823 [file] [log] [blame]
/*
* 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.util.Collection;
import java.util.List;
import javax.script.ScriptEngine;
import org.apache.sling.api.adapter.AdapterFactory;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.commons.mime.MimeTypeProvider;
import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
import org.apache.sling.scripting.api.ScriptCache;
import org.apache.sling.scripting.core.impl.jsr223.SlingScriptEngineManager;
import org.jetbrains.annotations.NotNull;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* AdapterFactory that adapts Resources to the DefaultSlingScript servlet, which
* executes the Resources as scripts.
*/
@Component(
service = {
AdapterFactory.class,
MimeTypeProvider.class
},
property = {
Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
Constants.SERVICE_DESCRIPTION + "=Default SlingScriptResolver",
"adaptables=org.apache.sling.api.resource.Resource",
"adapters=org.apache.sling.api.scripting.SlingScript",
"adapters=javax.servlet.Servlet",
"adapter.condition=If the resource's path ends in an extension registered by a script engine."
}
)
public class SlingScriptAdapterFactory implements AdapterFactory, MimeTypeProvider {
private BundleContext bundleContext;
/** The context string to use to select BindingsValuesProviders */
public static final String BINDINGS_CONTEXT = BindingsValuesProvider.DEFAULT_CONTEXT;
/**
* The service cache for script execution.
*/
private ServiceCache serviceCache;
/**
* The script engine manager.
*/
@Reference
private SlingScriptEngineManager scriptEngineManager;
@Reference
private volatile SlingScriptEnginePicker scriptEnginePicker;
/**
* The BindingsValuesProviderTracker
*/
@Reference
private BindingsValuesProvidersByContext bindingsValuesProviderTracker;
@Reference
private ScriptCache scriptCache;
// ---------- AdapterFactory -----------------------------------------------
@Override
@SuppressWarnings("unchecked")
public <AdapterType> AdapterType getAdapter(@NotNull final Object adaptable, @NotNull final Class<AdapterType> type) {
final Resource resource = (Resource) adaptable;
final String path = resource.getPath();
final String extension = path.substring(path.lastIndexOf('.') + 1);
final List<ScriptEngine> engines = scriptEngineManager.getEnginesByExtension(extension);
final ScriptEngine engine;
if (engines.size() == 0) {
return null;
} else if (engines.size() == 1) {
engine = engines.get(0);
} else {
engine = scriptEnginePicker.pickScriptEngine(engines, resource, extension);
}
if (engine != null) {
final Collection<BindingsValuesProvider> bindingsValuesProviders = bindingsValuesProviderTracker.getBindingsValuesProviders(engine.getFactory(), BINDINGS_CONTEXT);
// unchecked cast
return (AdapterType) new DefaultSlingScript(this.bundleContext, resource, engine, bindingsValuesProviders, this.serviceCache, scriptCache);
}
return null;
}
// ---------- MimeTypeProvider
/**
* Returns the first MIME type entry of the supported MIME types of a
* ScriptEngineFactory which is registered for the extension of the given
* name. If no ScriptEngineFactory is registered for the given extension or
* the registered ScriptEngineFactory is not registered for a MIME type,
* this method returns <code>null</code>.
*
* @param name The name whose extension is to be mapped to a MIME type. The
* extension is the string after the last dot in the name. If the
* name contains no dot, the entire name is considered the
* extension.
*/
@Override
public String getMimeType(String name) {
name = name.substring(name.lastIndexOf('.') + 1);
ScriptEngine se = scriptEngineManager.getEngineByExtension(name);
if (se != null) {
List<?> mimeTypes = se.getFactory().getMimeTypes();
if (mimeTypes != null && mimeTypes.size() > 0) {
return String.valueOf(mimeTypes.get(0));
}
}
return null;
}
/**
* Returns the first extension entry of the supported extensions of a
* ScriptEngineFactory which is registered for the given MIME type. If no
* ScriptEngineFactory is registered for the given MIME type or the
* registered ScriptEngineFactory is not registered for an extensions, this
* method returns <code>null</code>.
*
* @param mimeType The MIME type to be mapped to an extension.
*/
@Override
public String getExtension(String mimeType) {
ScriptEngine se = scriptEngineManager.getEngineByMimeType(mimeType);
if (se != null) {
List<?> extensions = se.getFactory().getExtensions();
if (extensions != null && extensions.size() > 0) {
return String.valueOf(extensions.get(0));
}
}
return null;
}
// ---------- SCR integration ----------------------------------------------
protected void activate(ComponentContext context) {
bundleContext = context.getBundleContext();
this.serviceCache = new ServiceCache(this.bundleContext);
}
protected void deactivate(ComponentContext context) {
this.serviceCache.dispose();
this.serviceCache = null;
this.bundleContext = null;
}
}