Prepare automation for ScriptEngineFactory projects (#1251)

These changes prepare for custom ScriptEngineFactories and does not
include any breaking changes.
* Moved AbstractScriptEngineFactory out of internal so that it can be
used by custom factories
* Modified ScriptEngineModuleTypeProvider to include engines from custom
factories
* Cleaned up some logging

Signed-off-by: Scott Rushworth <openhab@5iver.com>
This commit is contained in:
Scott Rushworth 2019-12-11 02:35:01 -05:00 committed by Kai Kreuzer
parent 57c719e187
commit 218bb79dfd
5 changed files with 43 additions and 25 deletions

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation.module.script.internal;
package org.openhab.core.automation.module.script;
import java.util.ArrayList;
import java.util.Collections;
@ -22,7 +22,6 @@ import javax.script.ScriptEngine;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -34,7 +33,7 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault
public abstract class AbstractScriptEngineFactory implements ScriptEngineFactory {
protected final Logger logger = LoggerFactory.getLogger(AbstractScriptEngineFactory.class);
protected final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public List<String> getScriptTypes() {
@ -65,5 +64,4 @@ public abstract class AbstractScriptEngineFactory implements ScriptEngineFactory
}
return scriptEngine;
}
}

View File

@ -13,6 +13,7 @@
package org.openhab.core.automation.module.script.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.automation.module.script.AbstractScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.osgi.service.component.annotations.Component;

View File

@ -24,6 +24,7 @@ import javax.script.ScriptEngine;
import javax.script.ScriptException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.automation.module.script.AbstractScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.osgi.service.component.annotations.Component;

View File

@ -70,12 +70,20 @@ public class ScriptEngineManagerImpl implements ScriptEngineManager {
this.genericSupport.put(scriptType, engineFactory);
}
}
logger.debug("Added {}", engineFactory.getClass().getSimpleName());
for (javax.script.ScriptEngineFactory f : ScriptEngineFactory.ENGINE_MANAGER.getEngineFactories()) {
logger.debug(
"ScriptEngineFactory details for {} ({}): supports {} ({}) with file extensions {}, names {}, and mimetypes {}",
f.getEngineName(), f.getEngineVersion(), f.getLanguageName(), f.getLanguageVersion(),
f.getExtensions(), f.getNames(), f.getMimeTypes());
if (!engineFactory.getScriptTypes().isEmpty()) {
ScriptEngine scriptEngine = engineFactory.createScriptEngine(engineFactory.getScriptTypes().get(0));
if (scriptEngine != null) {
javax.script.ScriptEngineFactory factory = scriptEngine.getFactory();
logger.debug(
"Initialized a {} ScriptEngineFactory for {} ({}): supports {} ({}) with file extensions {}, names {}, and mimetypes {}",
(isCustomFactory(engineFactory)) ? "custom" : "generic", factory.getEngineName(),
factory.getEngineVersion(), factory.getLanguageName(), factory.getLanguageVersion(),
factory.getExtensions(), factory.getNames(), factory.getMimeTypes());
} else {
logger.trace("addScriptEngineFactory: engine was null");
}
} else {
logger.trace("addScriptEngineFactory: scriptTypes was empty");
}
}
@ -126,7 +134,7 @@ public class ScriptEngineManagerImpl implements ScriptEngineManager {
logger.debug("Added ScriptEngine for language '{}' with identifier: {}", scriptType,
engineIdentifier);
} else {
logger.error("ScriptEngine for language '{}' could not be found for identifier: {}", scriptType,
logger.error("ScriptEngine for language '{}' could not be created for identifier: {}", scriptType,
engineIdentifier);
}
} catch (Exception ex) {
@ -193,7 +201,7 @@ public class ScriptEngineManagerImpl implements ScriptEngineManager {
/**
* This method will find and return a {@link ScriptEngineFactory} capable of executing a script of the given type,
* if one exists.
* if one exists. Custom ScriptEngineFactories are preferred over generic.
*
* @param scriptType a file extension (script) or MimeType (ScriptAction or ScriptCondition)
* @return {@link ScriptEngineFactory} or null

View File

@ -16,11 +16,13 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang.StringUtils;
import javax.script.ScriptEngine;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder;
@ -53,7 +55,7 @@ import org.slf4j.LoggerFactory;
public class ScriptModuleTypeProvider implements ModuleTypeProvider {
private final Logger logger = LoggerFactory.getLogger(ScriptModuleTypeProvider.class);
private final List<ParameterOption> parameterOptions = new CopyOnWriteArrayList<>();
private final Map<String, String> parameterOptions = new TreeMap<>();
@SuppressWarnings("unchecked")
@Override
@ -97,10 +99,14 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
* @return a list of {#link ConfigurationDescriptionParameter}s
*/
private List<ConfigDescriptionParameter> getConfigDescriptions(Locale locale) {
List<ParameterOption> parameterOptionsList = new ArrayList<>();
for (Map.Entry<String, String> entry : parameterOptions.entrySet()) {
parameterOptionsList.add(new ParameterOption(entry.getKey(), entry.getValue()));
}
final ConfigDescriptionParameter scriptType = ConfigDescriptionParameterBuilder.create("type", Type.TEXT)
.withRequired(true).withReadOnly(true).withMultiple(false).withLabel("Script Type")
.withDescription("the scripting language used").withOptions(parameterOptions).withLimitToOptions(true)
.build();
.withDescription("the scripting language used").withOptions(parameterOptionsList)
.withLimitToOptions(true).build();
final ConfigDescriptionParameter script = ConfigDescriptionParameterBuilder.create("script", Type.TEXT)
.withRequired(true).withReadOnly(false).withMultiple(false).withLabel("Script").withContext("script")
.withDescription("the script to execute").build();
@ -128,26 +134,30 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
}
/**
* As {@link ScriptEngineFactory}s are added/changed, this method will create the {@link ParameterOption}s
* As {@link ScriptEngineFactory}s are added/removed, this method will create the {@link ParameterOption}s
* that are available when selecting a script type in a ScriptActionType or ScriptConditionType.
*/
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void setScriptEngineFactory(ScriptEngineFactory engineFactory) {
parameterOptions.clear();
for (javax.script.ScriptEngineFactory f : ScriptEngineFactory.ENGINE_MANAGER.getEngineFactories()) {
String languageName = String.format("%s (%s)", StringUtils.capitalize(f.getLanguageName()),
f.getLanguageVersion());
ScriptEngine scriptEngine = engineFactory.createScriptEngine(engineFactory.getScriptTypes().get(0));
if (scriptEngine != null) {
List<String> mimeTypes = new ArrayList<>();
mimeTypes.addAll(f.getMimeTypes());
javax.script.ScriptEngineFactory factory = scriptEngine.getFactory();
String languageName = String.format("%s (%s)",
factory.getLanguageName().substring(0, 1).toUpperCase() + factory.getLanguageName().substring(1),
factory.getLanguageVersion());
mimeTypes.addAll(factory.getMimeTypes());
String preferredMimeType = mimeTypes.get(0);
mimeTypes.removeIf(mimeType -> !mimeType.contains("application") || mimeType.contains("x-"));
if (!mimeTypes.isEmpty()) {
preferredMimeType = mimeTypes.get(0);
}
parameterOptions.add(new ParameterOption(preferredMimeType, languageName));
parameterOptions.put(preferredMimeType, languageName);
logger.trace("ParameterOptions: {}", parameterOptions);
} else {
logger.trace("setScriptEngineFactory: engine was null");
}
logger.trace("ParameterOptions: {}", parameterOptions);
}
public void unsetScriptEngineFactory(ScriptEngineFactory scriptEngineFactory) {