Explorar o código

fix #2561 add scripnt engine

Shinsuke Sugaya %!s(int64=4) %!d(string=hai) anos
pai
achega
999097a7b0

+ 6 - 7
pom.xml

@@ -1445,13 +1445,6 @@
 			<version>4.2.0</version>
 		</dependency>
 
-		<!-- groovy -->
-		<dependency>
-			<groupId>org.codehaus.groovy</groupId>
-			<artifactId>groovy</artifactId>
-			<version>${groovy.version}</version>
-		</dependency>
-
 		<!-- Tomcat -->
 		<dependency>
 			<groupId>org.dbflute.tomcat</groupId>
@@ -1532,5 +1525,11 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
+		<dependency>
+			<groupId>org.codehaus.groovy</groupId>
+			<artifactId>groovy</artifactId>
+			<version>${groovy.version}</version>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 </project>

+ 2 - 0
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";
 }

+ 1 - 2
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() {

+ 1 - 2
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<String, String> paramMap) {

+ 29 - 0
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);
+    }
+}

+ 2 - 2
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<String, Object> 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;
             }

+ 7 - 1
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;
         }
     }

+ 6 - 3
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();
         }

+ 3 - 2
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<String, Object> params = new HashMap<>();
         params.put("executor", this);
 
-        return GroovyUtil.evaluate(script, params);
+        return ComponentUtil.getScriptEngineFactory().getScriptEngine(Constants.DEFAULT_SCRIPT).evaluate(script, params);
     }
 
 }

+ 27 - 0
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();
+}

+ 3 - 14
src/test/java/org/codelibs/fess/util/GroovyUtilTest.java → 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<String, Object> 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<String, Object> paramMap);
 }

+ 52 - 0
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<String, ScriptEngine> 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.");
+    }
+}

+ 7 - 0
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<String, Object> 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> T getComponent(final Class<T> clazz) {
         try {
             return SingletonLaContainer.getComponent(clazz);

+ 3 - 31
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<String, Object> paramMap) {
-        final Map<String, Object> 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);
     }
 }

+ 1 - 0
src/main/resources/fess.xml

@@ -4,6 +4,7 @@
 <components>
 	<include path="fess_config.xml"/>
 	<include path="fess_ds.xml"/>
+	<include path="fess_se.xml"/>
 	<include path="esflute_config.xml"/>
 	<include path="esflute_user.xml"/>
 	<include path="esflute_log.xml"/>

+ 7 - 0
src/main/resources/fess_se.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN"
+	"http://dbflute.org/meta/lastadi10.dtd">
+<components>
+	<component name="scriptEngineFactory" class="org.codelibs.fess.script.ScriptEngineFactory">
+	</component>
+</components>

+ 37 - 0
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<String, Object> paramMap) {
+                final Map<String, Object> 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() {

+ 42 - 0
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<String, Object> paramMap) {
+                final Map<String, Object> 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");