package com.constellio.app.services.extensions.plugins;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.ID_MISMATCH;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_EXISTING_ID;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_ID_FORMAT;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_JAR;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_MANIFEST;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_MIGRATION_SCRIPT;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_START;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.INVALID_VERSION;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.MORE_THAN_ONE_INSTALLABLE_MODULE_PER_JAR;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.NO_ID;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.NO_INSTALLABLE_MODULE_DETECTED_FROM_JAR;
import static com.constellio.app.services.extensions.plugins.PluginActivationFailureCause.NO_VERSION;
import static com.constellio.app.services.extensions.plugins.pluginInfo.ConstellioPluginStatus.ENABLED;
import static com.constellio.app.services.extensions.plugins.pluginInfo.ConstellioPluginStatus.INVALID;
import static com.constellio.app.services.extensions.plugins.pluginInfo.ConstellioPluginStatus.READY_TO_INSTALL;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import com.constellio.app.entities.modules.InstallableModule;
import com.constellio.app.entities.modules.MigrationScript;
import com.constellio.app.entities.navigation.NavigationConfig;
import com.constellio.app.services.extensions.plugins.ConstellioPluginManagerRuntimeException.InvalidId.InvalidId_BlankId;
import com.constellio.app.services.extensions.plugins.ConstellioPluginManagerRuntimeException.InvalidId.InvalidId_ExistingId;
import com.constellio.app.services.extensions.plugins.ConstellioPluginManagerRuntimeException.InvalidId.InvalidId_NonAlphaNumeric;
import com.constellio.app.services.extensions.plugins.pluginInfo.ConstellioPluginInfo;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.model.entities.configs.SystemConfiguration;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.SDKFoldersLocator;
public class JSPFConstellioPluginManagerAcceptanceTest extends ConstellioTest {
private ConstellioPluginManager pluginManager;
private File validModule, withoutConstellioVersion, validModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate,
invalidIdFormat, existingId, jarWithInvalidVersion,
idMissMatch, invalidModuleInMigrate, invalidModuleInStart, jarWithoutCode, jarWithoutVersion, jarWithoutManifest,
inexisting, noInstallableModule, severalInstallableModules;
private File pluginsFolder;
@Before
public void setUp()
throws Exception {
pluginManager = getAppLayerFactory().getPluginManager();
pluginsFolder = getAppLayerFactory().getAppLayerConfiguration().getPluginsFolder();
initTestFiles();
}
private void initTestFiles()
throws IOException {
File jarsFolder = new SDKFoldersLocator().getPluginsJarsFolder();
validModule = new File(jarsFolder, "ValidModule.zip");
withoutConstellioVersion = new File(jarsFolder, "WithoutConstellioVersion.zip");
validModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate = new File(jarsFolder,
"ValidModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate.zip");
idMissMatch = new File(jarsFolder, "IdMissMatch.zip");
invalidModuleInMigrate = new File(jarsFolder, "InvalidModuleInMigrate.zip");
invalidModuleInStart = new File(jarsFolder, "InvalidModuleInStart.zip");
noInstallableModule = new File(jarsFolder, "NoInstallableModule.zip");
severalInstallableModules = new File(jarsFolder, "SeveralInstallableModules.zip");
invalidIdFormat = new File(jarsFolder, "InvalidIdFormat.zip");
existingId = new File(jarsFolder, "ModuleWithRMId.zip");
jarWithInvalidVersion = new File(jarsFolder, "jarWithInvalidVersion.zip");
jarWithoutCode = new File(jarsFolder, "jarWithoutCode.zip");
jarWithoutVersion = new File(jarsFolder, "jarWithoutVersion.zip");
jarWithoutManifest = new File(jarsFolder, "jarWithoutManifest.zip");
inexisting = new File(jarsFolder, "inexisting.zip");
}
//@Test
public void givenInvalidModuleWhenDetectPluginsThenPluginWithAdequateErrorStatus() {
PluginActivationFailureCause errorCause = pluginManager.prepareInstallablePlugin(invalidModuleInMigrate);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(invalidModuleInStart);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(noInstallableModule);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(severalInstallableModules);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(idMissMatch);
assertThat(errorCause).isNull();
pluginManager.detectPlugins();
List<ConstellioPluginInfo> invalidPlugins = pluginManager.getPlugins(INVALID);
assertThat(invalidPlugins).extracting("code", "pluginActivationFailureCause").containsOnly(
//tuple("InvalidModuleInMigrate", "INVALID_MIGRATION_SCRIPT"),
//tuple("InvalidModuleInStart", "INVALID_START"),
tuple("NoInstallableModule", NO_INSTALLABLE_MODULE_DETECTED_FROM_JAR),
tuple("SeveralInstallableModules", MORE_THAN_ONE_INSTALLABLE_MODULE_PER_JAR),
tuple("IdMissMatch2", ID_MISMATCH)
);
List<ConstellioPluginInfo> validPluginsUntilMigration = pluginManager.getPlugins(ENABLED);
assertThat(validPluginsUntilMigration).extracting("code").contains(
"InvalidModuleInMigrate", "InvalidModuleInStart");
assertThat(pluginManager.getRegistredModulesAndActivePlugins()).extracting("id").contains(
"InvalidModuleInMigrate", "InvalidModuleInStart"
);
}
//@Test
public void givenValidModuleWhenDetectPluginsThenModuleDetectedCorrectly() {
PluginActivationFailureCause errorCause = pluginManager.prepareInstallablePlugin(validModule);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(validModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate);
assertThat(errorCause).isNull();
errorCause = pluginManager.prepareInstallablePlugin(withoutConstellioVersion);
assertThat(errorCause).isNull();
pluginManager.detectPlugins();
List<ConstellioPluginInfo> invalidPlugins = pluginManager.getPlugins(INVALID);
assertThat(invalidPlugins).isEmpty();
List<ConstellioPluginInfo> validPlugins = pluginManager.getPlugins(ENABLED);
assertThat(validPlugins).extracting("code").contains(
"ValidModule", "ValidModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate"
, "WithoutConstellioVersion");
assertThat(pluginManager.getRegistredModulesAndActivePlugins()).extracting("id").contains(
"ValidModule", "ValidModuleThrowingExceptionInMethodsDifferentFromStartAndMigrate"
, "WithoutConstellioVersion"
);
}
@Test
public void whenRegisterThenBehavesAsExpected() {
List<InstallableModule> modulesBefore = pluginManager.getRegistredModulesAndActivePlugins();
try {
pluginManager.registerModule(new TestInstallableModule("rm"));
fail("Could not register two modules with same id");
} catch (InvalidId_ExistingId e) {
//ok
}
try {
pluginManager.registerModule(new TestInstallableModule("<"));
fail("Could not register module with non alpha numeric id");
} catch (InvalidId_NonAlphaNumeric e) {
//ok
}
try {
pluginManager.registerModule(new TestInstallableModule(null));
fail("Could not register module with blank id");
} catch (InvalidId_BlankId e) {
//ok
}
try {
pluginManager.registerModule(new TestInstallableModule(" "));
fail("Could not register module with blank id");
} catch (InvalidId_BlankId e) {
//ok
}
InstallableModule validModule = new TestInstallableModule("validNonregistredId");
pluginManager.registerModule(validModule);
List<InstallableModule> modulesAfter = pluginManager.getRegistredModulesAndActivePlugins();
List<InstallableModule> expectedModules = new ArrayList<>(modulesBefore);
expectedModules.add(validModule);
assertThat(modulesAfter).containsAll(expectedModules).extracting("id");
}
@Test
public void givenValidModuleWhenPrepareInstallablePluginThenModuleAddedToConfigAndSaved() {
PluginActivationFailureCause errorCause = pluginManager.prepareInstallablePlugin(validModule);
assertThat(errorCause).isNull();
//saved
List<String> pluginsFolderFilesName = listFilesHavingNameInPluginsFolder("ValidModule.jar.new");
assertThat(pluginsFolderFilesName.size()).isEqualTo(1);
//added to config
List<ConstellioPluginInfo> readyToInstallPlugins = pluginManager
.getPlugins(READY_TO_INSTALL);
assertThat(readyToInstallPlugins).extracting("code").contains("ValidModule");
}
@Test
public void givenInvalidModuleWhenPrepareInstallablePluginThenReturnExpectedError() {
PluginActivationFailureCause errorCause = pluginManager.prepareInstallablePlugin(jarWithoutManifest);
assertThat(errorCause).isEqualTo(INVALID_MANIFEST);
errorCause = pluginManager.prepareInstallablePlugin(inexisting);
assertThat(errorCause).isEqualTo(INVALID_JAR);
errorCause = pluginManager.prepareInstallablePlugin(jarWithInvalidVersion);
assertThat(errorCause).isEqualTo(INVALID_VERSION);
errorCause = pluginManager.prepareInstallablePlugin(jarWithoutCode);
assertThat(errorCause).isEqualTo(NO_ID);
errorCause = pluginManager.prepareInstallablePlugin(jarWithoutVersion);
assertThat(errorCause).isEqualTo(NO_VERSION);
addValidJarInfoToConfig(new ConstellioPluginInfo().setCode("ValidModule").setVersion("2.02").setPluginStatus(ENABLED));
errorCause = pluginManager.prepareInstallablePlugin(validModule);
assertThat(errorCause).isEqualTo(PluginActivationFailureCause.CANNOT_INSTALL_OLDER_VERSION);
errorCause = pluginManager.prepareInstallablePlugin(invalidIdFormat);
assertThat(errorCause).isEqualTo(INVALID_ID_FORMAT);
errorCause = pluginManager.prepareInstallablePlugin(existingId);
assertThat(errorCause).isEqualTo(INVALID_EXISTING_ID);
}
@Test
public void whenMarkPluginAsDisabledThenConfigManagerCalledWithAppropriateParameter() {
ConstellioPluginConfigurationManager mockedPluginManager = mock(ConstellioPluginConfigurationManager.class);
JSPFConstellioPluginManager newPluginManager = new JSPFConstellioPluginManager(null,
getAppLayerFactory().getAppLayerConfiguration().getPluginsManagementOnStartupFile(), null, mockedPluginManager);
newPluginManager.markPluginAsDisabled("id");
verify(mockedPluginManager, times(1)).markPluginAsDisabled("id");
}
@Test
public void whenMarkPluginAsEnabledThenConfigManagerCalledWithAppropriateParameter() {
ConstellioPluginConfigurationManager mockedPluginManager = mock(ConstellioPluginConfigurationManager.class);
JSPFConstellioPluginManager newPluginManager = new JSPFConstellioPluginManager(null,
getAppLayerFactory().getAppLayerConfiguration().getPluginsManagementOnStartupFile(), null, mockedPluginManager);
newPluginManager.markPluginAsEnabled("id");
verify(mockedPluginManager, times(1)).markPluginAsEnabled("id");
}
@Test
public void whenHandleModuleNotStartedCorrectlyThenConfigManagerCalledWithAppropriateParameter() {
ConstellioPluginConfigurationManager mockedPluginManager = mock(ConstellioPluginConfigurationManager.class);
JSPFConstellioPluginManager newPluginManager = new JSPFConstellioPluginManager(null,
getAppLayerFactory().getAppLayerConfiguration().getPluginsManagementOnStartupFile(), null, mockedPluginManager);
TestInstallableModule module = new TestInstallableModule("id");
newPluginManager.handleModuleNotStartedCorrectly(module, zeCollection, null);
verify(mockedPluginManager, times(1)).invalidateModule("id", INVALID_START, null);
}
@Test
public void whenHandleModuleNotMigratedCorrectlyThenConfigManagerCalledWithAppropriateParameter() {
ConstellioPluginConfigurationManager mockedPluginManager = mock(ConstellioPluginConfigurationManager.class);
JSPFConstellioPluginManager newPluginManager = new JSPFConstellioPluginManager(null,
getAppLayerFactory().getAppLayerConfiguration().getPluginsManagementOnStartupFile(), null, mockedPluginManager);
newPluginManager.handleModuleNotMigratedCorrectly("id", zeCollection, null);
verify(mockedPluginManager, times(1)).invalidateModule("id", INVALID_MIGRATION_SCRIPT, null);
}
@Test
public void whenPrepareInstallablePluginThenBehavesAsExpected() {
}
private class TestInstallableModule implements InstallableModule {
private final String id;
public TestInstallableModule(String id) {
this.id = id;
}
@Override
public List<MigrationScript> getMigrationScripts() {
return null;
}
@Override
public void configureNavigation(NavigationConfig config) {
}
@Override
public void start(String collection, AppLayerFactory appLayerFactory) {
}
@Override
public void stop(String collection, AppLayerFactory appLayerFactory) {
}
@Override
public void addDemoData(String collection, AppLayerFactory appLayerFactory) {
}
@Override
public boolean isComplementary() {
return false;
}
@Override
public List<String> getDependencies() {
return null;
}
@Override
public List<SystemConfiguration> getConfigurations() {
return null;
}
@Override
public Map<String, List<String>> getPermissions() {
return null;
}
@Override
public List<String> getRolesForCreator() {
return null;
}
@Override
public String getId() {
return id;
}
@Override
public String getName() {
return null;
}
@Override
public String getPublisher() {
return null;
}
}
private List<String> listFilesHavingNameInPluginsFolder(String... fileNameFilter) {
List<String> returnList = new ArrayList<>();
if (fileNameFilter.length == 0) {
return returnList;
}
for (File file : pluginsFolder.listFiles()) {
for (String validName : fileNameFilter) {
if (file.getName().equals(validName)) {
returnList.add(validName);
}
}
}
return returnList;
}
private void addValidJarInfoToConfig(ConstellioPluginInfo info) {
ConfigManager configManager = getModelLayerFactory().getDataLayerFactory()
.getConfigManager();
ConstellioPluginConfigurationManager pluginConfigManger = new ConstellioPluginConfigurationManager(configManager);
pluginConfigManger.installPlugin(info.getCode(), info.getTitle(), info.getVersion(), info.getRequiredConstellioVersion());
switch (info.getPluginStatus()) {
case ENABLED:
pluginConfigManger.markPluginAsEnabled(info.getCode());
break;
case DISABLED:
pluginConfigManger.markPluginAsDisabled(info.getCode());
break;
case INVALID:
pluginConfigManger.invalidateModule(info.getCode(), info.getPluginActivationFailureCause(), null);
break;
}
}
}