/**
* Copyright (c) Codice Foundation
* <p>
* This 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 any later version.
* <p>
* 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. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package org.codice.ddf.itests.common;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.CatalogFramework;
import ddf.catalog.operation.SourceInfoResponse;
import ddf.catalog.operation.impl.SourceInfoRequestEnterprise;
import ddf.catalog.operation.impl.SourceInfoRequestLocal;
import ddf.catalog.source.CatalogProvider;
import ddf.catalog.source.CatalogStore;
import ddf.catalog.source.FederatedSource;
import ddf.catalog.source.Source;
import ddf.catalog.source.SourceDescriptor;
import ddf.catalog.source.SourceUnavailableException;
public class CatalogBundle {
protected static final Logger LOGGER = LoggerFactory.getLogger(CatalogBundle.class);
public static final long CATALOG_PROVIDER_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
public static final String CATALOG_FRAMEWORK_PID = "ddf.catalog.CatalogFrameworkImpl";
public static final String RESOURCE_DOWNLOAD_MANAGER_PID =
"ddf.catalog.resource.download.ReliableResourceDownloadManager";
private final ServiceManager serviceManager;
private final AdminConfig adminConfig;
public CatalogBundle(ServiceManager serviceManager, AdminConfig adminConfig) {
this.serviceManager = serviceManager;
this.adminConfig = adminConfig;
}
public CatalogProvider waitForCatalogProvider() throws InterruptedException {
LOGGER.info("Waiting for CatalogProvider to become available.");
serviceManager.printInactiveBundlesInfo();
CatalogProvider provider = null;
CatalogFramework framework = null;
long timeoutLimit = System.currentTimeMillis() + CATALOG_PROVIDER_TIMEOUT;
boolean available = false;
while (!available) {
if (provider == null) {
ServiceReference<CatalogFramework> frameworkRef = serviceManager.getServiceReference(CatalogFramework.class);
ServiceReference<CatalogProvider> providerRef = serviceManager.getServiceReference(
CatalogProvider.class);
if (providerRef != null) {
provider = serviceManager.getService(providerRef);
}
if (frameworkRef != null) {
framework = serviceManager.getService(frameworkRef);
}
}
if (framework != null && provider != null) {
SourceInfoRequestLocal sourceInfoRequestEnterprise =
new SourceInfoRequestLocal(true);
try {
SourceInfoResponse sources = framework.getSourceInfo(sourceInfoRequestEnterprise);
Set<SourceDescriptor> sourceInfo = sources.getSourceInfo();
for (SourceDescriptor sourceDescriptor : sourceInfo) {
if (sourceDescriptor.getSourceId().equals(provider.getId())) {
available = sourceDescriptor.isAvailable() && provider.isAvailable();
LOGGER.info("CatalogProvider.isAvailable = {}", available);
}
}
} catch (SourceUnavailableException e) {
available = false;
}
}
if (!available) {
if (System.currentTimeMillis() > timeoutLimit) {
LOGGER.info("CatalogProvider.isAvailable = false");
serviceManager.printInactiveBundles();
fail(String.format("Catalog provider timed out after %d minutes.",
TimeUnit.MILLISECONDS.toMinutes(CATALOG_PROVIDER_TIMEOUT)));
}
Thread.sleep(1000);
}
}
LOGGER.info("CatalogProvider is available.");
return provider;
}
public FederatedSource waitForFederatedSource(String id)
throws InterruptedException, InvalidSyntaxException {
LOGGER.info("Waiting for FederatedSource {} to become available.", id);
return waitForSource(id, FederatedSource.class);
}
public CatalogStore waitForCatalogStore(String id)
throws InterruptedException, InvalidSyntaxException {
LOGGER.info("Waiting for CatalogStore {} to become available.", id);
return waitForSource(id, CatalogStore.class);
}
private <T extends Source> T waitForSource(String id, Class<T> type)
throws InterruptedException, InvalidSyntaxException {
T source = null;
long timeoutLimit = System.currentTimeMillis() + CATALOG_PROVIDER_TIMEOUT;
boolean available = false;
while (!available) {
ServiceReference<CatalogFramework> frameworkRef = serviceManager.getServiceReference(CatalogFramework.class);
CatalogFramework framework = null;
if (frameworkRef != null) {
framework = serviceManager.getService(frameworkRef);
}
if (source == null) {
source = serviceManager.getServiceReferences(type, null)
.stream()
.map(serviceManager::getService)
.filter(src -> id.equals(src.getId()))
.findFirst()
.orElse(null);
}
if (source != null && framework != null) {
SourceInfoRequestEnterprise sourceInfoRequestEnterprise =
new SourceInfoRequestEnterprise(true);
try {
SourceInfoResponse sources = framework.getSourceInfo(sourceInfoRequestEnterprise);
Set<SourceDescriptor> sourceInfo = sources.getSourceInfo();
for (SourceDescriptor sourceDescriptor : sourceInfo) {
if (sourceDescriptor.getSourceId().equals(source.getId())) {
available = sourceDescriptor.isAvailable() && source.isAvailable();
LOGGER.info("Source.isAvailable = {} Framework.isAvailable = {}",
source.isAvailable(),
sourceDescriptor.isAvailable());
}
}
} catch (SourceUnavailableException e) {
available = false;
}
} else {
LOGGER.info("Currently no source of type {} and name {} could be found",
type.getName(),
id);
}
if (!available) {
if (System.currentTimeMillis() > timeoutLimit) {
fail("Source (" + id + ") was not created in a timely manner.");
}
Thread.sleep(1000);
}
}
LOGGER.info("Source {} is available.", id);
return source;
}
public CatalogFramework getCatalogFramework() throws InterruptedException {
LOGGER.info("getting framework");
CatalogFramework catalogFramework = null;
ServiceReference<CatalogFramework> providerRef = serviceManager.getServiceReference(
CatalogFramework.class);
if (providerRef != null) {
catalogFramework = serviceManager.getService(providerRef);
}
return catalogFramework;
}
public void setFanout(boolean fanoutEnabled) throws IOException {
Map<String, Object> properties = adminConfig.getDdfConfigAdmin()
.getProperties(CATALOG_FRAMEWORK_PID);
if (properties == null) {
properties = new Hashtable<>();
}
if (fanoutEnabled) {
properties.put("fanoutEnabled", "True");
} else {
properties.put("fanoutEnabled", "False");
}
serviceManager.startManagedService(CATALOG_FRAMEWORK_PID, properties);
}
public void setFanoutTagBlacklist(List<String> blacklist) throws IOException {
Map<String, Object> properties = adminConfig.getDdfConfigAdmin()
.getProperties(CATALOG_FRAMEWORK_PID);
if (blacklist != null) {
if (properties == null) {
properties = new Hashtable<>();
}
properties.put("fanoutTagBlacklist", String.join(",", blacklist));
serviceManager.startManagedService(CATALOG_FRAMEWORK_PID, properties);
}
}
public void setupCaching(boolean cachingEnabled) throws IOException {
if (cachingEnabled) {
setConfigProperty(RESOURCE_DOWNLOAD_MANAGER_PID, "cacheEnabled", "True");
} else {
setConfigProperty(RESOURCE_DOWNLOAD_MANAGER_PID, "cacheEnabled", "False");
}
}
public void setDownloadRetryDelayInSeconds(int delay) throws IOException {
setConfigProperty(RESOURCE_DOWNLOAD_MANAGER_PID, "delayBetweenAttempts", delay);
}
public void setupMaxDownloadRetryAttempts(int maxRetryAttempts) throws IOException {
setConfigProperty(RESOURCE_DOWNLOAD_MANAGER_PID, "maxRetryAttempts", maxRetryAttempts);
}
private void setConfigProperty(String pid, String propertyName, Object propertyValue)
throws IOException {
Map<String, Object> existingProperties = Optional.ofNullable(adminConfig.getDdfConfigAdmin()
.getProperties(pid))
.orElse(new Hashtable<>());
Hashtable<String, Object> updatedProperties = new Hashtable<>();
updatedProperties.putAll(existingProperties);
updatedProperties.put(propertyName, propertyValue);
Configuration configuration = adminConfig.getConfiguration(RESOURCE_DOWNLOAD_MANAGER_PID,
null);
configuration.update(updatedProperties);
}
}