/**
* 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 ddf.catalog.federation.layered.replication;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.cxf.jaxrs.client.WebClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.Metacard;
import ddf.catalog.operation.CreateResponse;
import ddf.catalog.operation.DeleteResponse;
import ddf.catalog.operation.Update;
import ddf.catalog.operation.UpdateRequest;
import ddf.catalog.operation.UpdateResponse;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PostIngestPlugin;
import ddf.catalog.transform.CatalogTransformerException;
import ddf.catalog.transform.MetacardTransformer;
public class RestReplicatorPlugin implements PostIngestPlugin {
private static final Logger LOGGER = LoggerFactory.getLogger(RestReplicatorPlugin.class);
/**
* A configurable property of parent's location.
*/
private String parentAddress = null;
private MetacardTransformer transformer = null;
private WebClient client;
public RestReplicatorPlugin(String endpointAddress) {
setParentAddress(endpointAddress);
}
@Override
public CreateResponse process(CreateResponse input) throws PluginExecutionException {
if (client != null && transformer != null) {
for (Metacard m : input.getCreatedMetacards()) {
String data = transform(m, client);
Response r = client.post(data);
LOGGER.debug("Posted the following GeoJSON: {}\n", data);
LOGGER.debug("RESPONSE: [{}]", ToStringBuilder.reflectionToString(r));
}
}
return input;
}
@Override
public UpdateResponse process(UpdateResponse input) throws PluginExecutionException {
if (client != null && transformer != null) {
WebClient updateClient = WebClient.fromClient(client);
updateClient.type(MediaType.APPLICATION_JSON);
List<Update> updates = input.getUpdatedMetacards();
if (updates == null) {
return input;
}
UpdateRequest request = input.getRequest();
if (request != null && !Metacard.ID.equals(request.getAttributeName())) {
throw new PluginExecutionException(new UnsupportedOperationException(
"Cannot replicate records that are not updated by " + Metacard.ID));
}
for (int i = 0; i < updates.size(); i++) {
Update update = updates.get(i);
if (request != null && request.getUpdates() != null
&& request.getUpdates().get(i) != null
&& request.getUpdates().get(i).getKey() != null) {
updateClient.path(request.getUpdates().get(i).getKey());
Metacard newMetacard = update.getNewMetacard();
String newData = transform(newMetacard, updateClient);
Response r = updateClient.put(newData);
LOGGER.debug("RESPONSE: [{}]", ToStringBuilder.reflectionToString(r));
}
}
}
return input;
}
@Override
public DeleteResponse process(DeleteResponse input) throws PluginExecutionException {
if (client != null) {
WebClient updateClient = WebClient.fromClient(client);
updateClient.type(MediaType.APPLICATION_JSON);
if (input == null || input.getDeletedMetacards() == null || input.getDeletedMetacards()
.isEmpty()) {
return input;
}
for (int i = 0; i < input.getDeletedMetacards().size(); i++) {
Metacard metacard = input.getDeletedMetacards().get(i);
if (metacard != null && metacard.getId() != null) {
updateClient.path(metacard.getId());
Response r = updateClient.delete();
LOGGER.debug("RESPONSE: [{}]", ToStringBuilder.reflectionToString(r));
}
}
}
return input;
}
public String getParentAddress() {
return parentAddress;
}
public void setParentAddress(String endpointAddress) {
if (endpointAddress == null) {
this.parentAddress = endpointAddress;
client = null;
} else if (!endpointAddress.equals(this.parentAddress)) {
String previous = this.parentAddress;
this.parentAddress = endpointAddress;
client = WebClient.create(this.parentAddress, true);
LOGGER.debug("Changed the parent address property from [{}] to [{}]", previous,
this.parentAddress);
}
}
public MetacardTransformer getTransformer() {
return transformer;
}
public void setTransformer(MetacardTransformer transformer) {
this.transformer = transformer;
LOGGER.debug("Changed transformer to [{}]", this.transformer);
}
private String transform(Metacard m, WebClient client) throws PluginExecutionException {
BinaryContent binaryContent;
try {
binaryContent = transformer.transform(m, null);
client.type(getValidMimeType(binaryContent.getMimeTypeValue()));
return new String(binaryContent.getByteArray(), StandardCharsets.UTF_8);
} catch (IOException e) {
LOGGER.warn("Could not understand metacard.", e);
throw new PluginExecutionException("Could not send metacard.");
} catch (CatalogTransformerException e) {
LOGGER.warn("Could not transform metacard.", e);
throw new PluginExecutionException("Could not send metacard.");
}
}
private String getValidMimeType(String mimeTypeValue) {
if (mimeTypeValue == null) {
return MediaType.APPLICATION_OCTET_STREAM;
}
return mimeTypeValue;
}
}