From 9b931482f29fd82c72a6a61e18d20cb3c3a97c98 Mon Sep 17 00:00:00 2001 From: Karel Maxa Date: Wed, 7 Feb 2024 11:43:08 +0100 Subject: [PATCH] Fix parsing of service provider file (#3841). --- modules/flowable-osgi/pom.xml | 5 ++ .../main/java/org/flowable/osgi/Extender.java | 12 +++- .../osgi/BundleScriptEngineResolverTest.java | 67 +++++++++++++++++++ .../services/javax.script.ScriptEngineFactory | 4 ++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 modules/flowable-osgi/src/test/java/org/flowable/osgi/BundleScriptEngineResolverTest.java create mode 100644 modules/flowable-osgi/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory diff --git a/modules/flowable-osgi/pom.xml b/modules/flowable-osgi/pom.xml index 099ea725c9c..d3691c37edf 100644 --- a/modules/flowable-osgi/pom.xml +++ b/modules/flowable-osgi/pom.xml @@ -201,6 +201,11 @@ junit-jupiter-api test + + org.mockito + mockito-junit-jupiter + test + diff --git a/modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java b/modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java index c1c5a7b4b4f..537e92c8062 100644 --- a/modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java +++ b/modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java @@ -21,11 +21,13 @@ import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; @@ -367,9 +369,13 @@ public void unregister() { @Override public ScriptEngine resolveScriptEngine(String name) { try { - BufferedReader in = new BufferedReader(new InputStreamReader(configFile.openStream())); - String className = in.readLine(); - in.close(); + String className; + try (var input = configFile.openStream()) { + className = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() + .map(line -> line.split("#", 2)[0].trim()) + .filter(Predicate.not(String::isBlank)) + .findFirst().orElse(null); + } Class cls = bundle.loadClass(className); if (!ScriptEngineFactory.class.isAssignableFrom(cls)) { throw new IllegalStateException("Invalid ScriptEngineFactory: " + cls.getName()); diff --git a/modules/flowable-osgi/src/test/java/org/flowable/osgi/BundleScriptEngineResolverTest.java b/modules/flowable-osgi/src/test/java/org/flowable/osgi/BundleScriptEngineResolverTest.java new file mode 100644 index 00000000000..093742eccdf --- /dev/null +++ b/modules/flowable-osgi/src/test/java/org/flowable/osgi/BundleScriptEngineResolverTest.java @@ -0,0 +1,67 @@ +/* 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.flowable.osgi; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.URL; +import java.util.List; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; + +import org.flowable.osgi.Extender.BundleScriptEngineResolver; +import org.junit.Test; +import org.osgi.framework.Bundle; + +/** + * Test processing of service provider configuration file. + */ +public class BundleScriptEngineResolverTest { + + @Test + public void testResolveScriptEngine() throws Exception { + ScriptEngineFactory factory = mock(ScriptEngineFactoryMock.class); + Bundle bundle = mock(Bundle.class); + when(bundle.loadClass(eq("org.flowable.ScriptEngineFactoryMock"))).thenAnswer(answer -> factory.getClass()); + URL configFile = getClass().getClassLoader().getResource("META-INF/services/javax.script.ScriptEngineFactory"); + BundleScriptEngineResolver resolver = new BundleScriptEngineResolver(bundle, configFile); + ScriptEngine resolvedEngine = resolver.resolveScriptEngine("mockengine"); + assertNotNull(resolvedEngine); + assertEquals("mockengine", resolvedEngine.get("name")); + } + + /** + * Script engine factory providing mock script engine. + */ + static abstract class ScriptEngineFactoryMock implements ScriptEngineFactory { + + @Override + public List getNames() { + return List.of("mockengine"); + } + + @Override + public ScriptEngine getScriptEngine() { + ScriptEngine engine = mock(ScriptEngine.class); + when(engine.get(eq("name"))).thenReturn("mockengine"); + return engine; + } + + } + +} diff --git a/modules/flowable-osgi/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/flowable-osgi/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 00000000000..165bef5b9b4 --- /dev/null +++ b/modules/flowable-osgi/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1,4 @@ +# Comments, tabs and spaces should be ignored +# See java.util.ServiceLoader + + org.flowable.ScriptEngineFactoryMock # should be also ignored