/**
* 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.registry.publication;
import java.security.PrivilegedActionException;
import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.codice.ddf.registry.common.RegistryConstants;
import org.codice.ddf.registry.common.metacard.RegistryObjectMetacardType;
import org.codice.ddf.registry.common.metacard.RegistryUtility;
import org.codice.ddf.registry.federationadmin.service.internal.RegistryPublicationService;
import org.codice.ddf.security.common.Security;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.Attribute;
import ddf.catalog.data.Metacard;
/**
* RegistryPublicationHandler is an org.osgi.service.event.EventHandler that listens for registry
* metacard updates and forwards changes on to any publish locations.
*/
public class RegistryPublicationHandler implements EventHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RegistryPublicationHandler.class);
private static final String METACARD_PROPERTY = "ddf.catalog.event.metacard";
private static final int SHUTDOWN_TIMEOUT_SECONDS = 60;
private static final int PUBLICATION_DELAY = 3; //seconds
private final RegistryPublicationService registryPublicationService;
private final ScheduledExecutorService executor;
public RegistryPublicationHandler(RegistryPublicationService registryPublicationService,
ScheduledExecutorService service) {
this.registryPublicationService = registryPublicationService;
this.executor = service;
}
public void destroy() {
executor.shutdown();
try {
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
LOGGER.debug("Thread pool didn't terminate");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
@Override
public void handleEvent(Event event) {
Metacard mcard = (Metacard) event.getProperty(METACARD_PROPERTY);
if (mcard == null || !mcard.getTags()
.contains(RegistryConstants.REGISTRY_TAG)) {
return;
}
executor.schedule(() -> processUpdate(mcard), PUBLICATION_DELAY, TimeUnit.SECONDS);
}
private void processUpdate(Metacard mcard) {
if (RegistryUtility.getListOfStringAttribute(mcard,
RegistryObjectMetacardType.PUBLISHED_LOCATIONS)
.isEmpty()) {
return;
}
Attribute lastPublished = mcard.getAttribute(RegistryObjectMetacardType.LAST_PUBLISHED);
Date datePublished = null;
if (lastPublished != null) {
datePublished = (Date) lastPublished.getValue();
}
//If we haven't published this metacard before or if we have had an update
//since the last time we published send an update to the remote location
if ((datePublished == null || datePublished.before(mcard.getModifiedDate()))) {
try {
Security security = Security.getInstance();
security.runAsAdminWithException(() -> {
registryPublicationService.update(mcard);
return null;
});
} catch (PrivilegedActionException e) {
LOGGER.debug("Unable to send update for {}", mcard.getTitle());
}
}
}
}