diff --git a/cms-api/pom.xml b/cms-api/pom.xml
index 296fd3a7f..f336ec9c7 100644
--- a/cms-api/pom.xml
+++ b/cms-api/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-api
jar
@@ -16,7 +16,7 @@
provided
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-api
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtensionPoint.java
index 6afd7438e..8ea1dd4fe 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtensionPoint.java
@@ -38,7 +38,7 @@ public abstract class TemplateModelExtendingExtensionPoint extends AbstractExten
public abstract void extendModel (TemplateEngine.Model model);
public Map getModel () {
- TemplateEngine.Model model = new TemplateEngine.Model(null, null);
+ TemplateEngine.Model model = new TemplateEngine.Model(null, null, null);
extendModel(model);
return model.values;
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtentionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtentionPoint.java
deleted file mode 100644
index 499e458a7..000000000
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateModelExtendingExtentionPoint.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.condation.cms.api.extensions;
-
-import java.util.Map;
-
-import com.condation.cms.api.Constants;
-
-/*-
- * #%L
- * cms-api
- * %%
- * Copyright (C) 2023 Marx-Software
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import com.condation.cms.api.template.TemplateEngine;
-
-/**
- *
- * @deprecated As of release 7.2.0, replaced by {@link TemplateModelExtendingExtensionPoint}
- *
- * @author thmar
- */
-@Deprecated(since = "7.2.0", forRemoval = true)
-public abstract class TemplateModelExtendingExtentionPoint extends AbstractExtensionPoint{
-
- public abstract void extendModel (TemplateEngine.Model model);
-
- public Map getModel () {
- TemplateEngine.Model model = new TemplateEngine.Model(null, null);
- extendModel(model);
- return model.values;
- }
-
- public String getNamespace () {
- return Constants.DEFAULT_MODULE_NAMESPACE;
- }
-}
diff --git a/cms-api/src/main/java/com/condation/cms/api/feature/features/ServerPropertiesFeature.java b/cms-api/src/main/java/com/condation/cms/api/feature/features/ServerPropertiesFeature.java
index d69b18c96..04884ad3d 100644
--- a/cms-api/src/main/java/com/condation/cms/api/feature/features/ServerPropertiesFeature.java
+++ b/cms-api/src/main/java/com/condation/cms/api/feature/features/ServerPropertiesFeature.java
@@ -33,7 +33,6 @@
*
* @author t.marx
*/
-@Deprecated(since = "6.5.0")
@FeatureScope({FeatureScope.Scope.GLOBAL, FeatureScope.Scope.MODULE, FeatureScope.Scope.REQUEST})
public record ServerPropertiesFeature(ServerProperties serverProperties) implements Feature {
diff --git a/cms-api/src/main/java/com/condation/cms/api/feature/features/SitePropertiesFeature.java b/cms-api/src/main/java/com/condation/cms/api/feature/features/SitePropertiesFeature.java
index c1a6f94d4..f6ad14aa0 100644
--- a/cms-api/src/main/java/com/condation/cms/api/feature/features/SitePropertiesFeature.java
+++ b/cms-api/src/main/java/com/condation/cms/api/feature/features/SitePropertiesFeature.java
@@ -33,7 +33,6 @@
*
* @author t.marx
*/
-@Deprecated(since = "6.5.0")
@FeatureScope({FeatureScope.Scope.GLOBAL, FeatureScope.Scope.MODULE, FeatureScope.Scope.REQUEST})
public record SitePropertiesFeature(SiteProperties siteProperties) implements Feature {
diff --git a/cms-api/src/main/java/com/condation/cms/api/featureflags/FeatureFlags.java b/cms-api/src/main/java/com/condation/cms/api/featureflags/FeatureFlags.java
new file mode 100644
index 000000000..a60e1e0f7
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/featureflags/FeatureFlags.java
@@ -0,0 +1,69 @@
+package com.condation.cms.api.featureflags;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class FeatureFlags {
+ private static final Map flags = new ConcurrentHashMap<>();
+
+ private FeatureFlags() {}
+
+ /**
+ * Initialize Feature-Flags.
+ * @param initialFlags Map of features
+ */
+ public static void initialize(Map initialFlags) {
+ flags.clear();
+ flags.putAll(initialFlags);
+ }
+
+ /**
+ * Checks if a feature is activated
+ * @param featureName Name of the feature.
+ * @return true, if the feature is activated; otherwise false.
+ */
+ public static boolean isEnabled(String featureName) {
+ return flags.getOrDefault(featureName, false);
+ }
+
+ /**
+ * sets or updates a feature
+ * @param featureName Name of the feature.
+ * @param enabled true if activated, false if deactivated.
+ */
+ public static void setFlag(String featureName, boolean enabled) {
+ flags.put(featureName, enabled);
+ }
+
+ /**
+ * returns an unmodifiable view of the feature flags
+ * @return Map of the current feature flags.
+ */
+ public static Map getFlags() {
+ return Collections.unmodifiableMap(flags);
+ }
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/template/TemplateEngine.java b/cms-api/src/main/java/com/condation/cms/api/template/TemplateEngine.java
index 877fb50ee..8181325d4 100644
--- a/cms-api/src/main/java/com/condation/cms/api/template/TemplateEngine.java
+++ b/cms-api/src/main/java/com/condation/cms/api/template/TemplateEngine.java
@@ -24,6 +24,7 @@
import com.condation.cms.api.db.ContentNode;
import com.condation.cms.api.db.cms.ReadOnlyFile;
+import com.condation.cms.api.request.RequestContext;
import com.condation.cms.api.theme.Theme;
import java.io.IOException;
import java.util.HashMap;
@@ -51,5 +52,6 @@ public static class Model {
public final Map values = new HashMap<>();
public final ReadOnlyFile contentFile;
public final ContentNode contentNode;
+ public final RequestContext requestContext;
}
}
diff --git a/cms-api/src/test/java/com/condation/cms/api/featureflags/FeatureFlagsTest.java b/cms-api/src/test/java/com/condation/cms/api/featureflags/FeatureFlagsTest.java
new file mode 100644
index 000000000..1c9565bb1
--- /dev/null
+++ b/cms-api/src/test/java/com/condation/cms/api/featureflags/FeatureFlagsTest.java
@@ -0,0 +1,91 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/UnitTests/JUnit5TestClass.java to edit this template
+ */
+package com.condation.cms.api.featureflags;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class FeatureFlagsTest {
+
+ @BeforeEach
+ void setup() {
+ // Initialisiere die FeatureFlags vor jedem Test
+ FeatureFlags.initialize(Map.of(
+ "featureX", true,
+ "newDashboard", false
+ ));
+ }
+
+ @Test
+ void testFeatureIsEnabled() {
+ // Prüfe, dass ein aktives Feature korrekt erkannt wird
+ assertThat(FeatureFlags.isEnabled("featureX")).isTrue();
+ }
+
+ @Test
+ void testFeatureIsDisabled() {
+ // Prüfe, dass ein inaktives Feature korrekt erkannt wird
+ assertThat(FeatureFlags.isEnabled("newDashboard")).isFalse();
+ }
+
+ @Test
+ void testDefaultFlagIsDisabled() {
+ // Prüfe, dass ein nicht initialisiertes Feature false zurückgibt
+ assertThat(FeatureFlags.isEnabled("nonExistentFeature")).isFalse();
+ }
+
+ @Test
+ void testSetFlag() {
+ // Aktiviere ein neues Feature und prüfe den Status
+ FeatureFlags.setFlag("betaFeature", true);
+ assertThat(FeatureFlags.isEnabled("betaFeature")).isTrue();
+
+ // Deaktiviere es wieder und prüfe den Status
+ FeatureFlags.setFlag("betaFeature", false);
+ assertThat(FeatureFlags.isEnabled("betaFeature")).isFalse();
+ }
+
+ @Test
+ void testGetFlags() {
+ // Prüfe, dass die initialisierten Flags korrekt zurückgegeben werden
+ Map flags = FeatureFlags.getFlags();
+
+ assertThat(flags).containsEntry("featureX", true)
+ .containsEntry("newDashboard", false)
+ .doesNotContainKey("nonExistentFeature");
+
+ // Prüfe, dass die Map unveränderlich ist
+ assertThatThrownBy(() -> flags.put("shouldFail", true))
+ .isInstanceOf(UnsupportedOperationException.class);
+ }
+}
+
diff --git a/cms-auth/pom.xml b/cms-auth/pom.xml
index ab64b75b4..9931f6184 100644
--- a/cms-auth/pom.xml
+++ b/cms-auth/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-auth
jar
@@ -19,7 +19,7 @@
cms-filesystem
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-api
provided
diff --git a/cms-content/pom.xml b/cms-content/pom.xml
index 6b734e29c..e517aa3f7 100644
--- a/cms-content/pom.xml
+++ b/cms-content/pom.xml
@@ -6,7 +6,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-content
jar
diff --git a/cms-content/src/main/java/com/condation/cms/content/DefaultContentRenderer.java b/cms-content/src/main/java/com/condation/cms/content/DefaultContentRenderer.java
index 2f83379d5..b1223fef0 100644
--- a/cms-content/src/main/java/com/condation/cms/content/DefaultContentRenderer.java
+++ b/cms-content/src/main/java/com/condation/cms/content/DefaultContentRenderer.java
@@ -31,7 +31,6 @@
import com.condation.cms.api.db.taxonomy.Taxonomy;
import com.condation.cms.api.extensions.ContentQueryOperatorExtensionPoint;
import com.condation.cms.api.extensions.TemplateModelExtendingExtensionPoint;
-import com.condation.cms.api.extensions.TemplateModelExtendingExtentionPoint;
import com.condation.cms.api.feature.features.AuthFeature;
import com.condation.cms.api.feature.features.HookSystemFeature;
import com.condation.cms.api.feature.features.InjectorFeature;
@@ -136,12 +135,13 @@ public String render(final ReadOnlyFile contentFile, final RequestContext contex
Optional contentNode = db.getContent().byUri(uri);
- TemplateEngine.Model model = new TemplateEngine.Model(contentFile, contentNode.isPresent() ? contentNode.get() : null);
+ TemplateEngine.Model model = new TemplateEngine.Model(
+ contentFile,
+ contentNode.isPresent() ? contentNode.get() : null,
+ context);
modelExtending.accept(model);
- //model.values.put("cms", Namespace.create("cms", meta));
-
Namespace namespace = new Namespace();
model.values.put("meta", new MapAccess(meta));
@@ -151,8 +151,8 @@ public String render(final ReadOnlyFile contentFile, final RequestContext contex
namespace.add("node", "sections", sections);
ShortCodeTemplateFunction shortCodeFunction = createShortCodeFunction(context);
- model.values.put("shortCodes", shortCodeFunction);
- namespace.add("cms", "shortCodes", shortCodeFunction);
+ model.values.put(ShortCodeTemplateFunction.KEY, shortCodeFunction);
+ namespace.add("cms", ShortCodeTemplateFunction.KEY, shortCodeFunction);
NavigationFunction navigationFunction = createNavigationFunction(contentFile, context);
model.values.put("navigation", navigationFunction);
@@ -252,16 +252,6 @@ private boolean isDevMode(final RequestContext context) {
}
private void extendModel(final TemplateEngine.Model model, Namespace namespace) {
- moduleManager.extensions(TemplateModelExtendingExtentionPoint.class).forEach(extensionPoint -> {
- var modModel = extensionPoint.getModel();
- // deprecated: module extensions on root will be remove in 8.0.0
- model.values.putAll(modModel);
- modModel.entrySet().forEach(entry -> namespace.add(
- extensionPoint.getNamespace(),
- entry.getKey(),
- entry.getValue()
- ));
- });
moduleManager.extensions(TemplateModelExtendingExtensionPoint.class).forEach(extensionPoint -> {
var modModel = extensionPoint.getModel();
// deprecated: module extensions on root will be remove in 8.0.0
diff --git a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
index 33470aed2..87469d342 100644
--- a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
+++ b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
@@ -26,6 +26,7 @@
import com.condation.cms.api.model.Parameter;
import java.util.Collections;
import java.util.Map;
+import java.util.Set;
import java.util.function.Function;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -47,6 +48,10 @@ public ShortCodes (Map> codes, TagParser tag
this.tagMap.putAll(codes);
}
+ public Set getShortCodeNames () {
+ return tagMap.names();
+ }
+
public String replace (final String content) {
return replace(content, Collections.emptyMap());
}
diff --git a/cms-content/src/main/java/com/condation/cms/content/shortcodes/TagMap.java b/cms-content/src/main/java/com/condation/cms/content/shortcodes/TagMap.java
index e503f067a..b8daff203 100644
--- a/cms-content/src/main/java/com/condation/cms/content/shortcodes/TagMap.java
+++ b/cms-content/src/main/java/com/condation/cms/content/shortcodes/TagMap.java
@@ -23,8 +23,10 @@
*/
import com.condation.cms.api.model.Parameter;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.function.Function;
/**
@@ -35,6 +37,10 @@ public class TagMap {
private final Map> tags = new HashMap<>();
+ public Set names () {
+ return Collections.unmodifiableSet(tags.keySet());
+ }
+
public void put(String codeName, Function function) {
tags.put(codeName, function);
}
diff --git a/cms-content/src/main/java/com/condation/cms/content/template/functions/hooks/HooksTemlateFunction.java b/cms-content/src/main/java/com/condation/cms/content/template/functions/hooks/HooksTemlateFunction.java
index 824133cdc..41f47b5da 100644
--- a/cms-content/src/main/java/com/condation/cms/content/template/functions/hooks/HooksTemlateFunction.java
+++ b/cms-content/src/main/java/com/condation/cms/content/template/functions/hooks/HooksTemlateFunction.java
@@ -39,15 +39,6 @@ public class HooksTemlateFunction {
private final HookSystem hookSystem;
- @Deprecated(since = "4.18.0", forRemoval = true)
- public ActionContext call (String name) {
- return execute(name, Map.of());
- }
- @Deprecated(since = "4.18.0", forRemoval = true)
- public ActionContext call (String name, Map arguments) {
- return execute(name, arguments);
- }
-
public ActionContext execute (String name) {
return execute(name, Map.of());
}
diff --git a/cms-content/src/main/java/com/condation/cms/content/template/functions/shortcode/ShortCodeTemplateFunction.java b/cms-content/src/main/java/com/condation/cms/content/template/functions/shortcode/ShortCodeTemplateFunction.java
index 353091f52..961b0f58c 100644
--- a/cms-content/src/main/java/com/condation/cms/content/template/functions/shortcode/ShortCodeTemplateFunction.java
+++ b/cms-content/src/main/java/com/condation/cms/content/template/functions/shortcode/ShortCodeTemplateFunction.java
@@ -25,6 +25,7 @@
import com.condation.cms.content.shortcodes.ShortCodes;
import java.util.Map;
+import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
@@ -33,6 +34,10 @@
*/
@RequiredArgsConstructor
public class ShortCodeTemplateFunction {
+
+ public static final String KEY = "shortCodes";
+
+ @Getter
private final ShortCodes shortCodes;
public String call (String name, Map parameters) {
diff --git a/cms-core/pom.xml b/cms-core/pom.xml
index 340f1cfd2..902ee4f77 100644
--- a/cms-core/pom.xml
+++ b/cms-core/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-core
jar
diff --git a/cms-extensions/pom.xml b/cms-extensions/pom.xml
index 5f8d74f11..d7f3a59a6 100644
--- a/cms-extensions/pom.xml
+++ b/cms-extensions/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-extensions
jar
diff --git a/cms-filesystem/pom.xml b/cms-filesystem/pom.xml
index 3a9ecc1b2..72372143b 100644
--- a/cms-filesystem/pom.xml
+++ b/cms-filesystem/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-filesystem
jar
diff --git a/cms-git/pom.xml b/cms-git/pom.xml
index 3542a9b77..74aeec147 100644
--- a/cms-git/pom.xml
+++ b/cms-git/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-git
jar
diff --git a/cms-media/pom.xml b/cms-media/pom.xml
index 8f599280b..ba41dc15a 100644
--- a/cms-media/pom.xml
+++ b/cms-media/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-media
jar
diff --git a/cms-server/pom.xml b/cms-server/pom.xml
index 917a5f998..db23703e8 100644
--- a/cms-server/pom.xml
+++ b/cms-server/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-server
jar
@@ -108,7 +108,7 @@
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-manager
diff --git a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
index 473283ad9..c8fdc93f4 100644
--- a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
+++ b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
@@ -28,7 +28,6 @@
import com.condation.cms.api.configuration.configs.SiteConfiguration;
import com.condation.cms.api.content.ContentParser;
import com.condation.cms.api.extensions.HookSystemRegisterExtensionPoint;
-import com.condation.cms.api.extensions.HookSystemRegisterExtentionPoint;
import com.condation.cms.api.extensions.RegisterShortCodesExtensionPoint;
import com.condation.cms.api.feature.features.ConfigurationFeature;
import com.condation.cms.api.feature.features.ContentNodeMapperFeature;
@@ -150,10 +149,22 @@ public void initContext (RequestContext requestContext, Request request) throws
requestContext.add(RequestExtensions.class, requestExtensions);
}
- private HookSystem initHookSystem(RequestContext requestContext) {
+ private void initHookSystem(RequestContext requestContext) {
var hookSystem = requestContext.get(HookSystemFeature.class).hookSystem();
var moduleManager = injector.getInstance(ModuleManager.class);
- moduleManager.extensions(HookSystemRegisterExtentionPoint.class).forEach(extensionPoint -> extensionPoint.register(hookSystem));
+ moduleManager.extensions(HookSystemRegisterExtensionPoint.class).forEach(extensionPoint -> extensionPoint.register(hookSystem));
+ }
+
+ /**
+ * Has to run as one of the last steps, because we need the requestContext
+ * to be filled
+ *
+ * @param requestContext
+ * @return
+ */
+ private HookSystem setupAndGetHookSystem() {
+ var hookSystem = injector.getInstance(HookSystem.class);
+ var moduleManager = injector.getInstance(ModuleManager.class);
moduleManager.extensions(HookSystemRegisterExtensionPoint.class).forEach(extensionPoint -> extensionPoint.register(hookSystem));
return hookSystem;
@@ -202,7 +213,7 @@ public RequestContext create() throws IOException {
requestContext.add(DBHooks.class, new DBHooks(requestContext));
requestContext.add(ContentHooks.class, new ContentHooks(requestContext));
- requestContext.add(HookSystemFeature.class, new HookSystemFeature(setupHookSystem()));
+ requestContext.add(HookSystemFeature.class, new HookSystemFeature(setupAndGetHookSystem()));
RequestExtensions requestExtensions = extensionManager.newContext(theme, requestContext);
@@ -243,21 +254,6 @@ public RequestContext create(
return requestContext;
}
- /**
- * Has to run as one of the last steps, because we need the requestContext
- * to be filled
- *
- * @param requestContext
- * @return
- */
- private HookSystem setupHookSystem() {
- var hookSystem = injector.getInstance(HookSystem.class);
- var moduleManager = injector.getInstance(ModuleManager.class);
- moduleManager.extensions(HookSystemRegisterExtentionPoint.class).forEach(extensionPoint -> extensionPoint.register(hookSystem));
-
- return hookSystem;
- }
-
private ShortCodes createShortCodes(RequestContext requestContext) {
Map> codes = new HashMap<>();
diff --git a/cms-server/src/main/java/com/condation/cms/server/configs/ModulesModule.java b/cms-server/src/main/java/com/condation/cms/server/configs/ModulesModule.java
index 5e2cf1110..4b0a4d776 100644
--- a/cms-server/src/main/java/com/condation/cms/server/configs/ModulesModule.java
+++ b/cms-server/src/main/java/com/condation/cms/server/configs/ModulesModule.java
@@ -24,7 +24,6 @@
import com.condation.cms.api.SiteProperties;
import com.condation.cms.api.extensions.MarkdownRendererProviderExtensionPoint;
import com.condation.cms.api.extensions.TemplateEngineProviderExtensionPoint;
-import com.condation.cms.api.extensions.TemplateEngineProviderExtentionPoint;
import com.condation.cms.api.feature.features.ModuleManagerFeature;
import com.condation.cms.api.hooks.HookSystem;
import com.condation.cms.api.markdown.MarkdownRenderer;
@@ -170,13 +169,6 @@ public TemplateEngine resolveTemplateEngine(SiteProperties siteProperties, Theme
if (extOpt.isPresent()) {
return extOpt.get().getTemplateEngine();
}
-
- List extensionsLegacy = moduleManager.extensions(TemplateEngineProviderExtentionPoint.class);
- Optional extLegacyOpt = extensionsLegacy.stream().filter((ext) -> ext.getName().equals(engine)).findFirst();
-
- if (extLegacyOpt.isPresent()) {
- return extLegacyOpt.get().getTemplateEngine();
- }
throw new RuntimeException("no template engine found");
}
diff --git a/cms-templates/pom.xml b/cms-templates/pom.xml
index 1f1d34ebf..b038adda4 100644
--- a/cms-templates/pom.xml
+++ b/cms-templates/pom.xml
@@ -7,7 +7,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-templates
@@ -25,6 +25,10 @@
com.condation.cms
cms-api
+
+ com.condation.cms
+ cms-content
+
com.condation.cms
cms-core
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/Module.java b/cms-templates/src/main/java/com/condation/cms/templates/Component.java
similarity index 60%
rename from modules-framework/api/src/main/java/com/condation/modules/api/Module.java
rename to cms-templates/src/main/java/com/condation/cms/templates/Component.java
index b26ce43e2..3894c03c6 100644
--- a/modules-framework/api/src/main/java/com/condation/modules/api/Module.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/Component.java
@@ -1,8 +1,8 @@
-package com.condation.modules.api;
+package com.condation.cms.templates;
/*-
* #%L
- * modules-api
+ * templates
* %%
* Copyright (C) 2023 - 2024 CondationCMS
* %%
@@ -22,37 +22,28 @@
* #L%
*/
-
-import java.util.List;
+import com.condation.cms.templates.parser.ComponentNode;
+import com.condation.cms.templates.renderer.Renderer;
+import java.io.Writer;
+import java.util.Optional;
/**
*
- * @author marx
+ * @author t.marx
*/
-public interface Module {
+public interface Component {
- public enum Priority {
- NORMAL,
- // System modules must be loaded before default modules
- HIGH,
- HIGHER,
- HIGHEST;
+ String getName();
+
+ default Optional getCloseingName () {
+ return Optional.empty();
}
- Priority getPriority ();
-
- List extensions(Class extensionClass);
-
- String getAuthor();
-
- String getDescription();
-
- String getId();
-
- String getName();
-
- String getVersion();
-
- boolean provides(Class extends ExtensionPoint> extensionClass);
-
+ default boolean isClosing () {
+ return false;
+ }
+
+ default void render (ComponentNode node, Renderer.Context context, Writer writer) {
+ // default render does nothing
+ };
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/DefaultTemplate.java b/cms-templates/src/main/java/com/condation/cms/templates/DefaultTemplate.java
index 60e6382b9..073399dfd 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/DefaultTemplate.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/DefaultTemplate.java
@@ -26,6 +26,7 @@
import com.condation.cms.templates.renderer.Renderer;
import com.condation.cms.templates.renderer.ScopeStack;
import java.io.IOException;
+import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import lombok.Getter;
@@ -52,9 +53,20 @@ public void evaluate(Map context, Writer writer) throws IOExcept
writer.flush();
}
+
+ @Override
+ public String evaluate(Map context, DynamicConfiguration dynamicConfiguration) throws IOException {
+ ScopeStack scopes = new ScopeStack(context);
+
+ try (var writer = new StringWriter()) {
+ renderer.render(rootNode, scopes, writer, dynamicConfiguration);
+ writer.flush();
+ return writer.toString();
+ }
+ }
public void evaluate (ScopeStack scopes, Writer writer) throws IOException {
- renderer.render(rootNode, scopes, writer);
+ renderer.render(rootNode, scopes, writer, null);
}
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java
new file mode 100644
index 000000000..65977de85
--- /dev/null
+++ b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java
@@ -0,0 +1,59 @@
+package com.condation.cms.templates;
+
+/*-
+ * #%L
+ * cms-templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.condation.cms.content.shortcodes.ShortCodes;
+import com.condation.cms.templates.tags.component.EndComponentTag;
+import com.condation.cms.templates.tags.component.ComponentTag;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ *
+ * @author t.marx
+ */
+public record DynamicConfiguration(ShortCodes shortCodes, Map components) {
+
+ public DynamicConfiguration {
+ for (var tag : shortCodes.getShortCodeNames()) {
+ var openTag = new ComponentTag(tag, shortCodes);
+ var closeTag = new EndComponentTag(tag);
+
+ components.put(openTag.getName(), openTag);
+ components.put(closeTag.getName(), closeTag);
+ }
+ }
+
+ public DynamicConfiguration(ShortCodes shortcodes) {
+ this(shortcodes, new HashMap<>());
+ }
+
+ public boolean hasComponent (String name) {
+ return components.containsKey(name);
+ }
+
+ public Optional getComponent (String name) {
+ return Optional.ofNullable(components.get(name));
+ }
+}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/Template.java b/cms-templates/src/main/java/com/condation/cms/templates/Template.java
index 071a35f38..ff0fa229c 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/Template.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/Template.java
@@ -43,5 +43,7 @@ default String evaluate(Map context) throws IOException {
return writer.toString();
}
+ String evaluate(Map context, DynamicConfiguration dynamicConfiguration) throws IOException;
+
void evaluate (Map context, Writer writer) throws IOException;
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/TemplateConfiguration.java b/cms-templates/src/main/java/com/condation/cms/templates/TemplateConfiguration.java
index ea95edffc..4cfc08c21 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/TemplateConfiguration.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/TemplateConfiguration.java
@@ -58,7 +58,7 @@ public boolean hasTags () {
}
public boolean hasFilters () {
- return !registeredTags.isEmpty();
+ return !filterRegistry.empty();
}
public TemplateConfiguration setCache (ICache cache) {
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/filter/FilterRegistry.java b/cms-templates/src/main/java/com/condation/cms/templates/filter/FilterRegistry.java
index 3e1392a46..3a415a33f 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/filter/FilterRegistry.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/filter/FilterRegistry.java
@@ -28,6 +28,10 @@
public class FilterRegistry {
private final Map filters = new HashMap<>();
+ public boolean empty () {
+ return filters.isEmpty();
+ }
+
public void register(String name, Filter filter) {
filters.put(name, filter);
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/lexer/Lexer.java b/cms-templates/src/main/java/com/condation/cms/templates/lexer/Lexer.java
index 934d668da..4e28f0311 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/lexer/Lexer.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/lexer/Lexer.java
@@ -36,11 +36,14 @@ public class Syntax {
public static final String VARIABLE_OPEN = "{{";
public static final String VARIABLE_CLOSE = "}}";
+ public static final String COMPONENT_OPEN = "{[";
+ public static final String COMPONENT_CLOSE = "]}";
+
public static final String[] OPENING = new String[] {
- TAG_OPEN, COMMENT_OPEN, VARIABLE_OPEN};
+ TAG_OPEN, COMMENT_OPEN, VARIABLE_OPEN, COMPONENT_OPEN};
public static final String[] CLOSING = new String[] {
- TAG_CLOSE, COMMENT_CLOSE, VARIABLE_CLOSE};
+ TAG_CLOSE, COMMENT_CLOSE, VARIABLE_CLOSE, COMPONENT_CLOSE};
}
public Lexer() {
@@ -61,34 +64,43 @@ public TokenStream tokenize(String input) {
int column = charStream.getColumn();
if (c == '{' && charStream.peek(1) == '{') {
- tokens.add(new Token(Token.Type.VARIABLE_START, "{{", line, column));
+ tokens.add(new Token(Token.Type.VARIABLE_START, Syntax.VARIABLE_OPEN, line, column));
charStream.skip(2);
state.set(State.Type.VARIABLE);
} else if (c == '{' && charStream.peek(1) == '%') {
- tokens.add(new Token(Token.Type.TAG_START, "{%", line, column));
+ tokens.add(new Token(Token.Type.TAG_START, Syntax.TAG_OPEN, line, column));
charStream.skip(2);
state.set(State.Type.TAG);
readTagContent(tokens, charStream); // Inhalte des Tags lesen
+ } else if (c == '{' && charStream.peek(1) == '[') {
+ tokens.add(new Token(Token.Type.COMPONENT_START, Syntax.COMPONENT_OPEN, line, column));
+ charStream.skip(2);
+ state.set(State.Type.COMPONENT);
+ readComponentContent(tokens, charStream);
} else if (c == '{' && charStream.peek(1) == '#') {
- tokens.add(new Token(Token.Type.COMMENT_START, "{*", line, column));
+ tokens.add(new Token(Token.Type.COMMENT_START, Syntax.COMMENT_OPEN, line, column));
charStream.skip(2);
state.set(State.Type.COMMENT);
} else if (state.is(State.Type.TAG) && c == '%' && charStream.peek(1) == '}') {
- tokens.add(new Token(Token.Type.TAG_END, "%}", line, column));
+ tokens.add(new Token(Token.Type.TAG_END, Syntax.TAG_CLOSE, line, column));
+ charStream.skip(2);
+ state.set(State.Type.NONE);
+ } else if (state.is(State.Type.COMPONENT) && c == ']' && charStream.peek(1) == '}') {
+ tokens.add(new Token(Token.Type.COMPONENT_END, Syntax.COMPONENT_CLOSE, line, column));
charStream.skip(2);
state.set(State.Type.NONE);
} else if (state.is(State.Type.VARIABLE) && c == '}' && charStream.peek(1) == '}') {
- tokens.add(new Token(Token.Type.VARIABLE_END, "}}", line, column));
+ tokens.add(new Token(Token.Type.VARIABLE_END, Syntax.VARIABLE_CLOSE, line, column));
charStream.skip(2);
state.set(State.Type.NONE);
} else if (state.is(State.Type.COMMENT) && c == '#' && charStream.peek(1) == '}') {
- tokens.add(new Token(Token.Type.COMMENT_END, "#}", line, column));
+ tokens.add(new Token(Token.Type.COMMENT_END, Syntax.COMMENT_CLOSE, line, column));
charStream.skip(2);
state.set(State.Type.NONE);
} else if (state.is(State.Type.VARIABLE)) {
tokens.add(new Token(Token.Type.IDENTIFIER, readVariableContent(charStream), line, column));
} else if (state.is(State.Type.COMMENT)) {
- tokens.add(new Token(Token.Type.COMMENT_VALUE, charStream.readUntil("#}"), line, column)); // Alles bis zum nächsten '{' als Text speichern
+ tokens.add(new Token(Token.Type.COMMENT_VALUE, charStream.readUntil(Syntax.COMMENT_CLOSE), line, column)); // Alles bis zum nächsten '{' als Text speichern
} else if (!state.is(State.Type.VARIABLE, State.Type.TAG)) {
tokens.add(new Token(Token.Type.TEXT, charStream.readUntil(Syntax.OPENING), line, column)); // Alles bis zum nächsten '{' als Text speichern
} else {
@@ -134,39 +146,21 @@ public static String readVariableContent(CharacterStream stream) {
return content.toString().trim();
}
-
- private void readTagContent(List tokens, CharacterStream charStream) {
+ private void readContent(List tokens, CharacterStream charStream, final String END) {
charStream.skipWhitespace();
- String keyword = charStream.readWhile(Character::isLetter);
+ String keyword = charStream.readWhile(Character::isLetterOrDigit);
tokens.add(new Token(Token.Type.IDENTIFIER, keyword, charStream.getLine(), charStream.getColumn()));
- String condition = charStream.readUntil("%}");
+ String condition = charStream.readUntil(END);
tokens.add(new Token(Token.Type.EXPRESSION, condition, charStream.getLine(), charStream.getColumn()));
}
-
- private String readString(CharacterStream charStream, char delimiter) {
- StringBuilder result = new StringBuilder();
- result.append(delimiter); // Anfangs-Anführungszeichen hinzufügen
- charStream.advance(); // Das anfängliche Anführungszeichen überspringen
- while (charStream.hasMore()) {
- char c = charStream.charAtCurrentPosition();
- if (c == delimiter) {
- result.append(c); // Abschließendes Anführungszeichen hinzufügen
- charStream.advance(); // Das abschließende Anführungszeichen überspringen
- break;
- }
- if (c == '\\') {
- // Escape-Sequenzen verarbeiten
- result.append(c); // Backslash hinzufügen
- charStream.advance();
- if (charStream.hasMore()) {
- c = charStream.charAtCurrentPosition();
- }
- }
- result.append(c);
- charStream.advance();
- }
- return result.toString();
+
+ private void readTagContent(List tokens, CharacterStream charStream) {
+ readContent(tokens, charStream, Syntax.TAG_CLOSE);
+ }
+
+ private void readComponentContent(List tokens, CharacterStream charStream) {
+ readContent(tokens, charStream, Syntax.COMPONENT_CLOSE);
}
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/lexer/State.java b/cms-templates/src/main/java/com/condation/cms/templates/lexer/State.java
index 3f91c018d..b960c7772 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/lexer/State.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/lexer/State.java
@@ -34,6 +34,7 @@ public class State {
public enum Type {
NONE,
TAG,
+ COMPONENT,
VARIABLE,
COMMENT
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/lexer/Token.java b/cms-templates/src/main/java/com/condation/cms/templates/lexer/Token.java
index 63fd6706a..256e15f0e 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/lexer/Token.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/lexer/Token.java
@@ -27,6 +27,8 @@ public static enum Type {
TEXT,
VARIABLE_START,
VARIABLE_END,
+ COMPONENT_START,
+ COMPONENT_END,
TAG_START,
TAG_END,
COMMENT_START,
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
index d43be166d..4573fd2d0 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
@@ -25,7 +25,10 @@
import com.condation.cms.api.db.DB;
import com.condation.cms.api.template.TemplateEngine;
import com.condation.cms.api.theme.Theme;
+import com.condation.cms.content.RenderContext;
+import com.condation.cms.content.template.functions.shortcode.ShortCodeTemplateFunction;
import com.condation.cms.templates.CMSTemplateEngine;
+import com.condation.cms.templates.DynamicConfiguration;
import com.condation.cms.templates.TemplateEngineFactory;
import com.condation.cms.templates.TemplateLoader;
import com.condation.cms.templates.loaders.CompositeTemplateLoader;
@@ -108,13 +111,19 @@ public void updateTheme(Theme theme) {
public String render(String template, Model model) throws IOException {
var cmsTemplate = templateEngine.getTemplate(template);
- return cmsTemplate.evaluate(model.values);
+ return cmsTemplate.evaluate(model.values, createDynamicConfiguration(model));
+ }
+
+ private DynamicConfiguration createDynamicConfiguration(Model model) {
+ var shortCodes = model.requestContext.get(RenderContext.class).shortCodes();
+ DynamicConfiguration dynamicConfig = new DynamicConfiguration(shortCodes);
+ return dynamicConfig;
}
@Override
public String renderFromString(String templateString, Model model) throws IOException {
var template = templateEngine.getTemplateFromString(templateString);
- return template.evaluate(model.values);
+ return template.evaluate(model.values, createDynamicConfiguration(model));
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/HookSystemRegisterExtentionPoint.java b/cms-templates/src/main/java/com/condation/cms/templates/parser/ComponentNode.java
similarity index 60%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/HookSystemRegisterExtentionPoint.java
rename to cms-templates/src/main/java/com/condation/cms/templates/parser/ComponentNode.java
index 540fbbd7f..547f51541 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/HookSystemRegisterExtentionPoint.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/parser/ComponentNode.java
@@ -1,8 +1,12 @@
-package com.condation.cms.api.extensions;
+package com.condation.cms.templates.parser;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.jexl3.JexlExpression;
/*-
* #%L
- * cms-api
+ * templates
* %%
* Copyright (C) 2023 - 2024 CondationCMS
* %%
@@ -22,19 +26,19 @@
* #L%
*/
-
-import com.condation.cms.api.hooks.HookSystem;
-
-/**
- * ExtensionPoint for modules to register hooks.
- *
- * @deprecated As of release 7.2.0, replaced by {@link HookSystemRegisterExtensionPoint}
- *
- * @author thmar
- */
-@Deprecated(since = "7.2.0", forRemoval = true)
-public abstract class HookSystemRegisterExtentionPoint extends AbstractExtensionPoint{
-
- public abstract void register (final HookSystem hookSystem);
+public class ComponentNode extends ASTNode {
+ @Getter
+ @Setter
+ private String name;
+ @Getter
+ @Setter
+ private String parameters;
+ public ComponentNode(int line, int column) {
+ super(line, column);
+ }
+ @Override
+ public String toString() {
+ return "ComponentNode('" + name + ", " + parameters + "')";
+ }
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/parser/Parser.java b/cms-templates/src/main/java/com/condation/cms/templates/parser/Parser.java
index d659599d2..2e71250aa 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/parser/Parser.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/parser/Parser.java
@@ -22,6 +22,8 @@
* #L%
*/
+import com.condation.cms.templates.Component;
+import com.condation.cms.templates.DynamicConfiguration;
import com.condation.cms.templates.lexer.TokenStream;
import com.condation.cms.templates.Tag;
import com.condation.cms.templates.TemplateConfiguration;
@@ -31,6 +33,8 @@
import java.util.Stack;
import com.condation.cms.templates.lexer.Token;
+import static com.condation.cms.templates.lexer.Token.Type.TAG_END;
+import static com.condation.cms.templates.lexer.Token.Type.TAG_START;
import lombok.RequiredArgsConstructor;
import org.apache.commons.jexl3.JexlEngine;
@@ -41,7 +45,11 @@ public class Parser {
private final JexlEngine engine;
- public ASTNode parse(final TokenStream tokenStream) {
+ public ASTNode parse (final TokenStream tokenStream) {
+ return _parse(tokenStream, new ParserConfiguration(configuration));
+ }
+
+ private ASTNode _parse(final TokenStream tokenStream, final ParserConfiguration parserConfiguration) {
ASTNode root = new ASTNode(0, 0);
Stack nodeStack = new Stack<>();
nodeStack.push(root);
@@ -81,15 +89,15 @@ public ASTNode parse(final TokenStream tokenStream) {
}
case TAG_END: {
if (!nodeStack.isEmpty() && nodeStack.peek() instanceof TagNode tempNode) {
- if (configuration.hasTag(tempNode.getName())) {
- Tag tag = configuration.getTag(tempNode.getName()).get();
+ if (parserConfiguration.hasTag(tempNode.getName())) {
+ Tag tag = parserConfiguration.getTag(tempNode.getName()).get();
if (tag.isClosingTag()) {
nodeStack.pop();
var temp = (TagNode) nodeStack.peek();
- var ptag = configuration.getTag(temp.getName()).get();
+ var ptag = parserConfiguration.getTag(temp.getName()).get();
if (ptag.getCloseTagName().isPresent()
&& ptag.getCloseTagName().get().equals(tag.getTagName())) {
@@ -109,6 +117,36 @@ public ASTNode parse(final TokenStream tokenStream) {
}
break;
}
+ case COMPONENT_START: {
+ ComponentNode tagNode = new ComponentNode(token.line, token.column);
+
+ nodeStack.peek().addChild(tagNode);
+ nodeStack.push(tagNode); // In den neuen Kontext für Tags wechseln
+ break;
+ }
+ case COMPONENT_END: {
+ if (!nodeStack.isEmpty() && nodeStack.peek() instanceof ComponentNode tempNode) {
+
+ var compName = tempNode.getName();
+ var isClosing = compName.startsWith("end");
+ var startName = compName.replaceFirst("end", "");
+
+ if (isClosing) {
+ nodeStack.pop();
+
+ var temp = (ComponentNode) nodeStack.peek();
+
+ if (temp.getName().equals(startName)) {
+ nodeStack.pop();
+ } else {
+ throw new ParserException("invalid closing component", token.line, token.column);
+ }
+ }
+ } else {
+ throw new ParserException("Unexpected token: COMPONENT_END", token.line, token.column);
+ }
+ break;
+ }
case VARIABLE_END: {
if (!nodeStack.isEmpty()) {
nodeStack.pop(); // Aus dem aktuellen Tag-/Variable-Block heraustreten
@@ -128,7 +166,7 @@ public ASTNode parse(final TokenStream tokenStream) {
case IDENTIFIER: {
ASTNode currentNode = nodeStack.peek();
if (currentNode instanceof TagNode tagNode1) {
- tagNode1.setName(token.value); // Tag-Name setzen
+ tagNode1.setName(token.value);
} else if (currentNode instanceof VariableNode variableNode1) {
var identifier = token.value;
if (TemplateUtils.hasFilters(identifier)) {
@@ -146,6 +184,8 @@ public ASTNode parse(final TokenStream tokenStream) {
variableNode1.setVariable(token.value); // Variable setzen
variableNode1.setExpression(engine.createExpression(token.value));
}
+ } else if (currentNode instanceof ComponentNode compNode) {
+ compNode.setName(token.value);
}
break;
}
@@ -154,16 +194,16 @@ public ASTNode parse(final TokenStream tokenStream) {
if (currentNode instanceof TagNode tagNode) {
tagNode.setCondition(token.value);
- if (configuration.getTag(tagNode.getName()).isEmpty()) {
+ if (parserConfiguration.getTag(tagNode.getName()).isEmpty()) {
throw new UnknownTagException("unkown tag (%s)".formatted(tagNode.getName()), currentNode.getLine(), currentNode.getColumn());
}
- Tag tag = configuration.getTag(tagNode.getName()).get();
+ Tag tag = parserConfiguration.getTag(tagNode.getName()).get();
if (tag.parseExpressions()) {
tagNode.setExpression(engine.createExpression(token.value));
}
- } else if (currentNode instanceof TagNode vNode) {
-
+ } else if (currentNode instanceof ComponentNode compNode) {
+ compNode.setParameters(token.value);
}
break;
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateEngineProviderExtentionPoint.java b/cms-templates/src/main/java/com/condation/cms/templates/parser/ParserConfiguration.java
similarity index 57%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/TemplateEngineProviderExtentionPoint.java
rename to cms-templates/src/main/java/com/condation/cms/templates/parser/ParserConfiguration.java
index f3c1b1fe6..facc9d2fd 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/TemplateEngineProviderExtentionPoint.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/parser/ParserConfiguration.java
@@ -1,8 +1,8 @@
-package com.condation.cms.api.extensions;
+package com.condation.cms.templates.parser;
/*-
* #%L
- * cms-api
+ * cms-templates
* %%
* Copyright (C) 2023 - 2024 CondationCMS
* %%
@@ -22,19 +22,23 @@
* #L%
*/
-
-import com.condation.cms.api.template.TemplateEngine;
+import com.condation.cms.templates.Component;
+import com.condation.cms.templates.DynamicConfiguration;
+import com.condation.cms.templates.Tag;
+import com.condation.cms.templates.TemplateConfiguration;
+import java.util.Optional;
/**
*
- * @deprecated As of release 7.2.0, replaced by {@link TemplateEngineProviderExtensionPoint}
- *
* @author t.marx
*/
-@Deprecated(since = "7.2.0", forRemoval = true)
-public abstract class TemplateEngineProviderExtentionPoint extends AbstractExtensionPoint {
-
- public abstract String getName ();
- public abstract TemplateEngine getTemplateEngine ();
+public record ParserConfiguration(TemplateConfiguration templateEngineConfiguration) {
+
+ public boolean hasTag (String name) {
+ return templateEngineConfiguration.hasTag(name);
+ }
+ public Optional getTag (String name) {
+ return templateEngineConfiguration.getTag(name);
+ }
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/renderer/RenderConfiguration.java b/cms-templates/src/main/java/com/condation/cms/templates/renderer/RenderConfiguration.java
new file mode 100644
index 000000000..f5b2558ab
--- /dev/null
+++ b/cms-templates/src/main/java/com/condation/cms/templates/renderer/RenderConfiguration.java
@@ -0,0 +1,59 @@
+package com.condation.cms.templates.renderer;
+
+/*-
+ * #%L
+ * cms-templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+import com.condation.cms.templates.Component;
+import com.condation.cms.templates.DynamicConfiguration;
+import com.condation.cms.templates.Tag;
+import com.condation.cms.templates.TemplateConfiguration;
+import java.util.Optional;
+
+/**
+ *
+ * @author t.marx
+ */
+public record RenderConfiguration(TemplateConfiguration templateEngineConfiguration, DynamicConfiguration dynamicConfiguration) {
+
+ public RenderConfiguration(TemplateConfiguration templateConfiguration) {
+ this(templateConfiguration, null);
+ }
+
+ public boolean hasTag(String tagName) {
+ return templateEngineConfiguration.hasTag(tagName);
+ }
+
+ public Optional getTag(String tagName) {
+ return templateEngineConfiguration.getTag(tagName);
+ }
+
+ public boolean hasComponent(String name) {
+ return (dynamicConfiguration != null && dynamicConfiguration.hasComponent(name));
+ }
+
+ public Optional getComponent(String name) {
+ if (dynamicConfiguration != null && dynamicConfiguration.hasComponent(name)) {
+ return dynamicConfiguration.getComponent(name);
+ }
+
+ return Optional.empty();
+ }
+}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/renderer/Renderer.java b/cms-templates/src/main/java/com/condation/cms/templates/renderer/Renderer.java
index 19b37cd2d..0c25c91e8 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/renderer/Renderer.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/renderer/Renderer.java
@@ -25,7 +25,10 @@
import com.condation.cms.templates.RenderFunction;
import com.condation.cms.templates.TemplateConfiguration;
import com.condation.cms.templates.CMSTemplateEngine;
+import com.condation.cms.templates.DynamicConfiguration;
+import com.condation.cms.templates.exceptions.RenderException;
import com.condation.cms.templates.parser.ASTNode;
+import com.condation.cms.templates.parser.ComponentNode;
import com.condation.cms.templates.parser.TagNode;
import com.condation.cms.templates.parser.TextNode;
import com.condation.cms.templates.parser.VariableNode;
@@ -70,11 +73,17 @@ public ScopeContext createEngineContext() {
}
}
- public void render(ASTNode node, final ScopeStack scopes, final Writer writer) throws IOException {
+ public void render(ASTNode node, final ScopeStack scopes, final Writer writer, final DynamicConfiguration dynamicConfiguration) throws IOException {
+
+ var renderConfig = new RenderConfiguration(configuration, dynamicConfiguration);
+
+ var renderFunction = (RenderFunction) (ASTNode node1, Context context, Writer writer1) -> {
+ renderNode(node1, context, writer1, renderConfig);
+ };
var contentWriter = new StringWriter();
- final Context renderContext = new Context(engine, scopes, this::renderNode, templateEngine);
- renderNode(node, renderContext, contentWriter);
+ final Context renderContext = new Context(engine, scopes, renderFunction, templateEngine);
+ renderFunction.render(node, renderContext, contentWriter);
if (renderContext.context().containsKey("_extends")) {
ExtendsTag.Extends ext = (ExtendsTag.Extends) renderContext.context().get("_extends");
@@ -83,7 +92,7 @@ public void render(ASTNode node, final ScopeStack scopes, final Writer writer) t
StringWriter parentWriter = new StringWriter();
renderContext.context().put("_parent", Boolean.TRUE);
- renderNode(parentTemplate.getRootNode(), renderContext, parentWriter);
+ renderFunction.render(parentTemplate.getRootNode(), renderContext, parentWriter);
writer.write(parentWriter.toString());
} else {
@@ -91,20 +100,32 @@ public void render(ASTNode node, final ScopeStack scopes, final Writer writer) t
}
}
- private void renderNode(ASTNode node, Context context, Writer writer) throws IOException {
+ private void renderNode(ASTNode node, Context context, Writer writer, RenderConfiguration renderConfiguration) throws IOException {
- if (node instanceof TextNode textNode) {
- writer.write(textNode.text);
- } else if (node instanceof VariableNode vnode) {
- renderVariable(vnode, context, writer);
- } else if (node instanceof TagNode tagNode) {
- var tag = configuration.getTag(tagNode.getName());
- if (tag.isPresent()) {
- tag.get().render(tagNode, context, writer);
+ switch (node) {
+ case TextNode textNode -> writer.write(textNode.text);
+ case VariableNode vnode -> renderVariable(vnode, context, writer);
+ case TagNode tagNode -> {
+ var tag = renderConfiguration.getTag(tagNode.getName());
+ if (tag.isPresent()) {
+ tag.get().render(tagNode, context, writer);
+ } else if (this.configuration.isDevMode()) {
+ throw new RenderException("unknown tag", node.getLine(), node.getColumn());
+ }
}
- } else {
- for (ASTNode child : node.getChildren()) {
- renderNode(child, context, writer);
+ case ComponentNode componentNode -> {
+ var component = renderConfiguration.getComponent(componentNode.getName());
+ if (component.isPresent()) {
+ component.get().render(componentNode, context, writer);
+ } else if (this.configuration.isDevMode()) {
+ throw new RenderException("unknown component", node.getLine(), node.getColumn());
+ }
+
+ }
+ default -> {
+ for (ASTNode child : node.getChildren()) {
+ renderNode(child, context, writer, renderConfiguration);
+ }
}
}
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/tags/ForTag.java b/cms-templates/src/main/java/com/condation/cms/templates/tags/ForTag.java
index 790f8375c..e3f9b9ea1 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/tags/ForTag.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/tags/ForTag.java
@@ -54,7 +54,6 @@ public Optional getCloseTagName() {
public void render(TagNode node, Renderer.Context context, Writer writer) {
var forCondition = parseForLoop(node);
- var collectionVariable = context.scopes().getVariable(forCondition.collection);
var colExp = context.engine().createExpression(forCondition.collection);
var collection = colExp.evaluate(context.createEngineContext());
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java
new file mode 100644
index 000000000..96cf57512
--- /dev/null
+++ b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java
@@ -0,0 +1,90 @@
+package com.condation.cms.templates.tags.component;
+
+/*-
+ * #%L
+ * cms-templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.condation.cms.content.shortcodes.ShortCodes;
+import com.condation.cms.templates.Component;
+import com.condation.cms.templates.exceptions.RenderException;
+import com.condation.cms.templates.parser.ComponentNode;
+import com.condation.cms.templates.renderer.Renderer;
+import com.condation.cms.templates.utils.ParameterUtil;
+import com.google.common.base.Strings;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Optional;
+import lombok.RequiredArgsConstructor;
+
+/**
+ *
+ * @author t.marx
+ */
+@RequiredArgsConstructor
+public class ComponentTag implements Component {
+
+ private final String shortCodeName;
+
+ private final ShortCodes shortCodes;
+
+ @Override
+ public String getName() {
+ return shortCodeName;
+ }
+
+
+ @Override
+ public Optional getCloseingName() {
+ return Optional.of("end%s".formatted(shortCodeName));
+ }
+
+ @Override
+ public void render(ComponentNode node, Renderer.Context context, Writer writer) {
+ try {
+
+ var params = ParameterUtil.parseAndEvaluate(node.getParameters(), context.createEngineContext(), context.engine());
+ var content = renderChildren(node, context);
+
+ params.put("_content", content);
+
+ var shortCodeResult = shortCodes.execute(shortCodeName, params);
+ if (!Strings.isNullOrEmpty(shortCodeResult)) {
+ writer.write(shortCodeResult);
+ }
+ } catch (Exception e) {
+ throw new RenderException(e.getMessage(), node.getLine(), node.getColumn());
+ }
+ }
+
+ private String renderChildren(ComponentNode node, Renderer.Context context) {
+ try {
+ StringWriter writer = new StringWriter();
+ for (var child : node.getChildren()) {
+ context.renderer().render(child, context, writer);
+ }
+ return writer.toString();
+ } catch (IOException ioe) {
+ throw new RenderException(ioe.getMessage(), node.getLine(), node.getColumn());
+ }
+ }
+
+}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContextFactory.java b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/EndComponentTag.java
similarity index 65%
rename from modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContextFactory.java
rename to cms-templates/src/main/java/com/condation/cms/templates/tags/component/EndComponentTag.java
index 0323f9b0e..5b4377d86 100644
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContextFactory.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/EndComponentTag.java
@@ -1,8 +1,8 @@
-package com.condation.modules.api;
+package com.condation.cms.templates.tags.component;
/*-
* #%L
- * modules-api
+ * cms-templates
* %%
* Copyright (C) 2023 - 2024 CondationCMS
* %%
@@ -22,12 +22,25 @@
* #L%
*/
+import com.condation.cms.templates.Component;
+import lombok.RequiredArgsConstructor;
/**
*
* @author t.marx
*/
-public interface ModuleRequestContextFactory {
+@RequiredArgsConstructor
+public class EndComponentTag implements Component {
- ModuleRequestContext createContext ();
+ private final String shortCodeName;
+
+ @Override
+ public String getName() {
+ return "end%s".formatted(shortCodeName);
+ }
+
+ @Override
+ public boolean isClosing() {
+ return true;
+ }
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/tags/macro/ImportTag.java b/cms-templates/src/main/java/com/condation/cms/templates/tags/macro/ImportTag.java
index d1395762d..944d0f5bb 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/tags/macro/ImportTag.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/tags/macro/ImportTag.java
@@ -112,7 +112,7 @@ public void setVariable(String name, Object value) {
}
// Method to parse the import statement
- public static ImportDefinition parseImport(String importStatement, TagNode node) {
+ private ImportDefinition parseImport(String importStatement, TagNode node) {
Matcher matcher = PATTERN.matcher(importStatement.trim());
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/utils/ParameterUtil.java b/cms-templates/src/main/java/com/condation/cms/templates/utils/ParameterUtil.java
new file mode 100644
index 000000000..3ee45fa4a
--- /dev/null
+++ b/cms-templates/src/main/java/com/condation/cms/templates/utils/ParameterUtil.java
@@ -0,0 +1,101 @@
+package com.condation.cms.templates.utils;
+
+/*-
+ * #%L
+ * cms-templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.condation.cms.templates.renderer.Renderer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.JexlEngine;
+import org.apache.commons.jexl3.JexlExpression;
+
+/**
+ *
+ * @author t.marx
+ */
+public class ParameterUtil {
+ public static Map parseAndEvaluate(String input, JexlContext jexlContext, JexlEngine engine) {
+ Map resultMap = new HashMap<>();
+
+ // Tokenize den Eingabestring (Leerzeichen als Trennung der Parameter)
+ List tokens = tokenize(input);
+
+ for (String token : tokens) {
+ int equalsIndex = token.indexOf('=');
+ if (equalsIndex > 0) {
+ String key = token.substring(0, equalsIndex).trim(); // Schlüssel extrahieren
+ String value = token.substring(equalsIndex + 1).trim(); // Wert extrahieren
+
+ // Anführungszeichen entfernen, falls vorhanden
+ if (value.startsWith("\"") && value.endsWith("\"")) {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ // Wert mit JEXL evaluieren
+ Object evaluatedValue;
+ try {
+ JexlExpression expression = engine.createExpression(value);
+ evaluatedValue = expression.evaluate(jexlContext);
+ } catch (Exception e) {
+ // Falls der Wert keine JEXL-Expression ist, einfach als String speichern
+ evaluatedValue = value;
+ }
+
+ resultMap.put(key, evaluatedValue);
+ }
+ }
+
+ return resultMap;
+ }
+
+ private static List tokenize(String input) {
+ List tokens = new ArrayList<>();
+ StringBuilder currentToken = new StringBuilder();
+ boolean inQuotes = false;
+
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+
+ if (c == '"') {
+ inQuotes = !inQuotes; // Zustand der Anführungszeichen umkehren
+ currentToken.append(c);
+ } else if (c == ' ' && !inQuotes) {
+ // Bei Leerzeichen trennen, sofern nicht in Anführungszeichen
+ if (currentToken.length() > 0) {
+ tokens.add(currentToken.toString());
+ currentToken.setLength(0);
+ }
+ } else {
+ currentToken.append(c);
+ }
+ }
+
+ if (currentToken.length() > 0) {
+ tokens.add(currentToken.toString());
+ }
+
+ return tokens;
+ }
+}
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java
new file mode 100644
index 000000000..6c49c3109
--- /dev/null
+++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java
@@ -0,0 +1,133 @@
+package com.condation.cms.templates;
+
+/*-
+ * #%L
+ * templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+import com.condation.cms.content.shortcodes.ShortCodes;
+import com.condation.cms.content.shortcodes.TagParser;
+import com.condation.cms.templates.exceptions.ParserException;
+import com.condation.cms.templates.exceptions.RenderException;
+import com.condation.cms.templates.loaders.StringTemplateLoader;
+import java.io.IOException;
+import java.util.Map;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * @author thmar
+ */
+public class TemplateEngineComponentTest extends AbstractTemplateEngineTest {
+
+ static ShortCodes shortCodes;
+ static DynamicConfiguration dynamicConfiguration;
+
+ @BeforeAll
+ public void setupShortCodes() {
+ shortCodes = new ShortCodes(
+ Map.of(
+ "tag1", (params) -> {
+ return "Hello";
+ },
+ "tag2", (param) -> {
+ return "Hello " + param.get("name") + "!";
+ },
+ "tag3", (param) -> {
+ return "%s
".formatted(param.get("_content"));
+ }),
+ new TagParser(null)
+ );
+ dynamicConfiguration = new DynamicConfiguration(shortCodes);
+ }
+
+ @Override
+ public TemplateLoader getLoader() {
+ return new StringTemplateLoader()
+ .add("tag1", """
+ {[ tag1 ]}
+
+ {[ endtag1 ]}
+ """)
+ .add("tag2", """
+ {[ tag2 name="CondationCMS" ]}
+ {[ endtag2 ]}
+ """)
+ .add("tag3", """
+ {[ tag3 ]}
+ This is the content!
+ {[ endtag3 ]}
+ """)
+ .add("parser_exception", """
+ {[ tag3 ]}
+ This is the content!
+ {[ endtag4 ]}
+ """)
+ .add("render_exception", """
+ {[ tag4 ]}
+ This is the content!
+ {[ endtag4 ]}
+ """);
+ }
+
+ @Test
+ public void test_tag1() throws IOException {
+ Template simpleTemplate = SUT.getTemplate("tag1");
+ Assertions.assertThat(simpleTemplate).isNotNull();
+
+ Assertions
+ .assertThat(simpleTemplate.evaluate(Map.of(), dynamicConfiguration))
+ .isEqualToIgnoringWhitespace("Hello");
+ }
+
+ @Test
+ public void test_tag2() throws IOException {
+ Template simpleTemplate = SUT.getTemplate("tag2");
+ Assertions.assertThat(simpleTemplate).isNotNull();
+
+ Assertions
+ .assertThat(simpleTemplate.evaluate(Map.of(), dynamicConfiguration))
+ .isEqualToIgnoringWhitespace("Hello CondationCMS!");
+ }
+
+ @Test
+ public void test_tag3() throws IOException {
+ Template simpleTemplate = SUT.getTemplate("tag3");
+ Assertions.assertThat(simpleTemplate).isNotNull();
+
+ Assertions
+ .assertThat(simpleTemplate.evaluate(Map.of(), dynamicConfiguration))
+ .isEqualToIgnoringWhitespace("This is the content!
");
+ }
+
+ @Test
+ public void test_parser_exception() throws IOException {
+ Assertions.assertThatThrownBy(() -> SUT.getTemplate("parser_exception"))
+ .isInstanceOf(ParserException.class);
+ }
+
+ @Test
+ public void test_render_exception() throws IOException {
+ var template = SUT.getTemplate("render_exception");
+ Assertions.assertThatThrownBy(() -> template.evaluate(Map.of(), dynamicConfiguration))
+ .isInstanceOf(RenderException.class);
+ }
+}
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
index 83d2e0fa3..513da71bd 100644
--- a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
+++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
@@ -21,6 +21,8 @@
* .
* #L%
*/
+import com.condation.cms.content.shortcodes.ShortCodes;
+import com.condation.cms.content.shortcodes.TagParser;
import com.condation.cms.templates.loaders.StringTemplateLoader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -56,7 +58,8 @@ public TemplateLoader getLoader() {
"variable_raw_filter",
"variable_1",
"for_1",
- "if_1"
+ "if_1",
+ "component_1"
})
void test_features(String templateFile) throws Exception {
var templateContent = readContent(templateFile + ".html");
@@ -68,11 +71,20 @@ void test_features(String templateFile) throws Exception {
var template = SUT.getTemplate(templateFile);
- var rendered = template.evaluate(data);
+ var rendered = template.evaluate(data, createDynamicConfig());
Assertions.assertThat(rendered).isEqualToIgnoringWhitespace(expectedContent);
}
+ private DynamicConfiguration createDynamicConfig () {
+ ShortCodes shortCodes = new ShortCodes(
+ Map.of(
+ "hello", (params) -> "hello " + params.get("name")
+ ),
+ new TagParser(null));
+ return new DynamicConfiguration(shortCodes);
+ }
+
private Map getData (String filename) throws IOException {
String dataFile = filename + "_data.json";
if (!exists(dataFile)) {
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/lexer/LexerTest.java b/cms-templates/src/test/java/com/condation/cms/templates/lexer/LexerTest.java
index 9daa26d5b..f6a52f8a9 100644
--- a/cms-templates/src/test/java/com/condation/cms/templates/lexer/LexerTest.java
+++ b/cms-templates/src/test/java/com/condation/cms/templates/lexer/LexerTest.java
@@ -98,6 +98,24 @@ public void test_tag() throws IOException {
token = tokens.next();
Assertions.assertThat(token.type).isEqualTo(Token.Type.TAG_END);
}
+
+ @Test
+ public void test_component() throws IOException {
+
+ var lexer = new Lexer();
+
+ var tokens = lexer.tokenize("{[ comp1 param1=\"value1\" param2=55 ]}");
+
+ Token token = tokens.next();
+ Assertions.assertThat(token.type).isEqualTo(Token.Type.COMPONENT_START);
+ token = tokens.next();
+ Assertions.assertThat(token.type).isEqualTo(Token.Type.IDENTIFIER);
+ Assertions.assertThat(token.value.trim()).isEqualTo("comp1");
+ token = tokens.next();
+ Assertions.assertThat(token.type).isEqualTo(Token.Type.EXPRESSION);
+ token = tokens.next();
+ Assertions.assertThat(token.type).isEqualTo(Token.Type.COMPONENT_END);
+ }
@Test
public void test_tag_with_condition_quoted() throws IOException {
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/utils/ParameterUtilTest.java b/cms-templates/src/test/java/com/condation/cms/templates/utils/ParameterUtilTest.java
new file mode 100644
index 000000000..297ddda53
--- /dev/null
+++ b/cms-templates/src/test/java/com/condation/cms/templates/utils/ParameterUtilTest.java
@@ -0,0 +1,54 @@
+package com.condation.cms.templates.utils;
+
+/*-
+ * #%L
+ * cms-templates
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import org.apache.commons.jexl3.JexlBuilder;
+import org.apache.commons.jexl3.JexlEngine;
+import org.apache.commons.jexl3.MapContext;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * @author t.marx
+ */
+public class ParameterUtilTest {
+
+ JexlEngine engine = new JexlBuilder().create();
+
+ @Test
+ public void testSomeMethod() {
+
+ var context = new MapContext();
+ context.set("variable", "CMS");
+
+ var parameters = ParameterUtil.parseAndEvaluate("param1=\"CondationCMS\" param2=30 param3=variable", context, engine);
+
+ Assertions.assertThat(parameters)
+ .hasSize(3)
+ .containsEntry("param1", "CondationCMS")
+ .containsEntry("param2", 30)
+ .containsEntry("param3", "CMS");
+ }
+
+}
diff --git a/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1.html b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1.html
new file mode 100644
index 000000000..18c3ec03c
--- /dev/null
+++ b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1.html
@@ -0,0 +1,23 @@
+
+{[ hello name="CondationCMS" ]}
+{[ endhello ]}
diff --git a/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_data.json b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_data.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_data.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_expected.html b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_expected.html
new file mode 100644
index 000000000..bcfab4e95
--- /dev/null
+++ b/cms-templates/src/test/resources/com/condation/cms/templates/testdata/component_1_expected.html
@@ -0,0 +1,22 @@
+
+hello CondationCMS
diff --git a/cms-test/pom.xml b/cms-test/pom.xml
index f59fd391d..a2a37478d 100644
--- a/cms-test/pom.xml
+++ b/cms-test/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
cms-test
jar
diff --git a/distribution/build.xml b/distribution/build.xml
index f2f16f646..ab1ebee05 100644
--- a/distribution/build.xml
+++ b/distribution/build.xml
@@ -1,6 +1,6 @@
- 7.4.2
+ 7.5.0
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index bd1ebf479..ae6d5fcd8 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
integration-tests
jar
diff --git a/modules-framework/api/pom.xml b/modules-framework/api/pom.xml
deleted file mode 100644
index 4f8446453..000000000
--- a/modules-framework/api/pom.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
- 4.0.0
-
- com.condation.cms.module.framework
- module-framework
- 7.4.2
-
- modules-api
- jar
-
-
-
- com.google.code.gson
- gson
-
-
-
\ No newline at end of file
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/BaseExtension.java b/modules-framework/api/src/main/java/com/condation/modules/api/BaseExtension.java
deleted file mode 100644
index 1ae856b6c..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/BaseExtension.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-/**
- *
- * @author marx
- * @param
- */
-public abstract class BaseExtension implements ExtensionPoint {
-
- protected ModuleConfiguration configuration;
-
- private C context;
-
- private R requestContext;
-
- @Override
- public void setContext(C context) {
- this.context = context;
- }
-
- public C getContext () {
- return this.context;
- }
-
- @Override
- public void setRequestContext(R context) {
- this.requestContext = requestContext;
- }
-
- public R getRequestContext () {
- return this.requestContext;
- }
-
- @Override
- public void setConfiguration(ModuleConfiguration configuration) {
- this.configuration = configuration;
- }
-
-
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/Context.java b/modules-framework/api/src/main/java/com/condation/modules/api/Context.java
deleted file mode 100644
index e1e323792..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/Context.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-/**
- * The Context is passed to the module. It can be used to inject implementation dependend objects or functionality
- *
- * @author marx
- */
-public interface Context {
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ExtensionPoint.java b/modules-framework/api/src/main/java/com/condation/modules/api/ExtensionPoint.java
deleted file mode 100644
index 92a7eee1f..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ExtensionPoint.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-
-
-/**
- *
- * @author marx
- * @param
- */
-public interface ExtensionPoint {
- void setConfiguration (ModuleConfiguration configuration);
-
- void setContext (C context);
-
- void setRequestContext (R context);
-
- void init ();
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ManagerConfiguration.java b/modules-framework/api/src/main/java/com/condation/modules/api/ManagerConfiguration.java
deleted file mode 100644
index 9b0748d3b..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ManagerConfiguration.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- *
- * @author thmarx
- */
-public class ManagerConfiguration {
-
- private ConcurrentMap modules = new ConcurrentHashMap<>();
-
- public ManagerConfiguration () {
-
- }
-
- public ConcurrentMap getModules() {
- return modules;
- }
-
- public void setModules(ConcurrentMap modules) {
- this.modules = modules;
- }
-
- public ModuleConfig get (final String moduleId) {
- return modules.get(moduleId);
- }
- public void add (final ModuleConfig config) {
- modules.put(config.getId(), config);
- }
- public void remove (final String moduleId) {
- modules.remove(moduleId);
- }
-
- public static class ModuleConfig {
-
- private boolean active = false;
-
- private String id;
-
- private String moduleDir;
-
- private String moduleDataDir;
-
- public ModuleConfig () {
-
- }
- public ModuleConfig (final String id) {
- this.id = id;
- }
-
- public void setId (final String id) {
- this.id = id;
- }
-
- public String getId () {
- return id;
- }
-
- public boolean isActive() {
- return active;
- }
-
- public void setActive(boolean active) {
- this.active = active;
- }
-
- public String getModuleDir() {
- return moduleDir;
- }
-
- public ModuleConfig setModuleDir(String moduleDir) {
- this.moduleDir = moduleDir;
- return this;
- }
-
- public String getModuleDataDir() {
- return moduleDataDir;
- }
-
- public ModuleConfig setModuleDataDir(String moduleDataDir) {
- this.moduleDataDir = moduleDataDir;
-
- return this;
- }
-
-
-
- @Override
- public int hashCode() {
- int hash = 3;
- hash = 37 * hash + Objects.hashCode(this.id);
- return hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final ModuleConfig other = (ModuleConfig) obj;
- if (!Objects.equals(this.id, other.id)) {
- return false;
- }
- return true;
- }
-
-
- }
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleConfiguration.java b/modules-framework/api/src/main/java/com/condation/modules/api/ModuleConfiguration.java
deleted file mode 100644
index 9bede7137..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleConfiguration.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Properties;
-
-/**
- *
- * @author thmarx
- */
-public class ModuleConfiguration {
-
- private final Properties properties = new Properties();
-
- final File configFile;
-
- final File dataDirectory;
-
- public ModuleConfiguration (final File path) throws IOException{
- configFile = new File(path, "configuration.properties");
- if (!configFile.exists()) {
- configFile.createNewFile();
- }
- properties.load(new FileReader(configFile));
-
- this.dataDirectory = new File(path.toURI());
- }
-
- public File getDataDir () {
- return dataDirectory;
- }
-
-
- /**
- * Stores the module configuration in the data directory for this module.
- *
- * @throws IOException
- */
- public void store () throws IOException {
- properties.store(new FileWriter(configFile), "module configuraion saved");
- }
- /**
- * Returns a configuration property value.
- *
- * @param key The key of the property.
- * @param defaultValue The default value to return.
- * @return The value for the key or the default value.
- */
- public Object get (final String key, final Object defaultValue) {
- return properties.getOrDefault(key, defaultValue);
- }
- /**
- * Returns a configuration property value as int.
- *
- * @param key The key of the property.
- * @param defaultValue The default value to return.
- * @return The value for the key or the default value.
- */
- public int getInt (final String key, final int defaultValue) {
- Object value = properties.get(key);
- if (value != null) {
- if (value instanceof Integer) {
- return (int) value;
- } else {
- return Integer.parseInt(((String)value).trim());
- }
- }
- return defaultValue;
- }
- /**
- * Returns a configuration property value as String.
- *
- * @param key The key of the property.
- * @param defaultValue The default value to return.
- * @return The value for the key or the default value.
- */
- public String getString (final String key, final String defaultValue) {
- Object value = properties.get(key);
- if (value != null) {
- if (value instanceof String) {
- return (String) value;
- } else {
- return String.valueOf(value);
- }
- }
- return defaultValue;
- }
-
- /**
- * Sets a configuration property.
- *
- * @param key The property key.
- * @param value The property value.
- */
- public void set (final String key, final Object value) {
- properties.put(key, value);
- }
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleDescription.java b/modules-framework/api/src/main/java/com/condation/modules/api/ModuleDescription.java
deleted file mode 100644
index 603076674..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleDescription.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-/**
- *
- * @author marx
- */
-public class ModuleDescription {
- private String name;
- private String description;
- private String version;
-
- public ModuleDescription () {
-
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getVersion() {
- return version;
- }
-
- public void setVersion(String version) {
- this.version = version;
- }
-
-
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleLifeCycleExtension.java b/modules-framework/api/src/main/java/com/condation/modules/api/ModuleLifeCycleExtension.java
deleted file mode 100644
index 86be03b42..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleLifeCycleExtension.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-
-
-/**
- *
- * @author marx
- */
-public abstract class ModuleLifeCycleExtension extends BaseExtension {
- /**
- * Called when the module is activated.
- */
- public void activate () {};
- /**
- * called when the module is deactivated.
- */
- public void deactivate () {};
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleManager.java b/modules-framework/api/src/main/java/com/condation/modules/api/ModuleManager.java
deleted file mode 100644
index e559536c9..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleManager.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- *
- * @author marx
- */
-public interface ModuleManager extends AutoCloseable {
-
- /**
- * activates a module.
- *
- * @param moduleId
- * @return returns true if the module is correctly or allready installed, otherwise false
- * @throws java.io.IOException
- */
- boolean activateModule(final String moduleId) throws IOException;
-
- /**
- *
- * @param moduleId
- * @return
- */
- boolean deactivateModule(final String moduleId) throws IOException;
-
- void initModules();
-
- /**
- * Returns the module description.
- * @param id
- * @return
- * @throws IOException
- */
- ModuleDescription description(final String id) throws IOException;
-
- /**
- * Returns all Extensions of the given type.
- *
- * @param
- * @param extensionClass
- * @return
- */
- List extensions(Class extensionClass);
-
- public Module module(final String id);
-
- /**
- * Returns the configuration of the module manager.
- *
- * @return
- */
- public ManagerConfiguration configuration();
-
- /**
- * Returns a list of all available module ids.
- *
- * @return
- */
- public List getModuleIds ();
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContext.java b/modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContext.java
deleted file mode 100644
index 35db574a9..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/ModuleRequestContext.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.condation.modules.api;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-/**
- * The Context is passed to the module. It can be used to inject implementation dependend objects or functionality
- *
- * @author marx
- */
-public interface ModuleRequestContext {
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/annotation/Extension.java b/modules-framework/api/src/main/java/com/condation/modules/api/annotation/Extension.java
deleted file mode 100644
index 62bab21b4..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/annotation/Extension.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.condation.modules.api.annotation;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-import com.condation.modules.api.ExtensionPoint;
-import java.lang.annotation.Documented;
-import static java.lang.annotation.ElementType.TYPE;
-import java.lang.annotation.Retention;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-import java.lang.annotation.Target;
-
-@Documented
-@Retention(SOURCE)
-@Target(TYPE)
-public @interface Extension {
- Class extends ExtensionPoint> value();
-}
diff --git a/modules-framework/api/src/main/java/com/condation/modules/api/annotation/ExtensionAnnotationProcessor.java b/modules-framework/api/src/main/java/com/condation/modules/api/annotation/ExtensionAnnotationProcessor.java
deleted file mode 100644
index 3f0ae2a41..000000000
--- a/modules-framework/api/src/main/java/com/condation/modules/api/annotation/ExtensionAnnotationProcessor.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package com.condation.modules.api.annotation;
-
-/*-
- * #%L
- * modules-api
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.nio.file.NoSuchFileException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.MirroredTypesException;
-import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic.Kind;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
-
-@SupportedAnnotationTypes("com.condation.modules.api.annotation.Extension")
-public class ExtensionAnnotationProcessor extends AbstractProcessor implements Processor {
-
- @Override
- public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.latest();
- }
-
- @Override
- public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
- if (roundEnv.processingOver()) {
- return false;
- }
- Map> extensions = new HashMap<>();
-
- Elements elements = processingEnv.getElementUtils();
-
- roundEnv.getElementsAnnotatedWith(Extension.class).stream().forEach((e) -> {
- Extension a = e.getAnnotation(Extension.class);
- if (!(a == null)) {
- if (!(!e.getKind().isClass() && !e.getKind().isInterface())) {
- TypeElement typedElement = (TypeElement) e;
- Collection teCollection = getTypeElements(typedElement, a);
- teCollection.forEach((te) -> {
- String extensionName = elements.getBinaryName(te).toString();
- String extensionImplName = elements.getBinaryName(typedElement).toString();
- if (!extensions.containsKey(extensionName)) {
- extensions.put(extensionName, new TreeSet<>());
- }
- extensions.get(extensionName).add(extensionImplName);
- });
- }
- }
- });
-
- // load existing extensions
- final Filer filer = processingEnv.getFiler();
- extensions.entrySet().stream().forEach((e) -> {
- try {
- String contract = e.getKey();
- FileObject extensionFileObject = filer.getResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/services/" + contract);
- BufferedReader r = new BufferedReader(new InputStreamReader(extensionFileObject.openInputStream(), "UTF-8"));
- String line;
- while ((line = r.readLine()) != null) {
- e.getValue().add(line);
- }
- r.close();
- } catch (FileNotFoundException fnfe) {
- // file not found
- } catch (IOException x) {
- //x.printStackTrace();
- if (NoSuchFileException.class.isInstance(x)) {
- // file not found
- } else {
- //processingEnv.getMessager().printMessage(Kind.ERROR, "Error loading existing extension files: " + x);
- }
- }
- });
-
- // now write them back out
- extensions.entrySet().stream().forEach((e) -> {
- try {
- String extension = e.getKey();
- processingEnv.getMessager().printMessage(Kind.NOTE, "Creating META-INF/services/" + extension);
- FileObject f = filer.createResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/services/" + extension);
- PrintWriter pw = new PrintWriter(new OutputStreamWriter(f.openOutputStream(), "UTF-8"));
- for (String value : e.getValue()) {
- pw.println(value);
- }
- pw.close();
- } catch (IOException x) {
- processingEnv.getMessager().printMessage(Kind.ERROR, "Error creating extension file: " + x);
- }
- });
-
- return false;
- }
-
- private Collection getTypeElements(TypeElement type, Extension a) {
- List typeElements = new ArrayList<>();
-
- try {
- a.value();
- } catch (MirroredTypesException e) {
-
- e.getTypeMirrors().stream().forEach((m) -> {
- if (m instanceof DeclaredType) {
- DeclaredType dt = (DeclaredType) m;
- typeElements.add((TypeElement) dt.asElement());
- } else {
- processingEnv.getMessager().printMessage(Kind.ERROR, "Invalid type specified", type);
- }
- });
- }
- return typeElements;
- }
-
-}
diff --git a/modules-framework/api/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/modules-framework/api/src/main/resources/META-INF/services/javax.annotation.processing.Processor
deleted file mode 100644
index 8be52f338..000000000
--- a/modules-framework/api/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ /dev/null
@@ -1 +0,0 @@
-com.condation.modules.api.annotation.ExtensionAnnotationProcessor
diff --git a/modules-framework/manager/pom.xml b/modules-framework/manager/pom.xml
deleted file mode 100644
index 04be151e2..000000000
--- a/modules-framework/manager/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 4.0.0
-
- com.condation.cms.module.framework
- module-framework
- 7.4.2
-
- modules-manager
- jar
-
-
-
- com.condation.cms.module.framework
- modules-api
-
-
- org.slf4j
- slf4j-api
-
-
- org.projectlombok
- lombok
- provided
-
-
-
-
\ No newline at end of file
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/Configuration.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/Configuration.java
deleted file mode 100644
index 5e0baecd4..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/Configuration.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.EnumMap;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author thmarx
- */
-public class Configuration {
-
- public enum Field {
- DB_DIR ("db.dir");
-
- private final String value;
-
- Field (final String value) {
- this.value = value;
- }
-
- public String value () {
- return value;
- }
- }
-
- public enum Stage {
-
- Production("production"),
- Development("development"),
- Test("test");
-
- private final String value;
- private Stage (final String value) {
- this.value = value;
- }
-
- public static Stage forStage (final String stage) {
- for (final Stage s : values()) {
- if (s.value.equals(stage)) {
- return s;
- }
- }
- throw new IllegalArgumentException("unknown stage: " + stage);
- }
- }
-
- private static final EnumMap configurations = new EnumMap<>(Stage.class);
-
- private final Properties properties = new Properties();
-
- private Configuration (){}
-
- public synchronized static Configuration empty () {
- return new Configuration();
- }
-
- public synchronized static Configuration getInstance(final File baseDir) {
- Configuration instance = new Configuration();
-
- try {
- instance.properties.load(new FileReader(new File(baseDir, "conf/configuration.properties")));
- } catch (FileNotFoundException ex) {
- Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
- }
-
- return instance;
- }
-
- public synchronized static Configuration getInstance(final Stage stage) {
- if (!configurations.containsKey(stage)) {
- Configuration INSTANCE = new Configuration();
- // loading resource using getResourceAsStream() method
- InputStream in = Configuration.class.getResourceAsStream("/configuration_" + stage.value + ".properties");
- try {
- INSTANCE.properties.load(in);
- } catch (IOException ex) {
- Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
- }
- configurations.put(stage, INSTANCE);
- }
- return configurations.get(stage);
- }
-
- public Object get (final String key, final Object defaultValue) {
- return properties.getOrDefault(key, defaultValue);
- }
- public int getInt (final String key, final int defaultValue) {
- Object value = properties.get(key);
- if (value != null) {
- if (value instanceof Integer) {
- return (int) value;
- } else {
- return Integer.parseInt(((String)value).trim());
- }
- }
- return defaultValue;
- }
-
- public String getString (final String key, final String defaultValue) {
- Object value = properties.get(key);
- if (value != null) {
- if (value instanceof String) {
- return (String) value;
- } else {
- return String.valueOf(value);
- }
- }
- return defaultValue;
- }
-
- public void set (final String key, final Object value) {
- properties.put(key, value);
- }
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleAPIClassLoader.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleAPIClassLoader.java
deleted file mode 100644
index 1fe454acd..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleAPIClassLoader.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- *
- * @author marx
- */
-public class ModuleAPIClassLoader extends ClassLoader {
-
- private final List apiPackages;
-
- private final ClassLoader parent;
-
- public ModuleAPIClassLoader(ClassLoader classLoader, List apiPackages) {
- super(classLoader);
-
- this.parent = classLoader;
- List temp = apiPackages != null ? apiPackages : new ArrayList<>();
- this.apiPackages = temp.stream().map(c -> !c.endsWith(".") ? c + "." : c).collect(Collectors.toList());
-
- this.apiPackages.add("com.condation.modules.api.");
- this.apiPackages.add("java.");
- this.apiPackages.add("javax.");
- this.apiPackages.add("com.sun.");
- this.apiPackages.add("sun.");
- }
-
- private boolean isAllowed(final String name) {
- for (String packageName : apiPackages) {
- if (name.startsWith(packageName)) {
- return true;
- }
-
- String tempname = packageName.replaceAll("\\.", "/");
- if (name.startsWith("/")) {
- tempname = "/" + tempname;
- }
- if (name.startsWith(tempname)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected Class> loadClass(String className, boolean resolve) throws ClassNotFoundException {
- if (isAllowed(className)) {
- return getParent().loadClass(className);
- }
-
- throw new ClassNotFoundException(className + "not visible");
- }
-
- @Override
- public Class> loadClass(String className) throws ClassNotFoundException {
- if (isAllowed(className)) {
- return getParent().loadClass(className);
- }
-
- throw new ClassNotFoundException(className + "not visible");
- }
-
- @Override
- protected Class> findClass(String className) throws ClassNotFoundException {
- if (isAllowed(className)) {
- return getParent().loadClass(className);
- }
-
- throw new ClassNotFoundException(className + "not visible");
- }
-
- @Override
- public InputStream getResourceAsStream(String name) {
- if (isAllowed(name)) {
- return getParent().getResourceAsStream(name);
- }
-
- return null;
- }
-
- @Override
- public Enumeration getResources(String name) throws IOException {
- if (isAllowed(name)) {
- return getParent().getResources(name);
- }
-
- return new Enumeration() {
- Iterator iter = Collections.EMPTY_LIST.iterator();
-
- @Override
- public boolean hasMoreElements() {
- return iter.hasNext();
- }
-
- @Override
- public URL nextElement() {
- return iter.next();
- }
- };
- }
-
- @Override
- public URL getResource(String name) {
- if (isAllowed(name)) {
- return getParent().getResource(name);
- }
- return null;
- }
-
- @Override
- protected Enumeration findResources(String name) throws IOException {
- if (isAllowed(name)) {
- return parent.getResources(name);
- }
-
- return new Enumeration() {
- Iterator iter = Collections.EMPTY_LIST.iterator();
-
- @Override
- public boolean hasMoreElements() {
- return iter.hasNext();
- }
-
- @Override
- public URL nextElement() {
- return iter.next();
- }
- };
- }
-
- @Override
- protected URL findResource(String name) {
- if (isAllowed(name)) {
- return parent.getResource(name);
- }
- return null;
- }
-
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleComparator.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleComparator.java
deleted file mode 100644
index 56becb909..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleComparator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-import java.util.Comparator;
-
-/**
- *
- * @author marx
- */
-public class ModuleComparator implements Comparator {
-
- @Override
- public int compare(ModuleImpl o1, ModuleImpl o2) {
- return ((Integer) o1.getDependencies().size()).compareTo(o2.getDependencies().size());
- }
-
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleImpl.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleImpl.java
deleted file mode 100644
index 2674ca0bc..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleImpl.java
+++ /dev/null
@@ -1,284 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import com.condation.modules.api.Context;
-import com.condation.modules.api.ExtensionPoint;
-import com.condation.modules.api.Module;
-import com.condation.modules.api.Module.Priority;
-import com.condation.modules.api.ModuleConfiguration;
-import com.condation.modules.api.ModuleRequestContextFactory;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.ServiceLoader;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- *
- * @author thmarx
- */
-public class ModuleImpl implements Module {
-
- private String id;
- private String version;
- private String name;
- private String description;
- private String author;
- private Priority priority = Priority.NORMAL;
- private final List dependencyList = new ArrayList<>();
- private final ModuleRequestContextFactory requestContextFactory;
-
- File moduleDir;
-
- File modulesDataDir;
-
- URLClassLoader classloader;
-
- ModuleConfiguration configuration;
-
- private final Context context;
- private final ModuleInjector injector;
-
- Map extensions = new HashMap<>();
-
- private ModuleServiceLoader moduleServiceLoader;
-
- protected ModuleImpl(final File moduleDir, final File modulesDataDir, final Context context,
- final ModuleInjector injector, final ModuleRequestContextFactory requestContextFactory) throws MalformedURLException, IOException {
- this.moduleDir = moduleDir;
- this.modulesDataDir = modulesDataDir;
- this.context = context;
- this.injector = injector;
- this.requestContextFactory = requestContextFactory;
-
- Properties properties = new Properties();
- try (FileReader reader = new FileReader(new File(moduleDir, "module.properties"))) {
- properties.load(reader);
- this.id = properties.getProperty("id");
- this.name = properties.getProperty("name");
- this.version = properties.getProperty("version");
- this.description = properties.getProperty("description");
- this.author = properties.getProperty("author");
- String dependencies = properties.getProperty("dependencies");
- if (dependencies != null && !dependencies.equals("")) {
- for (String dep : dependencies.split(";")) {
- String[] dependency = dep.split("#");
- if (dependency != null && dependency.length == 2) {
- dependencyList.add(new Dependency(dependency[0], dependency[1]));
- }
- }
- }
- String config_prio = properties.getProperty("priority", "NORMAL");
- this.priority = Priority.valueOf(config_prio);
- }
- }
-
- public void init(final ClassLoader parentClassLoader) throws MalformedURLException, IOException {
- List urls = new ArrayList<>();
-
- File[] libs = new File(moduleDir, "libs").listFiles((File dir, String name1) -> name1.endsWith(".jar"));
- for (File lib : libs) {
- urls.add(new URL("jar:" + lib.toURI().toURL() + "!/"));
- lib = null;
- }
-
- classloader = new ModuledFirstURLClassLoader(urls.toArray(new URL[libs.length]), parentClassLoader);
- urls.clear();
- urls = null;
- libs = null;
-
- File dataDir = new File(modulesDataDir, id);
- if (!dataDir.exists()) {
- dataDir.mkdirs();
- }
- this.configuration = new ModuleConfiguration(dataDir);
-
- this.moduleServiceLoader = ModuleServiceLoader.create(classloader);
- }
-
- @Override
- public boolean provides(Class extends ExtensionPoint> extensionClass) {
- ServiceLoader extends ExtensionPoint> serviceLoader = ServiceLoader.load(extensionClass, classloader);
- return serviceLoader.iterator().hasNext();
- }
-
- @Override
- public List extensions(Class extensionClass) {
-
- return moduleServiceLoader.get(extensionClass).stream()
- .map(ext -> {
- ext.setContext(context);
- ext.setConfiguration(configuration);
-
- if (requestContextFactory != null) {
- ext.setRequestContext(requestContextFactory.createContext());
- }
-
- if (injector != null) {
- injector.inject(ext);
- }
-
- ext.init();
-
- return ext;
- }).toList();
- }
-
- @Override
- public Priority getPriority() {
- return priority;
- }
-
- @Override
- public String getVersion() {
- return version;
- }
-
- public void setVersion(String version) {
- this.version = version;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- @Override
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
-
- public List getDependencies() {
- return this.dependencyList;
- }
-
- public File getModuleDir() {
- return moduleDir;
- }
-
- public File getModulesDataDir() {
- return modulesDataDir;
- }
-
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 61 * hash + Objects.hashCode(this.id);
- return hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final ModuleImpl other = (ModuleImpl) obj;
- if (!Objects.equals(this.id, other.id)) {
- return false;
- }
- return true;
- }
-
- public void close() throws IOException {
- this.classloader.close();
-
- // workaround: close all libs manually: see https://bugs.openjdk.java.net/browse/JDK-7183373
- for (URL u : this.classloader.getURLs()) {
- if (u.getProtocol().equals("jar")) {
- ((JarURLConnection) u.openConnection()).getJarFile().close();
- }
- }
-
- this.classloader = null;
- this.configuration = null;
- this.dependencyList.clear();
- this.extensions.clear();
- this.extensions = null;
- this.modulesDataDir = null;
- this.moduleDir = null;
- }
-
- public static class Dependency {
-
- private final String id;
- private final String version;
-
- public Dependency(String id, String version) {
- this.id = id;
- this.version = version;
- }
-
- public String id() {
- return id;
- }
-
- public String version() {
- return version;
- }
-
- }
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleInjector.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleInjector.java
deleted file mode 100644
index 2689642d2..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleInjector.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-import com.condation.modules.api.ExtensionPoint;
-
-
-
-/**
- *
- * @author marx
- */
-public interface ModuleInjector {
-
- public void inject (final ExtensionPoint extension);
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleLoader.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleLoader.java
deleted file mode 100644
index 76b87ce9a..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleLoader.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-import com.condation.modules.api.Context;
-import com.condation.modules.api.ManagerConfiguration;
-import com.condation.modules.api.ModuleLifeCycleExtension;
-import com.condation.modules.api.ModuleRequestContextFactory;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- *
- * @author marx
- */
-public class ModuleLoader {
-
- private final ManagerConfiguration configuration;
-
- final Map activeModules = new ConcurrentHashMap<>();
-
- final File modulesPath;
- final File modulesDataPath;
-
- final ClassLoader globalClassLoader;
-
- final Context context;
- final ModuleInjector injector;
-
- final ModuleRequestContextFactory requestContextFactory;
-
- protected ModuleLoader(final ManagerConfiguration configuration, final File modulesPath, final File modulesDataPath,
- final ClassLoader globalClassLoader, final Context context, final ModuleInjector injector,
- final ModuleRequestContextFactory requestContextFactory) {
- this.configuration = configuration;
- this.modulesPath = modulesPath;
- this.modulesDataPath = modulesDataPath;
- this.globalClassLoader = globalClassLoader;
- this.context = context;
- this.injector = injector;
- this.requestContextFactory = requestContextFactory;
- }
-
- protected Map activeModules() {
- return activeModules;
- }
-
- protected boolean deactivateModule(final String moduleId) throws IOException {
-
- ModuleImpl module = activeModules().get(moduleId);
- module.extensions(ModuleLifeCycleExtension.class).stream().forEach((ModuleLifeCycleExtension mle) -> {
- mle.setContext(context);
- mle.deactivate();
- });
-
- activeModules().get(moduleId).close();
- activeModules().remove(moduleId);
-
- return true;
- }
-
- protected boolean activateModule(final String moduleId) throws IOException {
-
- File moduleDir = new File(modulesPath, configuration.get(moduleId).getModuleDir());
- File moduleData = modulesDataPath;
-// File moduleData = activeModules().get(moduleId).getModulesDataDir();
-
- ModuleImpl module = new ModuleImpl(moduleDir, moduleData, this.context, this.injector, this.requestContextFactory);
-
- if (areDependencyFulfilled(module)) {
- ManagerConfiguration.ModuleConfig config = configuration.get(moduleId);
- if (config == null) {
- config = new ManagerConfiguration.ModuleConfig(moduleId);
- }
-
- module.init(this.globalClassLoader);
-
- config.setActive(true);
- module.extensions(ModuleLifeCycleExtension.class).stream().forEach((ModuleLifeCycleExtension mle) -> {
- mle.setContext(context);
- mle.activate();
- });
- configuration.add(config);
-
- activeModules().put(module.getId(), module);
- return true;
- }
- return false;
- }
-
- protected void tryToLoadModules(final List modules) {
- // sort modules by dependency count low to max
- Collections.sort(modules, new ModuleComparator());
-
- int tryCount = 0;
- int oldSize = modules.size();
- while (!modules.isEmpty()) {
- if (tryCount > 2) {
- break;
- }
- loadFulfilledModules(modules);
- if (modules.size() == oldSize) {
- tryCount++;
- } else {
- oldSize = modules.size();
- }
- }
- }
-
- private void loadFulfilledModules(final List modules) {
- for (final ModuleImpl module : modules) {
- if (areDependencyFulfilled(module) && configuration.get(module.getId()).isActive()) {
- activeModules.put(module.getId(), module);
- }
- }
- modules.removeAll(activeModules.values());
- }
-
- private boolean areDependencyFulfilled(final ModuleImpl module) {
- return module.getDependencies().stream().noneMatch((dependency) -> (!activeModules.containsKey(dependency.id())));
- }
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleManagerImpl.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleManagerImpl.java
deleted file mode 100644
index 968965764..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleManagerImpl.java
+++ /dev/null
@@ -1,411 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-import com.condation.modules.api.Context;
-import com.condation.modules.api.ExtensionPoint;
-import com.condation.modules.api.ManagerConfiguration;
-import com.condation.modules.api.Module;
-import com.condation.modules.api.ModuleDescription;
-import com.condation.modules.api.ModuleLifeCycleExtension;
-import com.condation.modules.api.ModuleManager;
-import com.condation.modules.api.ModuleRequestContextFactory;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The ModuleManager loads all modules from a given directoy.
- *
- * @author thmarx
- */
-public class ModuleManagerImpl implements ModuleManager {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ModuleManagerImpl.class);
-
- public static class Builder {
-
- private File modulesPath = null;
- private File modulesDataPath = null;
- private Context context = null;
- private ModuleAPIClassLoader classLoader = null;
- private ModuleInjector injector = null;
- private ModuleRequestContextFactory requestContextFactory = null;
-
- public Builder requestContextFactory(ModuleRequestContextFactory requestContextFactory) {
- this.requestContextFactory = requestContextFactory;
- return this;
- }
-
- public ModuleManager build() {
- return new ModuleManagerImpl(this);
- }
-
- public Builder setModulesPath(File path) {
- this.modulesPath = path;
- return this;
- }
-
- public Builder setModulesDataPath(File path) {
- this.modulesDataPath = path;
- return this;
- }
-
- public Builder setContext(Context context) {
- this.context = context;
- return this;
- }
-
- public Builder setClassLoader(ModuleAPIClassLoader classLoader) {
- this.classLoader = classLoader;
- return this;
- }
-
- public Builder setInjector(ModuleInjector injector) {
- this.injector = injector;
- return this;
- }
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- /**
- * Creates a new ModuleManager instance.
- *
- * @param modulesPath Path where the modules are stored
- * @param modulesDataPath Path, where the modules data is stored
- * @param context the context
- * @return A new ModuleManager.
- */
- public static ModuleManager create(final File modulesPath, final File modulesDataPath, final Context context) {
- return create(modulesPath, modulesDataPath, context, new ModuleAPIClassLoader(ModuleManagerImpl.class.getClassLoader(), Collections.EMPTY_LIST));
- }
-
- /**
- * Creates a new ModuleManager instance.
- *
- * @param modulesPath the path where the installed modules are located.
- * @param modulesDataPath the path where the modules data directory is
- * located.
- * @param context the context
- * @param classLoader the classloader
- * @return
- */
- public static ModuleManager create(final File modulesPath, final File modulesDataPath, final Context context, final ModuleAPIClassLoader classLoader) {
- return create(modulesPath, modulesDataPath, context, classLoader, null);
- }
-
- /**
- * Creates a new ModuleManager instance.
- *
- * @param modulesPath the path where the installed modules are located.
- * @param modulesDataPath the path where the modules data directory is
- * located.
- * @param context the context
- * @param injector Injector for dependency injection
- * @return A new ModuleManager.
- */
- public static ModuleManager create(final File modulesPath, final File modulesDataPath, final Context context, final ModuleInjector injector) {
- return create(modulesPath, modulesDataPath, context, new ModuleAPIClassLoader(ModuleManagerImpl.class.getClassLoader(), Collections.EMPTY_LIST), injector);
- }
-
- /**
- * Creates a ne ModuleManager instance.
- *
- * @param modulesPath the path where the installed modules are located.
- * @param modulesDataPath the path where the modules data directory is
- * located.
- * @param context the context
- * @param classLoader the classloader
- * @param injector Injector for dependency injection
- * @return
- */
- public static ModuleManager create(final File modulesPath, final File modulesDataPath, final Context context, final ModuleAPIClassLoader classLoader, final ModuleInjector injector) {
- return builder().setClassLoader(classLoader)
- .setModulesPath(modulesPath)
- .setModulesDataPath(modulesDataPath)
- .setContext(context).setInjector(injector).build();
- }
-
- final File modulesPath;
- final File modulesDataPath;
-
- final ModuleLoader moduleLoader;
-
- final ModuleAPIClassLoader globalClassLoader;
-
- private ManagerConfiguration configuration;
-
- private final Context context;
-
- final ModuleInjector injector;
-
- final ModuleRequestContextFactory requestContextFactory;
-
- final ModuleServiceLoader systemExtensionLoader;
-
- public ModuleManagerImpl() {
- this.modulesDataPath = null;
- this.modulesPath = null;
- this.globalClassLoader = null;
- this.moduleLoader = null;
- this.context = null;
- this.injector = null;
- this.requestContextFactory = null;
- this.systemExtensionLoader = null;
- }
-
- private ModuleManagerImpl(final Builder builder) {
- this.modulesPath = builder.modulesPath;
- this.modulesDataPath = builder.modulesDataPath;
- this.context = builder.context;
- this.injector = builder.injector;
- this.requestContextFactory = builder.requestContextFactory;
-
- this.configuration = new ManagerConfiguration();
- this.globalClassLoader = builder.classLoader;
- this.moduleLoader = new ModuleLoader(configuration, modulesPath, modulesDataPath, this.globalClassLoader,
- this.context, this.injector, this.requestContextFactory);
-
- File[] moduleFiles = modulesPath.listFiles((File file) -> file.isDirectory());
- File moduleData = modulesDataPath;
-
- Set allUsedModuleIDs = new HashSet<>();
-
- Map modules = new HashMap<>();
- if (moduleFiles != null) {
- loadModules(moduleFiles, moduleData, allUsedModuleIDs, modules);
- }
- configuration.getModules().values().stream().filter((mc) -> (!allUsedModuleIDs.contains(mc.getId()))).forEach((mc) -> {
- configuration.remove(mc.getId());
- });
-
- systemExtensionLoader = ModuleServiceLoader.create(globalClassLoader.getParent());
-
- }
-
- @Override
- public void initModules() {
-
- File[] moduleFiles = modulesPath.listFiles((File file) -> file.isDirectory());
- File moduleData = modulesDataPath;
-
- Set allUsedModuleIDs = new HashSet<>();
-
- Map modules = new HashMap<>();
- if (moduleFiles != null) {
- loadModules(moduleFiles, moduleData, allUsedModuleIDs, modules);
- }
-
- List moduleList = new ArrayList<>(modules.values());
- moduleLoader.tryToLoadModules(moduleList);
-
- configuration.getModules().values().forEach((mc) -> {
- if (!moduleLoader.activeModules().containsKey(mc.getId())) {
- configuration.get(mc.getId()).setActive(false);
- }
- });
- }
-
- private void loadModules(File[] moduleFiles, File moduleData, Set allUsedModuleIDs, Map modules) {
- for (File module : moduleFiles) {
- try {
- ModuleImpl mod = new ModuleImpl(module, moduleData, this.context, this.injector, this.requestContextFactory
- );
- allUsedModuleIDs.add(mod.getId());
- modules.put(mod.getId(), mod);
- if (configuration.get(mod.getId()) == null) {
- configuration.add(new ManagerConfiguration.ModuleConfig(mod.getId()).setModuleDir(module.getName()));
- }
- } catch (IOException ex) {
- LOGGER.error("", ex);
- // deactivate module
- String modid = module.getName();
- allUsedModuleIDs.add(modid);
- if (configuration.get(modid) != null) {
- LOGGER.warn("deactivate module caused by an error");
- configuration.get(modid).setActive(false);
- }
- }
- }
- }
-
- @Override
- public void close() {
- extensions(ModuleLifeCycleExtension.class).stream().forEach((ModuleLifeCycleExtension mle) -> {
- mle.setContext(context);
- mle.deactivate();
- });
- }
-
- /**
- * Returns a module by id. All the modules are loaded correctly so you can
- * get extensions.
- *
- * @param id The id of the module.
- * @return The module for the given id or null.
- */
- @Override
- public Module module(final String id) {
- return moduleLoader.activeModules.get(id);
- }
-
- @Override
- public List getModuleIds() {
- List modules = new ArrayList<>(configuration.getModules().values());
-
- return modules.stream().map((mc) -> {
- try {
- File moduleDir = new File(modulesPath, configuration.get(mc.getId()).getModuleDir());
- File moduleData = modulesDataPath;
- ModuleImpl module = new ModuleImpl(moduleDir, moduleData, this.context, this.injector, this.requestContextFactory);
- return module;
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- }).sorted(new ModuleComparator()).map(Module::getId).collect(Collectors.toList());
- }
-
- /**
- * Returns the module description.
- *
- * @param id
- * @return
- * @throws IOException
- */
- @Override
- public ModuleDescription description(final String id) throws IOException {
- ModuleImpl module;
- if (moduleLoader.activeModules.containsKey(id)) {
- module = moduleLoader.activeModules.get(id);
- } else {
- ManagerConfiguration.ModuleConfig mc = configuration.get(id);
- File moduleDir = new File(modulesPath, configuration.get(mc.getId()).getModuleDir());
- module = new ModuleImpl(moduleDir, null, this.context, this.injector, this.requestContextFactory);
- }
-
- ModuleDescription description = new ModuleDescription();
- description.setVersion(module.getVersion());
- description.setName(module.getName());
- description.setDescription(module.getDescription());
- return description;
- }
-
- /**
- * activates a module.
- *
- * @param moduleId
- * @return returns true if the module is correctly or allready installed,
- * otherwise false
- * @throws java.io.IOException
- */
- @Override
- public boolean activateModule(final String moduleId) throws IOException {
- if (configuration.get(moduleId) == null || !configuration.get(moduleId).isActive()) {
- return moduleLoader.activateModule(moduleId);
- } else if (configuration.get(moduleId) != null && configuration.get(moduleId).isActive()) {
- return true;
- }
- return false;
-
- }
-
- /**
- *
- * @param moduleId
- * @return
- */
- @Override
- public boolean deactivateModule(final String moduleId) throws IOException {
- if (configuration.get(moduleId) == null) {
- return true;
- } else if (configuration.get(moduleId) != null && !configuration.get(moduleId).isActive()) {
- return true;
- }
-
- moduleLoader.deactivateModule(moduleId);
-
- configuration.get(moduleId).setActive(false);
- return true;
-
- }
-
- /**
- * Returns all Extensions of the given type.
- *
- * @param
- * @param extensionClass
- * @return
- */
- @Override
- public List extensions(Class extensionClass) {
- List extensions = new ArrayList<>();
- moduleLoader.activeModules().values().forEach((ModuleImpl m) -> {
- var moduleExt = m.extensions(extensionClass);
- if (!moduleExt.isEmpty()) {
- extensions.addAll(moduleExt);
- }
- });
- // system modules
- systemExtensionLoader.get(extensionClass)
- .stream()
- .map(ext -> {
- ext.setContext(context);
-
- if (requestContextFactory != null) {
- ext.setRequestContext(requestContextFactory.createContext());
- }
-
- if (injector != null) {
- injector.inject(ext);
- }
-
- ext.init();
-
- return ext;
- })
- .forEach(extensions::add);
-
- return extensions;
- }
-
- /**
- * Returns the configuration of the module manager.
- *
- * @return
- */
- @Override
- public ManagerConfiguration configuration() {
- return configuration;
- }
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleServiceLoader.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleServiceLoader.java
deleted file mode 100644
index 49f9e3d93..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuleServiceLoader.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- *
- * @author t.marx
- */
-@Slf4j
-public final class ModuleServiceLoader {
-
- static final String PREFIX = "META-INF/services/";
-
- private final ClassLoader loader;
-
- private final ConcurrentMap, List>> providers = new ConcurrentHashMap<>();
-
- private ModuleServiceLoader(ClassLoader loader) {
- this.loader = loader;
- }
-
- public static ModuleServiceLoader create(ClassLoader loader) {
- return new ModuleServiceLoader(loader);
- }
-
- public List get(Class service) {
- try {
- return providers.computeIfAbsent(service, clazz -> {
- return initService(clazz);
- }).stream()
- .map(this::newInstance)
- .filter(Objects::nonNull)
- .map(service::cast)
- .toList();
- } catch (Exception ex) {
- log.error("", ex);
- }
- return Collections.emptyList();
- }
-
- private S newInstance(Provider provider) {
- try {
- return provider.get();
- } catch (Exception ex) {
- log.error("error createing instance", ex);
- }
- return null;
- }
-
- private List> initService(Class service) {
-
- List> providerImpls = new ArrayList<>();
- try {
- String fullName = PREFIX + service.getName();
- Enumeration resources = loader.getResources(fullName);
- while (resources.hasMoreElements()) {
- var url = resources.nextElement();
- try (var ins = url.openStream(); var reader = new BufferedReader(new InputStreamReader(ins))) {
-
- String line;
- while ((line = reader.readLine()) != null) {
- var serviceImplClass = (Class) Class.forName(line, false, loader);
- providerImpls.add(new Provider<>(serviceImplClass));
- }
- }
- }
- } catch (Exception e) {
- log.error("", e);
- }
-
- return providerImpls;
- }
-
- private record Provider(Class type) {
-
- public S get() throws Exception {
- return (S) type.getConstructors()[0].newInstance();
- }
- }
-}
diff --git a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuledFirstURLClassLoader.java b/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuledFirstURLClassLoader.java
deleted file mode 100644
index 402958488..000000000
--- a/modules-framework/manager/src/main/java/com/condation/modules/manager/ModuledFirstURLClassLoader.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.condation.modules.manager;
-
-/*-
- * #%L
- * modules-manager
- * %%
- * Copyright (C) 2023 - 2024 CondationCMS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- *
- * @author marx
- */
-public class ModuledFirstURLClassLoader extends URLClassLoader {
-
- public ModuledFirstURLClassLoader(URL[] classpath, ClassLoader parent) {
- super(classpath, parent);
- }
-
- @Override
- protected synchronized Class> loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- // First, check if the class has already been loaded
- Class> c = findLoadedClass(name);
- if (c == null) {
-
- if (c == null) {
- try {
- // checking local
- c = findClass(name);
- } catch (ClassNotFoundException e) {
- // checking parent
- // This call to loadClass may eventually call findClass again, in case the parent doesn't find anything.
- c = super.loadClass(name, resolve);
- }
- }
- }
- if (resolve) {
- resolveClass(c);
- }
- return c;
- }
-
- @Override
- public URL getResource(String name) {
- URL url = null;
- if (url == null) {
- url = findResource(name);
- if (url == null) {
- // This call to getResource may eventually call findResource again, in case the parent doesn't find anything.
- url = super.getResource(name);
- }
- }
- return url;
- }
-
- @Override
- public Enumeration getResources(String name) throws IOException {
- /**
- * Similar to super, but local resources are enumerated before parent
- * resources
- */
- Enumeration localUrls = findResources(name);
- Enumeration parentUrls = null;
- if (getParent() != null) {
- parentUrls = getParent().getResources(name);
- }
- final List urls = new ArrayList<>();
- if (localUrls != null) {
- while (localUrls.hasMoreElements()) {
- urls.add(localUrls.nextElement());
- }
- }
- if (parentUrls != null) {
- while (parentUrls.hasMoreElements()) {
- urls.add(parentUrls.nextElement());
- }
- }
- return new Enumeration() {
- Iterator iter = urls.iterator();
-
- @Override
- public boolean hasMoreElements() {
- return iter.hasNext();
- }
-
- @Override
- public URL nextElement() {
- return iter.next();
- }
- };
- }
-
- @Override
- public InputStream getResourceAsStream(String name) {
- URL url = getResource(name);
- try {
- return url != null ? url.openStream() : null;
- } catch (IOException e) {
- }
- return null;
- }
-
-}
diff --git a/modules-framework/pom.xml b/modules-framework/pom.xml
deleted file mode 100644
index 87b294b4b..000000000
--- a/modules-framework/pom.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- 4.0.0
-
- com.condation.cms
- cms-parent
- 7.4.2
-
- com.condation.cms.module.framework
- module-framework
- pom
-
-
- api
- manager
-
-
diff --git a/modules/example-module/pom.xml b/modules/example-module/pom.xml
index 99133c151..d9a68f7c0 100644
--- a/modules/example-module/pom.xml
+++ b/modules/example-module/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms.modules
cms-modules
- 7.4.2
+ 7.5.0
example-module
jar
@@ -21,7 +21,7 @@
provided
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-api
provided
diff --git a/modules/pom.xml b/modules/pom.xml
index 4ae1a2766..68caa3783 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
com.condation.cms.modules
cms-modules
@@ -12,6 +12,6 @@
example-module
- system-modules
+ system-modules
diff --git a/modules/system-modules/pom.xml b/modules/system-modules/pom.xml
index 1c3176bab..83de8a4c1 100644
--- a/modules/system-modules/pom.xml
+++ b/modules/system-modules/pom.xml
@@ -4,7 +4,7 @@
com.condation.cms.modules
cms-modules
- 7.4.2
+ 7.5.0
cms-system-modules
jar
diff --git a/pom.xml b/pom.xml
index 610091096..9249ec9ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.condation.cms
cms-parent
- 7.4.2
+ 7.5.0
pom
UTF-8
@@ -13,11 +13,11 @@
yyyy-MM-dd HH:mm
12.0.16
10.1.0
+ 1.0.0
cms-api
cms-server
- modules-framework
modules
cms-filesystem
cms-media
@@ -113,14 +113,14 @@
${project.version}
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-manager
- ${project.version}
+ ${modules-framework.version}
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-api
- ${project.version}
+ ${modules-framework.version}
com.condation.cms.modules
@@ -374,9 +374,9 @@
1.1.1
- com.condation.cms.module.framework
+ com.condation.modules.framework
modules-api
- 6.4.0
+ ${modules-framework.version}