Skip to content

Commit

Permalink
Plugins can be loaded in any order
Browse files Browse the repository at this point in the history
  • Loading branch information
hylkevds committed Jun 11, 2024
1 parent b15abd3 commit a7390f2
Show file tree
Hide file tree
Showing 26 changed files with 152 additions and 51 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Implemented OData any() filters.
* Added options for adding extra meta data to the landing page using the modelLoader plugin.
* Implemented $filter for MQTT topics. Can be enabled using the `mqtt.allowFilter` setting.
* Plugins can be loaded in any order.

**Internal changes & Bugfixes**
* Improved generated queries when fetching entities over a one-to-many relation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_PASSWORD_LENGTH;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_USERNAME_LENGTH;

import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.settings.ConfigDefaults;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.settings.Settings;
Expand Down Expand Up @@ -88,14 +89,15 @@ public class BasicAuthProvider implements AuthProvider, LiquibaseUser, ConfigDef
private final Map<String, UserClientInfo> usernameToUserinfo = new ConcurrentHashMap<>();

@Override
public void init(CoreSettings coreSettings) {
public InitResult init(CoreSettings coreSettings) {
this.coreSettings = coreSettings;
DatabaseHandler.init(coreSettings);
final Settings authSettings = coreSettings.getAuthSettings();
roleAdmin = authSettings.get(TAG_AUTH_ROLE_ADMIN, CoreSettings.class);
maxClientsPerUser = authSettings.getInt(TAG_MAX_CLIENTS_PER_USER, getClass());
maxPassLength = authSettings.getInt(TAG_MAX_PASSWORD_LENGTH, getClass());
maxNameLength = authSettings.getInt(TAG_MAX_USERNAME_LENGTH, getClass());
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_PASSWORD_LENGTH;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_USERNAME_LENGTH;

import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.settings.ConfigDefaults;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.settings.Settings;
Expand Down Expand Up @@ -129,7 +130,7 @@ public class KeycloakAuthProvider implements AuthProvider, LiquibaseUser, Config
private static final Map<String, Object> OPTIONS = new HashMap<>();

@Override
public void init(CoreSettings coreSettings) {
public InitResult init(CoreSettings coreSettings) {
this.coreSettings = coreSettings;
OPTIONS.put("keycloak-config-file", FROST_SERVER_KEYCLOAKJSON);
final Settings authSettings = coreSettings.getAuthSettings();
Expand All @@ -142,6 +143,7 @@ public void init(CoreSettings coreSettings) {
DatabaseHandler.init(coreSettings);
databaseHandler = DatabaseHandler.getInstance(coreSettings);
}
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package de.fraunhofer.iosb.ilt.frostserver.formatter;

import de.fraunhofer.iosb.ilt.frostserver.path.Version;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.PluginResultFormat;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import java.util.Arrays;
Expand All @@ -30,8 +31,9 @@
public class PluginResultFormatDefault implements PluginResultFormat {

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
settings.getPluginManager().registerPlugin(this);
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import de.fraunhofer.iosb.ilt.frostserver.path.ResourcePath;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain;
import de.fraunhofer.iosb.ilt.frostserver.query.Query;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.util.SecurityModel;
Expand Down Expand Up @@ -138,8 +139,9 @@ public default <T> T get(ResourcePath path, Query query, Class<T> clazz) {
* Initialise using the given settings.
*
* @param settings The settigns to use.
* @return the result of the initialisation.
*/
public void init(CoreSettings settings);
public InitResult init(CoreSettings settings);

/**
* Get the settings that were used to initialise this PM.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
* Karlsruhe, Germany.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.fraunhofer.iosb.ilt.frostserver.service;

/**
*
* @author scf
*/
public enum InitResult {
/**
* Initialisation was successful.
*/
INIT_OK,
/**
* Initialisation needs to be delayed because dependencies are not loaded
* yet.
*/
INIT_DELAY,
/**
* Initialisation failed.
*/
INIT_FAILED
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ public interface Plugin {
* Initialise the plugin using settings from the given CoreSettings.
*
* @param settings The settings to use.
* @return the result of the initialisation.
*/
public void init(CoreSettings settings);
public InitResult init(CoreSettings settings);

/**
* Check if this plugin is enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package de.fraunhofer.iosb.ilt.frostserver.service;

import static de.fraunhofer.iosb.ilt.frostserver.service.InitResult.INIT_OK;

import de.fraunhofer.iosb.ilt.frostserver.formatter.ResultFormatter;
import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry;
import de.fraunhofer.iosb.ilt.frostserver.path.Version;
Expand Down Expand Up @@ -126,7 +128,7 @@ public void init() {
Settings pluginSettings = settings.getPluginSettings();
String provided = pluginSettings.get(TAG_PROVIDED_PLUGINS, getClass()).trim();
String extra = pluginSettings.get(TAG_PLUGINS, getClass()).trim();
LOGGER.info("Loading plugins.");
LOGGER.info("Loading plugins...");
loadPlugins(provided);
loadPlugins(extra);
initPlugins(PersistenceManagerFactory.getInstance(settings).create());
Expand Down Expand Up @@ -166,20 +168,57 @@ private void loadPlugins(String classList) {
if (classList.isEmpty()) {
return;
}
String[] split = classList.trim().split(",");
final List<Plugin> pluginsToLoad = new ArrayList<>();
final String[] split = classList.trim().split(",");
LOGGER.info("Loading {} plugins...", split.length);
for (String className : split) {
try {
LOGGER.info("Loading {}", className);
Class<? extends Plugin> clazz = getClass().getClassLoader().loadClass(className.trim()).asSubclass(Plugin.class);
Plugin plugin = clazz.getDeclaredConstructor().newInstance();
plugin.init(settings);
pluginsToLoad.add(plugin);
} catch (NoClassDefFoundError | ClassNotFoundException ex) {
LOGGER.warn("Could not find given plugin class: '{}': {}", StringHelper.cleanForLogging(className), ex.getMessage());
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
LOGGER.warn("Could not load given plugin class: '{}': {}", StringHelper.cleanForLogging(className), ex.getMessage());
LOGGER.info("Exception:", ex);
} catch (RuntimeException ex) {
LOGGER.warn("Plugin caused an exception during initialisation.", ex);
LOGGER.warn("Plugin caused an exception during loading.", ex);
}
}

while (!pluginsToLoad.isEmpty()) {
int count = pluginsToLoad.size();
LOGGER.info("Initialising {} plugins...", count);
for (Iterator<Plugin> it = pluginsToLoad.iterator(); it.hasNext();) {
Plugin plugin = it.next();
try {
LOGGER.info("Initialising {}", plugin.getClass().getName());
InitResult result = plugin.init(settings);
switch (result) {
case INIT_DELAY:
// don't remove, try again later.
break;

case INIT_FAILED:
// Failed, don't try again.
LOGGER.warn("Failed to initialise plugin: '{}'", plugin);
it.remove();
break;

default:
case INIT_OK:
// All is fine.
it.remove();
break;
}

} catch (RuntimeException ex) {
LOGGER.warn("Plugin caused an exception during initialisation.", ex);
}
}
if (count == pluginsToLoad.size()) {
LOGGER.error("All {} remaining plugins can not be initialised", count);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package de.fraunhofer.iosb.ilt.frostserver.util;

import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.util.exception.UpgradeFailedException;
import java.io.IOException;
Expand All @@ -34,8 +35,9 @@ public interface LiquibaseUser {
* Initialise the LiquibaseUser so it can check for, or do upgrades.
*
* @param coreSettings The settings to use for initialisation.
* @return the result of the initialisation.
*/
public void init(CoreSettings coreSettings);
public InitResult init(CoreSettings coreSettings);

/**
* Give a summary of any upgrades that need to be done to the storage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import de.fraunhofer.iosb.ilt.frostserver.persistence.PersistenceManager;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain;
import de.fraunhofer.iosb.ilt.frostserver.query.Query;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.PluginManager;
import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
Expand Down Expand Up @@ -365,8 +366,9 @@ public List<EntityChangedMessage> getEntityChangedMessages() {
}

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
coreSettings = settings;
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import de.fraunhofer.iosb.ilt.frostserver.property.Property;
import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeSimplePrimitive;
import de.fraunhofer.iosb.ilt.frostserver.query.expression.constant.IntegerConstant;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.PluginService;
import de.fraunhofer.iosb.ilt.frostserver.service.Service;
import de.fraunhofer.iosb.ilt.frostserver.service.ServiceRequest;
Expand Down Expand Up @@ -166,8 +167,9 @@ public ServiceResponse execute(Service mainService, ServiceRequest request, Serv
}

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
settings.getPluginManager().registerPlugin(this);
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import static de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings.TAG_AUTH_ALLOW_ANON_READ;

import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.settings.Settings;
import de.fraunhofer.iosb.ilt.frostserver.util.AuthProvider;
Expand Down Expand Up @@ -65,8 +66,9 @@ public boolean userHasRole(String clientId, String userName, String roleName) {
}

@Override
public void init(CoreSettings coreSettings) {
public InitResult init(CoreSettings coreSettings) {
// This dummy needs no initialisation.
return InitResult.INIT_OK;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain;
import de.fraunhofer.iosb.ilt.frostserver.property.Property;
import de.fraunhofer.iosb.ilt.frostserver.query.Query;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.settings.PersistenceSettings;
Expand Down Expand Up @@ -158,7 +159,7 @@ private static TableCollection getTableCollection(CoreSettings settings) {
}

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
this.settings = settings;
tableCollection = getTableCollection(settings);
persistenceSettings = settings.getPersistenceSettings();
Expand All @@ -174,6 +175,7 @@ public void init(CoreSettings settings) {
entityFactories = new EntityFactories(settings.getModelRegistry(), tableCollection);
dataSize = new DataSize(settings.getDataSizeMax());
schemaPriority = customSettings.get(TAG_DB_SCHEMA_PRIORITY, ConnectionUtils.class);
return InitResult.INIT_OK;
}

private void init() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain;
import de.fraunhofer.iosb.ilt.frostserver.property.Property;
import de.fraunhofer.iosb.ilt.frostserver.query.Query;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode;
import de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings;
import de.fraunhofer.iosb.ilt.frostserver.settings.PersistenceSettings;
Expand Down Expand Up @@ -166,7 +167,7 @@ private static TableCollection getTableCollection(CoreSettings settings) {
}

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
this.settings = settings;
tableCollection = getTableCollection(settings);
persistenceSettings = settings.getPersistenceSettings();
Expand All @@ -182,6 +183,7 @@ public void init(CoreSettings settings) {
entityFactories = new EntityFactories(settings.getModelRegistry(), tableCollection);
dataSize = new DataSize(settings.getDataSizeMax());
schemaPriority = customSettings.get(TAG_DB_SCHEMA_PRIORITY, ConnectionUtils.class);
return InitResult.INIT_OK;
}

private void init() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import static de.fraunhofer.iosb.ilt.frostserver.plugin.actuation.ActuationModelSettings.TAG_ENABLE_ACTUATION;
import static de.fraunhofer.iosb.ilt.frostserver.property.SpecialNames.AT_IOT_ID;
import static de.fraunhofer.iosb.ilt.frostserver.service.InitResult.INIT_OK;

import de.fraunhofer.iosb.ilt.frostserver.model.EntityType;
import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry;
Expand All @@ -32,6 +33,7 @@
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntity;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntitySet;
import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex;
import de.fraunhofer.iosb.ilt.frostserver.service.InitResult;
import de.fraunhofer.iosb.ilt.frostserver.service.PluginModel;
import de.fraunhofer.iosb.ilt.frostserver.service.PluginRootDocument;
import de.fraunhofer.iosb.ilt.frostserver.service.Service;
Expand Down Expand Up @@ -103,19 +105,16 @@ public class PluginActuation implements PluginRootDocument, PluginModel, ConfigD
private boolean enabled;
private boolean fullyInitialised;

public PluginActuation() {
LOGGER.info("Creating new Actuation Plugin.");
}

@Override
public void init(CoreSettings settings) {
public InitResult init(CoreSettings settings) {
this.settings = settings;
Settings pluginSettings = settings.getPluginSettings();
enabled = pluginSettings.getBoolean(TAG_ENABLE_ACTUATION, ActuationModelSettings.class);
if (enabled) {
modelSettings = new ActuationModelSettings(settings);
settings.getPluginManager().registerPlugin(this);
}
return INIT_OK;
}

@Override
Expand Down
Loading

0 comments on commit a7390f2

Please sign in to comment.