[RM] Feature Support for loading secondary message storages from extensions and plugins.
MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/center/impl/PluginLoader.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/center/impl/PluginLoader.java
******************************************************************************/
package com.exactpro.sf.center.impl;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.PropertyConfigurator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.exactpro.sf.center.IVersion;
import com.exactpro.sf.center.SFException;
import com.exactpro.sf.common.logging.CommonLoggers;
@@ -34,30 +58,6 @@ import com.exactpro.sf.scriptrunner.PreprocessorLoader;
import com.exactpro.sf.scriptrunner.ValidatorLoader;
import com.exactpro.sf.scriptrunner.services.PluginServiceLoader;
import com.exactpro.sf.util.DirectoryFilter;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.PropertyConfigurator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-import java.util.Set;
public class PluginLoader {
@@ -105,6 +105,8 @@ public class PluginLoader {
private final IVersion coreVersion;
+ private final ILoadableManager messageStorageLoader;
+
private final List<IVersion> pluginVersions;
public PluginLoader(
@@ -121,7 +123,8 @@ public class PluginLoader {
ILoadableManager matrixConverterManager,
ILoadableManager statisticsReportsLoader,
PluginServiceLoader pluginServiceLoader,
- IVersion coreVersion) {
+ IVersion coreVersion,
+ ILoadableManager messageStorageLoader) {
if (wd == null) {
throw new NullPointerException("IWorkspaceDispatcher can't be null");
}
@@ -140,6 +143,7 @@ public class PluginLoader {
this.statisticsReportsLoader = statisticsReportsLoader;
this.pluginServiceLoader = pluginServiceLoader;
this.coreVersion = coreVersion;
+ this.messageStorageLoader = messageStorageLoader;
this.pluginVersions = new ArrayList<>();
}
@@ -500,6 +504,19 @@ public class PluginLoader {
logger.info("Ignore statistic reports [No StatisticsReportsLoader]. Plugin: {}", pluginPath);
}
+ //
+ // Load AbstractMessageStorage
+ //
+ if (messageStorageLoader != null) {
+ try {
+ messageStorageLoader.load(loadableContext);
+ } catch (Exception e) {
+ throw new EPSCommonException(e);
+ }
+ } else {
+ logger.info("Ignore message storages [No MessageStorageLoader]. Plugin: {}", pluginPath);
+ }
+
// Collect service description files
if(pluginServiceLoader != null) {
try {

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/center/impl/SFLocalContext.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/center/impl/SFLocalContext.java
@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
-import com.exactpro.sf.configuration.CleanupConfiguration;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
@@ -42,6 +41,7 @@ import com.exactpro.sf.center.SFContextSettings;
import com.exactpro.sf.center.SFException;
import com.exactpro.sf.common.adapting.IAdapterManager;
import com.exactpro.sf.common.util.EPSCommonException;
+import com.exactpro.sf.configuration.CleanupConfiguration;
import com.exactpro.sf.configuration.DataManager;
import com.exactpro.sf.configuration.DefaultAdapterManager;
import com.exactpro.sf.configuration.DictionaryManager;
@@ -95,6 +95,9 @@ import com.exactpro.sf.storage.IServiceStorage;
import com.exactpro.sf.storage.IStorage;
import com.exactpro.sf.storage.ITestScriptStorage;
import com.exactpro.sf.storage.IVariableSetStorage;
+import com.exactpro.sf.storage.MessageStorageLoader;
+import com.exactpro.sf.storage.impl.AbstractMessageStorage;
+import com.exactpro.sf.storage.impl.BroadcastMessageStorage;
import com.exactpro.sf.storage.impl.DatabaseAuthStorage;
import com.exactpro.sf.storage.impl.DatabaseEnvironmentStorage;
import com.exactpro.sf.storage.impl.DatabaseMatrixStorage;
@@ -306,6 +309,7 @@ public class SFLocalContext implements ISFContext {
embeddedServices.add(updateService);
PluginServiceLoader pluginServiceLoader = new PluginServiceLoader();
+ MessageStorageLoader messageStorageLoader = new MessageStorageLoader();
// 5) Load core & plugins
PluginLoader pluginLoader = new PluginLoader(
@@ -322,13 +326,14 @@ public class SFLocalContext implements ISFContext {
matrixConverterLoader,
statisticsService,
pluginServiceLoader,
- version);
+ version,
+ messageStorageLoader);
LoadInfo loadInfo = pluginLoader.load();
loadInfo.appendClassPath(compilerClassPath);
compilerClassPath = loadInfo.getClassPath();
- messageStorage = createMessageStorage(envSettings, sessionFactory, dictionaryManager);
+ messageStorage = createMessageStorage(envSettings, sessionFactory, dictionaryManager, messageStorageLoader.getSecondaryMessageStorages(workspaceDispatcher, envSettings, dictionaryManager));
disposables.add(messageStorage);
serviceStorage = createServiceStorage(envSettings, sessionFactory, workspaceDispatcher, staticServiceManager, dictionaryManager, messageStorage);
@@ -398,15 +403,20 @@ public class SFLocalContext implements ISFContext {
}
}
- private IMessageStorage createMessageStorage(EnvironmentSettings envSettings, SessionFactory sessionFactory, DictionaryManager dictionaryManager) throws WorkspaceStructureException, FileNotFoundException {
+ private IMessageStorage createMessageStorage(EnvironmentSettings envSettings, SessionFactory sessionFactory, IDictionaryManager dictionaryManager, List<AbstractMessageStorage> secondary) throws WorkspaceStructureException, FileNotFoundException {
+ AbstractMessageStorage primaryMessageStorage;
switch (envSettings.getStorageType()) {
case DB:
- return new DatabaseMessageStorage(new DBStorageSettings(workspaceDispatcher, sessionFactory, dictionaryManager, envSettings));
+ primaryMessageStorage = new DatabaseMessageStorage(new DBStorageSettings(workspaceDispatcher, sessionFactory, dictionaryManager, envSettings));
+ break;
case FILE:
- return new FileMessageStorage(new BaseStorageSettings(workspaceDispatcher, dictionaryManager, envSettings));
+ primaryMessageStorage = new FileMessageStorage(new BaseStorageSettings(workspaceDispatcher, dictionaryManager, envSettings));
+ break;
default:
throw new EPSCommonException("Unsupported message storage type. Check your descriptor.xml file.");
}
+
+ return new BroadcastMessageStorage(primaryMessageStorage, secondary);
}
private IMatrixStorage createMatrixStorage(EnvironmentSettings envSettings, SessionFactory sessionFactory) {

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/externalapi/ServiceFactory.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/externalapi/ServiceFactory.java
@@ -193,7 +193,7 @@ public class ServiceFactory implements IServiceFactory {
IVersion coreVersion = new CoreVersion();
PluginLoader pluginLoader = new PluginLoader(wd, staticServiceManager, null,
dictionaryManager, null, null, null, dataManager, null, null, null, null,
- null, coreVersion);
+ null, coreVersion, null);
pluginLoader.load();
this.marshalManager = new ServiceMarshalManager(staticServiceManager, dictionaryManager);

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/help/HelpBuilder.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/help/HelpBuilder.java
@@ -306,7 +306,7 @@ public class HelpBuilder {
}
PluginLoader pluginLoader = new PluginLoader(wd, staticServiceManager, actionManager, dictionaryManager, preprocessorLoader, validatorLoader,
- adapterManager, dataManager, languageManager, matrixProviderHolder, matrixConverterManager, statisticsReportLoader, null, version);
+ adapterManager, dataManager, languageManager, matrixProviderHolder, matrixConverterManager, statisticsReportLoader, null, version, null);
pluginLoader.load();

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/BaseStorageSettings.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/BaseStorageSettings.java
******************************************************************************/
package com.exactpro.sf.storage;
-import com.exactpro.sf.configuration.DictionaryManager;
+import com.exactpro.sf.configuration.IDictionaryManager;
import com.exactpro.sf.configuration.workspace.IWorkspaceDispatcher;
import com.exactpro.sf.scriptrunner.EnvironmentSettings;
-import org.apache.commons.configuration.EnvironmentConfiguration;
public class BaseStorageSettings {
protected final IWorkspaceDispatcher workspaceDispatcher;
- protected final DictionaryManager dictionaryManager;
+ protected final IDictionaryManager dictionaryManager;
private final EnvironmentSettings environmentSettings;
- public BaseStorageSettings(IWorkspaceDispatcher workspaceDispatcher, DictionaryManager dictionaryManager, EnvironmentSettings environmentSettings) {
+ public BaseStorageSettings(IWorkspaceDispatcher workspaceDispatcher, IDictionaryManager dictionaryManager, EnvironmentSettings environmentSettings) {
this.workspaceDispatcher = workspaceDispatcher;
this.dictionaryManager = dictionaryManager;
this.environmentSettings = environmentSettings;
@@ -35,7 +34,7 @@ public class BaseStorageSettings {
return workspaceDispatcher;
}
- public DictionaryManager getDictionaryManager() {
+ public IDictionaryManager getDictionaryManager() {
return dictionaryManager;
}

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/DBStorageSettings.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/DBStorageSettings.java
******************************************************************************/
package com.exactpro.sf.storage;
-import com.exactpro.sf.configuration.DictionaryManager;
+import org.hibernate.SessionFactory;
+
+import com.exactpro.sf.configuration.IDictionaryManager;
import com.exactpro.sf.configuration.workspace.IWorkspaceDispatcher;
import com.exactpro.sf.scriptrunner.EnvironmentSettings;
-import org.apache.commons.configuration.EnvironmentConfiguration;
-import org.hibernate.SessionFactory;
public class DBStorageSettings extends BaseStorageSettings {
private final SessionFactory sessionFactory;
- public DBStorageSettings(IWorkspaceDispatcher workspaceDispatcher, SessionFactory sessionFactory, DictionaryManager dictionaryManager, EnvironmentSettings environmentSettings
+ public DBStorageSettings(IWorkspaceDispatcher workspaceDispatcher, SessionFactory sessionFactory, IDictionaryManager dictionaryManager, EnvironmentSettings environmentSettings
) {
super(workspaceDispatcher, dictionaryManager, environmentSettings);
this.sessionFactory = sessionFactory;

ADD
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/IAbstractMessageStorageFactory.java
+/*******************************************************************************
+ * Copyright 2009-2020 Exactpro (Exactpro Systems Limited)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+package com.exactpro.sf.storage;
+
+import com.exactpro.sf.configuration.IDictionaryManager;
+import com.exactpro.sf.configuration.workspace.IWorkspaceDispatcher;
+import com.exactpro.sf.scriptrunner.EnvironmentSettings;
+import com.exactpro.sf.storage.impl.AbstractMessageStorage;
+
+public interface IAbstractMessageStorageFactory {
+
+ /**
+ * Create secondary message storage
+ * @param environmentSettings Global settings of Sailfish
+ */
+ AbstractMessageStorage createMessageStorage(IWorkspaceDispatcher dispatcher, EnvironmentSettings environmentSettings, IDictionaryManager dictionaryManager);
+
+}

ADD
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/MessageStorageLoader.java
+/*******************************************************************************
+ * Copyright 2009-2020 Exactpro (Exactpro Systems Limited)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+package com.exactpro.sf.storage;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.ServiceLoader;
+import java.util.stream.Collectors;
+
+import com.exactpro.sf.configuration.IDictionaryManager;
+import com.exactpro.sf.configuration.ILoadableManager;
+import com.exactpro.sf.configuration.ILoadableManagerContext;
+import com.exactpro.sf.configuration.workspace.IWorkspaceDispatcher;
+import com.exactpro.sf.scriptrunner.EnvironmentSettings;
+import com.exactpro.sf.storage.impl.AbstractMessageStorage;
+
+public class MessageStorageLoader implements ILoadableManager {
+
+ private final List<IAbstractMessageStorageFactory> secondaryMessageStorageFactory;
+
+ public MessageStorageLoader() {
+ this.secondaryMessageStorageFactory = new LinkedList<>();
+ }
+
+ @Override
+ public void load(ILoadableManagerContext context) throws Exception {
+ for (IAbstractMessageStorageFactory factory : ServiceLoader.load(IAbstractMessageStorageFactory.class, context.getClassLoaders()[0])) {
+ secondaryMessageStorageFactory.add(factory);
+ }
+ }
+
+ public List<AbstractMessageStorage> getSecondaryMessageStorages(IWorkspaceDispatcher dispatcher, EnvironmentSettings environmentSettings, IDictionaryManager dictionaryManager){
+ return secondaryMessageStorageFactory
+ .stream()
+ .map(factory -> factory.createMessageStorage(dispatcher, environmentSettings, dictionaryManager))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ //Unused
+ @Override
+ public void finalize(ILoadableManagerContext context) throws Exception {}
+}

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/impl/AbstractMessageStorage.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/impl/AbstractMessageStorage.java
@@ -30,7 +30,7 @@ import com.exactpro.sf.common.messages.IMessageFactory;
import com.exactpro.sf.common.messages.MessageUtil;
import com.exactpro.sf.common.messages.structures.IDictionaryStructure;
import com.exactpro.sf.common.messages.structures.IMessageStructure;
-import com.exactpro.sf.configuration.DictionaryManager;
+import com.exactpro.sf.configuration.IDictionaryManager;
import com.exactpro.sf.configuration.suri.SailfishURI;
import com.exactpro.sf.storage.IMessageStorage;
import com.exactpro.sf.storage.ScriptRun;
@@ -39,9 +39,9 @@ import com.exactpro.sf.storage.util.JsonMessageConverter;
public abstract class AbstractMessageStorage implements IMessageStorage {
protected final Logger logger = LoggerFactory.getLogger(getClass().getName() + "@" + Integer.toHexString(hashCode()));
- protected final DictionaryManager dictionaryManager;
+ protected final IDictionaryManager dictionaryManager;
- public AbstractMessageStorage(DictionaryManager dictionaryManager) {
+ public AbstractMessageStorage(IDictionaryManager dictionaryManager) {
this.dictionaryManager = Objects.requireNonNull(dictionaryManager, "Dictionary manager cannot be null");
}

ADD
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/impl/BroadcastMessageStorage.java
+/*******************************************************************************
+ * Copyright 2009-2020 Exactpro (Exactpro Systems Limited)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+package com.exactpro.sf.storage.impl;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+import com.exactpro.sf.common.messages.IHumanMessage;
+import com.exactpro.sf.common.messages.IMessage;
+import com.exactpro.sf.common.util.EPSCommonException;
+import com.exactpro.sf.storage.MessageFilter;
+import com.exactpro.sf.storage.MessageRow;
+import com.exactpro.sf.storage.ScriptRun;
+
+public class BroadcastMessageStorage extends AbstractMessageStorage {
+
+ private static final String ERROR_MESSAGE_ON_STORE = "Can`t store message to all storage";
+ private static final String ERROR_MESSAGE_ON_CLEAR = "Can`t clear message from all storage";
+ private static final String ERROR_MESSAGE_ON_DISPOSE = "Can`t dispose all storages";
+
+ private final AbstractMessageStorage primaryStorage;
+ private final List<AbstractMessageStorage> writableStorages;
+
+ public BroadcastMessageStorage(AbstractMessageStorage primaryStorage, List<AbstractMessageStorage> secondaryStorages) {
+ super(primaryStorage.dictionaryManager);
+ this.primaryStorage = Objects.requireNonNull(primaryStorage, "Primary storage can`t be null");
+ writableStorages = secondaryStorages == null ? new LinkedList<>() : secondaryStorages;
+ writableStorages.add(this.primaryStorage);
+ }
+
+ public BroadcastMessageStorage(AbstractMessageStorage primaryStorage, AbstractMessageStorage... secondaryStorages) {
+ this(primaryStorage, secondaryStorages.length > 0 ? Arrays.asList(secondaryStorages) : null);
+ }
+
+ @Override
+ public ScriptRun openScriptRun(String name, String description) {
+ return primaryStorage.openScriptRun(name, description);
+ }
+
+ @Override
+ public void closeScriptRun(ScriptRun scriptRun) {
+ primaryStorage.closeScriptRun(scriptRun);
+ }
+
+ @Override
+ protected void storeMessage(IMessage message, IHumanMessage humanMessage, String jsonMessage) {
+ EPSCommonException exception = null;
+ for (AbstractMessageStorage storage : writableStorages) {
+ try {
+ storage.storeMessage(message, humanMessage, jsonMessage);
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ if (exception == null) {
+ exception = new EPSCommonException(ERROR_MESSAGE_ON_STORE);
+ }
+ exception.addSuppressed(e);
+ }
+ }
+
+ if (exception != null && exception.getSuppressed().length > 0) {
+ throw exception;
+ }
+ }
+
+ @Override
+ public Iterable<MessageRow> getMessages(int count, MessageFilter filter) {
+ return primaryStorage.getMessages(count, filter);
+ }
+
+ @Override
+ public Iterable<MessageRow> getMessages(int offset, int count, String where) {
+ return primaryStorage.getMessages(offset, count, where);
+ }
+
+ @Override
+ public void clear() {
+ EPSCommonException exception = null;
+ for (AbstractMessageStorage storage : writableStorages) {
+ try {
+ storage.clear();
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ if (exception == null) {
+ exception = new EPSCommonException(ERROR_MESSAGE_ON_CLEAR);
+ }
+ exception.addSuppressed(e);
+ }
+ }
+
+ if (exception != null && exception.getSuppressed().length > 0) {
+ throw exception;
+ }
+ }
+
+ @Override
+ public void dispose() {
+
+ EPSCommonException exception = null;
+
+ for (AbstractMessageStorage storage : writableStorages) {
+ try {
+ storage.dispose();
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ if (exception == null) {
+ exception = new EPSCommonException(ERROR_MESSAGE_ON_DISPOSE);
+ }
+ exception.addSuppressed(e);
+ }
+ }
+
+ if (exception != null && exception.getSuppressed().length > 0) {
+ throw exception;
+ }
+ }
+}

ADD
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/storage/impl/FakeAbstractMessageStorage.java
+/*******************************************************************************
+ * Copyright 2009-2020 Exactpro (Exactpro Systems Limited)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+package com.exactpro.sf.storage.impl;
+
+import java.time.Instant;
+import java.util.Collections;
+
+import com.exactpro.sf.common.messages.IHumanMessage;
+import com.exactpro.sf.common.messages.IMessage;
+import com.exactpro.sf.configuration.DictionaryManager;
+import com.exactpro.sf.storage.MessageFilter;
+import com.exactpro.sf.storage.MessageRow;
+
+public class FakeAbstractMessageStorage extends AbstractMessageStorage {
+
+ public FakeAbstractMessageStorage(DictionaryManager dictionaryManager) {
+ super(dictionaryManager);
+ }
+
+ @Override
+ protected void storeMessage(IMessage message, IHumanMessage humanMessage, String jsonMessage) {
+ logger.trace("Message {} skipped by service settings 'persistMessageToStorage'.", message.getName());
+ }
+
+ @Override
+ public Iterable<MessageRow> getMessages(int count, MessageFilter filter) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Iterable<MessageRow> getMessages(int offset, int count, String where) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void clear() {
+
+ }
+
+ @Override
+ public void dispose() {
+
+ }
+
+ @Override
+ public void removeMessages(Instant olderThan) {
+
+ }
+
+ @Override
+ public void removeMessages(String serviceID) {
+
+ }
+
+
+}

[RM] Feature #62422. Support for loading secondary message storages from extensions and plugins.

Change-Id: I6a481308cf9c3b4d6e22b0acd08e113beec67185