ddf.content.plugin.cataloger.CatalogContentPlugin.java Source code

Java tutorial

Introduction

Here is the source code for ddf.content.plugin.cataloger.CatalogContentPlugin.java

Source

/**
 * 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.content.plugin.cataloger;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.activation.MimeType;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.LoggerFactory;
import org.slf4j.ext.XLogger;

import com.google.common.io.FileBackedOutputStream;

import ddf.catalog.CatalogFramework;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.MetacardCreationException;
import ddf.catalog.data.impl.AttributeImpl;
import ddf.catalog.transform.CatalogTransformerException;
import ddf.catalog.transform.InputTransformer;
import ddf.content.data.ContentItem;
import ddf.content.operation.CreateResponse;
import ddf.content.operation.DeleteResponse;
import ddf.content.operation.UpdateResponse;
import ddf.content.operation.impl.CreateResponseImpl;
import ddf.content.operation.impl.DeleteResponseImpl;
import ddf.content.operation.impl.UpdateResponseImpl;
import ddf.content.plugin.ContentPlugin;
import ddf.content.plugin.PluginExecutionException;
import ddf.mime.MimeTypeToTransformerMapper;
import ddf.security.SubjectUtils;

public class CatalogContentPlugin implements ContentPlugin {
    private static final XLogger LOGGER = new XLogger(LoggerFactory.getLogger(CatalogContentPlugin.class));

    private static final String CATALOG_ID = "Catalog-ID";

    private static final String DEFAULT_METACARD_TRANSFORMER = "geojson";

    private final CatalogFramework catalogFramework;

    private Cataloger cataloger;

    private MimeTypeToTransformerMapper mimeTypeToTransformerMapper;

    public CatalogContentPlugin(CatalogFramework catalogFramework,
            MimeTypeToTransformerMapper mimeTypeToTransformerMapper) {
        LOGGER.trace("INSIDE: CatalogContentPlugin constructor");

        this.catalogFramework = catalogFramework;
        this.cataloger = new Cataloger(catalogFramework);
        this.mimeTypeToTransformerMapper = mimeTypeToTransformerMapper;
    }

    @Override
    public CreateResponse process(CreateResponse input) throws PluginExecutionException {
        LOGGER.trace("ENTERING: process(CreateResponse)");

        ContentItem createdContentItem = input.getCreatedContentItem();
        CreateResponseImpl response = new CreateResponseImpl(input);
        MimeType mimeType = createdContentItem.getMimeType();
        InputStream stream = null;
        try {
            stream = createdContentItem.getInputStream();
        } catch (IOException e) {
            throw new PluginExecutionException("Unable to read InputStream in created content item.", e);
        }

        if (stream == null) {
            throw new PluginExecutionException("InputStream is null in created content item.");
        }

        try {
            Metacard metacard = generateMetacard(createdContentItem, mimeType, createdContentItem.getUri(), stream);
            String catalogId = cataloger.createMetacard(metacard);
            LOGGER.debug("catalogId = " + catalogId);
            Map<String, String> properties = response.getResponseProperties();
            properties.put(CATALOG_ID, catalogId);
            response.setResponseProperties(properties);
            if (metacard != null) {
                try {
                    BinaryContent binaryContent = catalogFramework.transform(metacard, DEFAULT_METACARD_TRANSFORMER,
                            null);
                    response.setCreatedMetadata(binaryContent.getByteArray());
                    response.setCreatedMetadataMimeType(binaryContent.getMimeType().toString());
                } catch (IOException | CatalogTransformerException e) {
                    LOGGER.warn("Unable to transform metacard to readable metadata.", e);
                }
            }
        } catch (MetacardCreationException e) {
            LOGGER.warn(e.getMessage(), e);
            throw new PluginExecutionException(e.getMessage(), e);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                }
            }
        }

        LOGGER.trace("EXITING: process(CreateResponse)");

        return response;
    }

    @Override
    public UpdateResponse process(UpdateResponse input) throws PluginExecutionException {
        LOGGER.trace("ENTERING: process(UpdateResponse)");

        ContentItem updatedContentItem = input.getUpdatedContentItem();
        UpdateResponseImpl response = new UpdateResponseImpl(input);
        MimeType mimeType = updatedContentItem.getMimeType();
        InputStream stream = null;
        try {
            stream = updatedContentItem.getInputStream();
        } catch (IOException e) {
            throw new PluginExecutionException("Unable to read InputStream in updated content item.", e);
        }

        if (stream == null) {
            throw new PluginExecutionException("InputStream is null in updated content item.");
        }

        try {
            Metacard metacard = generateMetacard(updatedContentItem, mimeType, updatedContentItem.getUri(), stream);
            String catalogId = cataloger.updateMetacard(updatedContentItem.getUri(), metacard);
            LOGGER.debug("catalogId = " + catalogId);
            Map<String, String> properties = response.getResponseProperties();
            properties.put(CATALOG_ID, catalogId);
            response.setResponseProperties(properties);
            if (metacard != null) {
                try {
                    BinaryContent binaryContent = catalogFramework.transform(metacard, DEFAULT_METACARD_TRANSFORMER,
                            null);
                    response.setUpdatedMetadata(binaryContent.getByteArray());
                    response.setUpdatedMetadataMimeType(binaryContent.getMimeType().toString());
                } catch (IOException | CatalogTransformerException e) {
                    LOGGER.warn("Unable to transform metacard to readable metadata.", e);
                }
            }
        } catch (MetacardCreationException e) {
            LOGGER.warn(e.getMessage(), e);
            throw new PluginExecutionException(e.getMessage(), e);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                }
            }
        }

        LOGGER.trace("EXITING: process(UpdateResponse)");

        return response;
    }

    @Override
    public DeleteResponse process(DeleteResponse input) throws PluginExecutionException {
        LOGGER.trace("ENTERING: process(DeleteResponse)");

        DeleteResponseImpl response = new DeleteResponseImpl(input);

        String catalogId = cataloger.deleteMetacard(input.getContentItem().getUri());
        if (catalogId != null && !catalogId.isEmpty()) {
            // Create response indicating file (actually, catalog entry) was deleted
            response = new DeleteResponseImpl(input.getRequest(), input.getContentItem(), true,
                    input.getResponseProperties(), input.getProperties());
        }

        LOGGER.debug("catalogId = " + catalogId);
        Map<String, String> properties = response.getResponseProperties();
        properties.put(CATALOG_ID, catalogId);
        response.setResponseProperties(properties);

        LOGGER.trace("EXITING: process(DeleteResponse)");

        return response;
    }

    private Metacard generateMetacard(ContentItem contentItem, MimeType mimeType, String uri, InputStream message)
            throws MetacardCreationException {
        LOGGER.trace("ENTERING: generateMetacard");

        List<InputTransformer> listOfCandidates = mimeTypeToTransformerMapper.findMatches(InputTransformer.class,
                mimeType);

        LOGGER.debug("List of matches for mimeType [ {} ]: {}", mimeType, listOfCandidates);

        Metacard generatedMetacard = null;
        try (FileBackedOutputStream fileBackedOutputStream = new FileBackedOutputStream(1000000)) {

            long size;
            try {
                size = IOUtils.copyLarge(message, fileBackedOutputStream);
                LOGGER.debug("Copied {} bytes of file in content framework", size);
            } catch (IOException e) {
                throw new MetacardCreationException("Could not copy bytes of content message.", e);
            }

            // Multiple InputTransformers may be found that match the mime type.
            // Need to try each InputTransformer until we find one that can successfully transform
            // the input stream's data into a metacard. Once an InputTransformer is found that
            // can create the metacard, then do not need to try any remaining InputTransformers.
            for (InputTransformer transformer : listOfCandidates) {

                try (InputStream inputStreamMessageCopy = fileBackedOutputStream.asByteSource().openStream()) {
                    generatedMetacard = transformer.transform(inputStreamMessageCopy);
                    if (generatedMetacard != null) {
                        try {
                            Subject subject = SecurityUtils.getSubject();
                            if (subject != null) {
                                generatedMetacard.setAttribute(new AttributeImpl(Metacard.POINT_OF_CONTACT,
                                        SubjectUtils.getName(subject)));
                            }
                        } catch (IllegalStateException e) {
                            LOGGER.debug("Unable to retrieve user from request.", e);
                        }

                        if (uri != null) {
                            //Setting the non-transformer specific information not including creation and modification dates/times
                            generatedMetacard.setAttribute(new AttributeImpl(Metacard.RESOURCE_URI, uri));
                            generatedMetacard
                                    .setAttribute(new AttributeImpl(Metacard.RESOURCE_SIZE, String.valueOf(size)));
                        } else {
                            LOGGER.debug("Metacard had a null uri");
                        }
                        if (StringUtils.isBlank(generatedMetacard.getTitle())) {
                            LOGGER.debug("Metacard title was blank. Setting title to filename.");
                            generatedMetacard
                                    .setAttribute(new AttributeImpl(Metacard.TITLE, contentItem.getFilename()));
                        }
                        break;
                    }
                } catch (IOException | CatalogTransformerException e) {
                    LOGGER.debug("Transformer [" + transformer + "] could not create metacard.", e);
                }

            }

            if (generatedMetacard == null) {
                throw new MetacardCreationException(
                        "Could not create metacard with mimeType " + mimeType + ". No valid transformers found.");
            }

            LOGGER.trace("EXITING: generateMetacard");
        } catch (IOException e) {
            LOGGER.debug("Error encountered while using filed backed stream.", e);
        }

        return generatedMetacard;
    }

}