diff --git a/pom.xml b/pom.xml index 5beca9134..a9feb2d4e 100644 --- a/pom.xml +++ b/pom.xml @@ -1445,13 +1445,6 @@ 4.2.0 - - - org.codehaus.groovy - groovy - ${groovy.version} - - org.dbflute.tomcat @@ -1532,5 +1525,11 @@ + + org.codehaus.groovy + groovy + ${groovy.version} + test + diff --git a/src/main/java/org/codelibs/fess/Constants.java b/src/main/java/org/codelibs/fess/Constants.java index d764393c8..9e17c864a 100644 --- a/src/main/java/org/codelibs/fess/Constants.java +++ b/src/main/java/org/codelibs/fess/Constants.java @@ -469,4 +469,6 @@ public class Constants extends CoreLibConstants { public static final String EXECUTE_TYPE_PYTHON = "python"; public static final String EXECUTE_TYPE_SUGGEST = "suggest"; + + public static final String DEFAULT_SCRIPT = "groovy"; } diff --git a/src/main/java/org/codelibs/fess/crawler/transformer/FessTransformer.java b/src/main/java/org/codelibs/fess/crawler/transformer/FessTransformer.java index 89e593318..5aa8e537a 100644 --- a/src/main/java/org/codelibs/fess/crawler/transformer/FessTransformer.java +++ b/src/main/java/org/codelibs/fess/crawler/transformer/FessTransformer.java @@ -33,7 +33,6 @@ import org.codelibs.fess.crawler.entity.UrlQueue; import org.codelibs.fess.crawler.util.CrawlingParameterUtil; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.util.ComponentUtil; -import org.codelibs.fess.util.GroovyUtil; public interface FessTransformer { @@ -158,7 +157,7 @@ public interface FessTransformer { return StringUtil.EMPTY; } - return GroovyUtil.evaluate(template, paramMap); + return ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(template, paramMap); } default int getMaxSiteLength() { diff --git a/src/main/java/org/codelibs/fess/ds/AbstractDataStore.java b/src/main/java/org/codelibs/fess/ds/AbstractDataStore.java index f3aa080b2..521103840 100644 --- a/src/main/java/org/codelibs/fess/ds/AbstractDataStore.java +++ b/src/main/java/org/codelibs/fess/ds/AbstractDataStore.java @@ -36,7 +36,6 @@ import org.codelibs.fess.helper.CrawlingInfoHelper; import org.codelibs.fess.helper.SystemHelper; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.util.ComponentUtil; -import org.codelibs.fess.util.GroovyUtil; public abstract class AbstractDataStore implements DataStore { @@ -130,7 +129,7 @@ public abstract class AbstractDataStore implements DataStore { return paramMap.get(template); } - return GroovyUtil.evaluate(template, paramMap); + return ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(template, paramMap); } protected long getReadInterval(final Map paramMap) { diff --git a/src/main/java/org/codelibs/fess/exception/ScriptEngineException.java b/src/main/java/org/codelibs/fess/exception/ScriptEngineException.java new file mode 100644 index 000000000..0807a6876 --- /dev/null +++ b/src/main/java/org/codelibs/fess/exception/ScriptEngineException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2021 CodeLibs Project and the Others. + * + * Licensed 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.codelibs.fess.exception; + +public class ScriptEngineException extends FessSystemException { + + private static final long serialVersionUID = 1L; + + public ScriptEngineException(final String message) { + super(message); + } + + public ScriptEngineException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/codelibs/fess/helper/PathMappingHelper.java b/src/main/java/org/codelibs/fess/helper/PathMappingHelper.java index 08ae49569..55b204f36 100644 --- a/src/main/java/org/codelibs/fess/helper/PathMappingHelper.java +++ b/src/main/java/org/codelibs/fess/helper/PathMappingHelper.java @@ -32,7 +32,6 @@ import org.codelibs.fess.es.config.exbhv.PathMappingBhv; import org.codelibs.fess.es.config.exentity.PathMapping; import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.DocumentUtil; -import org.codelibs.fess.util.GroovyUtil; import org.lastaflute.di.core.exception.ComponentNotFoundException; import org.lastaflute.di.core.factory.SingletonLaContainerFactory; import org.lastaflute.web.util.LaRequestUtil; @@ -164,7 +163,8 @@ public class PathMappingHelper { final Map paramMap = new HashMap<>(); paramMap.put("url", u); paramMap.put("matcher", m); - final Object value = GroovyUtil.evaluate(template, paramMap); + final Object value = + ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(template, paramMap); if (value == null) { return u; } diff --git a/src/main/java/org/codelibs/fess/helper/PluginHelper.java b/src/main/java/org/codelibs/fess/helper/PluginHelper.java index 04762a42d..34c3e7669 100644 --- a/src/main/java/org/codelibs/fess/helper/PluginHelper.java +++ b/src/main/java/org/codelibs/fess/helper/PluginHelper.java @@ -374,7 +374,7 @@ public class PluginHelper { } public enum ArtifactType { - DATA_STORE("fess-ds"), THEME("fess-theme"), INGEST("fess-ingest"), UNKNOWN("jar"); + DATA_STORE("fess-ds"), THEME("fess-theme"), INGEST("fess-ingest"), SCRIPT("fess-script"), WEBAPP("fess-webapp"), UNKNOWN("jar"); private final String id; @@ -396,6 +396,12 @@ public class PluginHelper { if (name.startsWith(INGEST.getId())) { return INGEST; } + if (name.startsWith(SCRIPT.getId())) { + return SCRIPT; + } + if (name.startsWith(WEBAPP.getId())) { + return WEBAPP; + } return UNKNOWN; } } diff --git a/src/main/java/org/codelibs/fess/indexer/DocBoostMatcher.java b/src/main/java/org/codelibs/fess/indexer/DocBoostMatcher.java index 68e132539..67b5135dc 100644 --- a/src/main/java/org/codelibs/fess/indexer/DocBoostMatcher.java +++ b/src/main/java/org/codelibs/fess/indexer/DocBoostMatcher.java @@ -17,8 +17,9 @@ package org.codelibs.fess.indexer; import java.util.Map; +import org.codelibs.fess.Constants; import org.codelibs.fess.es.config.exentity.BoostDocumentRule; -import org.codelibs.fess.util.GroovyUtil; +import org.codelibs.fess.util.ComponentUtil; public class DocBoostMatcher { @@ -41,7 +42,8 @@ public class DocBoostMatcher { return false; } - final Object value = GroovyUtil.evaluate(matchExpression, map); + final Object value = + ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(matchExpression, map); if (value instanceof Boolean) { return ((Boolean) value); } @@ -54,7 +56,8 @@ public class DocBoostMatcher { return 0.0f; } - final Object value = GroovyUtil.evaluate(boostExpression, map); + final Object value = + ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(boostExpression, map); if (value instanceof Integer) { return ((Integer) value).floatValue(); } diff --git a/src/main/java/org/codelibs/fess/job/impl/GroovyExecutor.java b/src/main/java/org/codelibs/fess/job/impl/GroovyExecutor.java index b7480a5e6..6ca8ed020 100644 --- a/src/main/java/org/codelibs/fess/job/impl/GroovyExecutor.java +++ b/src/main/java/org/codelibs/fess/job/impl/GroovyExecutor.java @@ -18,8 +18,9 @@ package org.codelibs.fess.job.impl; import java.util.HashMap; import java.util.Map; +import org.codelibs.fess.Constants; import org.codelibs.fess.job.JobExecutor; -import org.codelibs.fess.util.GroovyUtil; +import org.codelibs.fess.util.ComponentUtil; public class GroovyExecutor extends JobExecutor { @@ -28,7 +29,7 @@ public class GroovyExecutor extends JobExecutor { final Map params = new HashMap<>(); params.put("executor", this); - return GroovyUtil.evaluate(script, params); + return ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(script, params); } } diff --git a/src/main/java/org/codelibs/fess/script/AbstractScriptEngine.java b/src/main/java/org/codelibs/fess/script/AbstractScriptEngine.java new file mode 100644 index 000000000..c263f4cdb --- /dev/null +++ b/src/main/java/org/codelibs/fess/script/AbstractScriptEngine.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2021 CodeLibs Project and the Others. + * + * Licensed 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.codelibs.fess.script; + +import org.codelibs.fess.util.ComponentUtil; + +public abstract class AbstractScriptEngine implements ScriptEngine { + + public void register() { + ComponentUtil.getScriptEngineFactory().add(getName(), this); + } + + protected abstract String getName(); +} diff --git a/src/test/java/org/codelibs/fess/util/GroovyUtilTest.java b/src/main/java/org/codelibs/fess/script/ScriptEngine.java similarity index 53% rename from src/test/java/org/codelibs/fess/util/GroovyUtilTest.java rename to src/main/java/org/codelibs/fess/script/ScriptEngine.java index c0a650759..ff8eaba72 100644 --- a/src/test/java/org/codelibs/fess/util/GroovyUtilTest.java +++ b/src/main/java/org/codelibs/fess/script/ScriptEngine.java @@ -13,21 +13,10 @@ * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -package org.codelibs.fess.util; +package org.codelibs.fess.script; -import java.util.HashMap; import java.util.Map; -import org.codelibs.fess.unit.UnitFessTestCase; - -public class GroovyUtilTest extends UnitFessTestCase { - public void test_evaluate() { - final Map params = new HashMap<>(); - assertNull(GroovyUtil.evaluate("", params)); - assertEquals("", GroovyUtil.evaluate("return ''", params)); - assertEquals(1, GroovyUtil.evaluate("return 1", params)); - - params.put("test", "123"); - assertEquals("123", GroovyUtil.evaluate("return test", params)); - } +public interface ScriptEngine { + Object evaluate(final String template, final Map paramMap); } diff --git a/src/main/java/org/codelibs/fess/script/ScriptEngineFactory.java b/src/main/java/org/codelibs/fess/script/ScriptEngineFactory.java new file mode 100644 index 000000000..58e5c2176 --- /dev/null +++ b/src/main/java/org/codelibs/fess/script/ScriptEngineFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2021 CodeLibs Project and the Others. + * + * Licensed 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.codelibs.fess.script; + +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.codelibs.fess.exception.ScriptEngineException; + +public class ScriptEngineFactory { + private static final Logger logger = LogManager.getLogger(ScriptEngineFactory.class); + + protected Map scriptEngineMap = new LinkedHashMap<>(); + + public void add(final String name, final ScriptEngine scriptEngine) { + if (name == null || scriptEngine == null) { + throw new IllegalArgumentException("name or scriptEngine is null."); + } + if (logger.isDebugEnabled()) { + logger.debug("Loaded {}", name); + } + scriptEngineMap.put(name.toLowerCase(Locale.ROOT), scriptEngine); + scriptEngineMap.put(scriptEngine.getClass().getSimpleName().toLowerCase(Locale.ROOT), scriptEngine); + } + + public ScriptEngine getScriptEngine(final String name) { + if (name == null) { + throw new ScriptEngineException("script name is null."); + } + final ScriptEngine scriptEngine = scriptEngineMap.get(name.toLowerCase(Locale.ROOT)); + if (scriptEngine != null) { + return scriptEngine; + } + throw new ScriptEngineException(name + " is not found."); + } +} diff --git a/src/main/java/org/codelibs/fess/util/ComponentUtil.java b/src/main/java/org/codelibs/fess/util/ComponentUtil.java index 838cff7b4..e1ec3a703 100644 --- a/src/main/java/org/codelibs/fess/util/ComponentUtil.java +++ b/src/main/java/org/codelibs/fess/util/ComponentUtil.java @@ -77,6 +77,7 @@ import org.codelibs.fess.job.JobExecutor; import org.codelibs.fess.ldap.LdapManager; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.mylasta.direction.FessProp; +import org.codelibs.fess.script.ScriptEngineFactory; import org.codelibs.fess.sso.SsoManager; import org.codelibs.fess.thumbnail.ThumbnailManager; import org.lastaflute.core.message.MessageManager; @@ -95,6 +96,8 @@ public final class ComponentUtil { private static Map componentMap = new HashMap<>(); + private static final String SCRIPT_ENGINE_FACTORY = "scriptEngineFactory"; + private static final String INGEST_FACTORY = "ingestFactory"; private static final String NOTIFICATION_HELPER = "notificationHelper"; @@ -481,6 +484,10 @@ public final class ComponentUtil { return getComponent(INGEST_FACTORY); } + public static ScriptEngineFactory getScriptEngineFactory() { + return getComponent(SCRIPT_ENGINE_FACTORY); + } + public static T getComponent(final Class clazz) { try { return SingletonLaContainer.getComponent(clazz); diff --git a/src/main/java/org/codelibs/fess/util/GroovyUtil.java b/src/main/java/org/codelibs/fess/util/GroovyUtil.java index db8d4487f..d34d73d97 100644 --- a/src/main/java/org/codelibs/fess/util/GroovyUtil.java +++ b/src/main/java/org/codelibs/fess/util/GroovyUtil.java @@ -15,46 +15,18 @@ */ package org.codelibs.fess.util; -import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.codelibs.fess.exception.JobProcessingException; -import org.lastaflute.di.core.factory.SingletonLaContainerFactory; - -import groovy.lang.Binding; -import groovy.lang.GroovyClassLoader; -import groovy.lang.GroovyShell; +import org.codelibs.fess.Constants; +@Deprecated public final class GroovyUtil { - private static final Logger logger = LogManager.getLogger(GroovyUtil.class); private GroovyUtil() { // nothing } public static Object evaluate(final String template, final Map paramMap) { - final Map bindingMap = new HashMap<>(paramMap); - bindingMap.put("container", SingletonLaContainerFactory.getContainer()); - final GroovyShell groovyShell = new GroovyShell(new Binding(bindingMap)); - try { - return groovyShell.evaluate(template); - } catch (final JobProcessingException e) { - throw e; - } catch (final Exception e) { - logger.warn("Failed to evalue groovy script: {} => {}", template, paramMap, e); - return null; - } finally { - final GroovyClassLoader loader = groovyShell.getClassLoader(); - // StreamUtil.of(loader.getLoadedClasses()).forEach(c -> { - // try { - // GroovySystem.getMetaClassRegistry().removeMetaClass(c); - // } catch (Throwable t) { - // logger.warn("Failed to delete " + c, t); - // } - // }); - loader.clearCache(); - } + return ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(template, paramMap); } } diff --git a/src/main/resources/fess.xml b/src/main/resources/fess.xml index b9be2e70d..e16e7507a 100644 --- a/src/main/resources/fess.xml +++ b/src/main/resources/fess.xml @@ -4,6 +4,7 @@ + diff --git a/src/main/resources/fess_se.xml b/src/main/resources/fess_se.xml new file mode 100644 index 000000000..5e1786a2a --- /dev/null +++ b/src/main/resources/fess_se.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/src/test/java/org/codelibs/fess/ds/AbstractDataStoreTest.java b/src/test/java/org/codelibs/fess/ds/AbstractDataStoreTest.java index e73226a03..5ab388fb4 100644 --- a/src/test/java/org/codelibs/fess/ds/AbstractDataStoreTest.java +++ b/src/test/java/org/codelibs/fess/ds/AbstractDataStoreTest.java @@ -18,9 +18,19 @@ package org.codelibs.fess.ds; import java.util.HashMap; import java.util.Map; +import org.codelibs.fess.Constants; import org.codelibs.fess.ds.callback.IndexUpdateCallback; import org.codelibs.fess.es.config.exentity.DataConfig; +import org.codelibs.fess.exception.JobProcessingException; +import org.codelibs.fess.script.AbstractScriptEngine; +import org.codelibs.fess.script.ScriptEngineFactory; import org.codelibs.fess.unit.UnitFessTestCase; +import org.codelibs.fess.util.ComponentUtil; +import org.lastaflute.di.core.factory.SingletonLaContainerFactory; + +import groovy.lang.Binding; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyShell; public class AbstractDataStoreTest extends UnitFessTestCase { public AbstractDataStore dataStore; @@ -40,6 +50,33 @@ public class AbstractDataStoreTest extends UnitFessTestCase { // TODO nothing } }; + + ScriptEngineFactory scriptEngineFactory = new ScriptEngineFactory(); + ComponentUtil.register(scriptEngineFactory, "scriptEngineFactory"); + new AbstractScriptEngine() { + + @Override + public Object evaluate(String template, Map paramMap) { + final Map bindingMap = new HashMap<>(paramMap); + bindingMap.put("container", SingletonLaContainerFactory.getContainer()); + final GroovyShell groovyShell = new GroovyShell(new Binding(bindingMap)); + try { + return groovyShell.evaluate(template); + } catch (final JobProcessingException e) { + throw e; + } catch (final Exception e) { + return null; + } finally { + final GroovyClassLoader loader = groovyShell.getClassLoader(); + loader.clearCache(); + } + } + + @Override + protected String getName() { + return Constants.DEFAULT_SCRIPT; + } + }.register(); } public void test_convertValue() { diff --git a/src/test/java/org/codelibs/fess/indexer/DocBoostMatcherTest.java b/src/test/java/org/codelibs/fess/indexer/DocBoostMatcherTest.java index f800010b2..7ccf20620 100644 --- a/src/test/java/org/codelibs/fess/indexer/DocBoostMatcherTest.java +++ b/src/test/java/org/codelibs/fess/indexer/DocBoostMatcherTest.java @@ -18,9 +18,51 @@ package org.codelibs.fess.indexer; import java.util.HashMap; import java.util.Map; +import org.codelibs.fess.Constants; +import org.codelibs.fess.exception.JobProcessingException; +import org.codelibs.fess.script.AbstractScriptEngine; +import org.codelibs.fess.script.ScriptEngineFactory; import org.codelibs.fess.unit.UnitFessTestCase; +import org.codelibs.fess.util.ComponentUtil; +import org.lastaflute.di.core.factory.SingletonLaContainerFactory; + +import groovy.lang.Binding; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyShell; public class DocBoostMatcherTest extends UnitFessTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + ScriptEngineFactory scriptEngineFactory = new ScriptEngineFactory(); + ComponentUtil.register(scriptEngineFactory, "scriptEngineFactory"); + new AbstractScriptEngine() { + + @Override + public Object evaluate(String template, Map paramMap) { + final Map bindingMap = new HashMap<>(paramMap); + bindingMap.put("container", SingletonLaContainerFactory.getContainer()); + final GroovyShell groovyShell = new GroovyShell(new Binding(bindingMap)); + try { + return groovyShell.evaluate(template); + } catch (final JobProcessingException e) { + throw e; + } catch (final Exception e) { + return null; + } finally { + final GroovyClassLoader loader = groovyShell.getClassLoader(); + loader.clearCache(); + } + } + + @Override + protected String getName() { + return Constants.DEFAULT_SCRIPT; + } + }.register(); + } + public void test_integer() { final DocBoostMatcher docBoostMatcher = new DocBoostMatcher(); docBoostMatcher.setBoostExpression("10");