/**
* 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.impl.operations;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.configuration.SystemInfo;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.Constants;
import ddf.catalog.content.data.ContentItem;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.federation.FederationException;
import ddf.catalog.filter.FilterDelegate;
import ddf.catalog.filter.impl.LiteralImpl;
import ddf.catalog.filter.impl.PropertyIsEqualToLiteral;
import ddf.catalog.filter.impl.PropertyNameImpl;
import ddf.catalog.impl.FrameworkProperties;
import ddf.catalog.operation.Query;
import ddf.catalog.operation.QueryRequest;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.ResourceRequest;
import ddf.catalog.operation.ResourceResponse;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.operation.impl.ResourceResponseImpl;
import ddf.catalog.plugin.AccessPlugin;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PolicyPlugin;
import ddf.catalog.plugin.PolicyResponse;
import ddf.catalog.plugin.PostResourcePlugin;
import ddf.catalog.plugin.PreAuthorizationPlugin;
import ddf.catalog.plugin.PreResourcePlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.catalog.resource.DataUsageLimitExceededException;
import ddf.catalog.resource.ResourceNotFoundException;
import ddf.catalog.resource.ResourceNotSupportedException;
import ddf.catalog.resource.ResourceReader;
import ddf.catalog.resource.download.DownloadException;
import ddf.catalog.resourceretriever.LocalResourceRetriever;
import ddf.catalog.resourceretriever.RemoteResourceRetriever;
import ddf.catalog.resourceretriever.ResourceRetriever;
import ddf.catalog.source.FederatedSource;
import ddf.catalog.source.UnsupportedQueryException;
import ddf.catalog.util.impl.DescribableImpl;
/**
* Support class for resource delegate operations for the {@code CatalogFrameworkImpl}.
* <p>
* This class contains six delegated resource methods and methods to support them. No
* operations/support methods should be added to this class except in support of CFI
* resource operations.
*/
public class ResourceOperations extends DescribableImpl {
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceOperations.class);
private static final String FAILED_BY_GET_RESOURCE_PLUGIN =
"Error during Pre/PostResourcePlugin.";
private static final String DEFAULT_RESOURCE_NOT_FOUND_MESSAGE = "Unknown resource request";
// Inject properties
private final FrameworkProperties frameworkProperties;
private final QueryOperations queryOperations;
private final OperationsSecuritySupport opsSecuritySupport;
public ResourceOperations(FrameworkProperties frameworkProperties,
QueryOperations queryOperations, OperationsSecuritySupport opsSecuritySupport) {
this.frameworkProperties = frameworkProperties;
this.queryOperations = queryOperations;
this.opsSecuritySupport = opsSecuritySupport;
setId(SystemInfo.getSiteName());
setVersion(SystemInfo.getVersion());
setOrganization(SystemInfo.getOrganization());
}
//
// Delegate methods
//
public ResourceResponse getEnterpriseResource(ResourceRequest request, boolean fanoutEnabled)
throws IOException, ResourceNotFoundException, ResourceNotSupportedException {
String methodName = "getEnterpriseResource";
LOGGER.debug("ENTERING: {}", methodName);
ResourceResponse resourceResponse = getResource(request, true, null, fanoutEnabled);
LOGGER.debug("EXITING: {}", methodName);
return resourceResponse;
}
public Map<String, Set<String>> getEnterpriseResourceOptions(String metacardId,
boolean fanoutEnabled) throws ResourceNotFoundException {
LOGGER.trace("ENTERING: getEnterpriseResourceOptions");
Set<String> supportedOptions = Collections.emptySet();
try {
QueryRequest queryRequest = new QueryRequestImpl(createMetacardIdQuery(metacardId),
true,
null,
null);
QueryResponse queryResponse = queryOperations.query(queryRequest,
null,
false,
fanoutEnabled);
List<Result> results = queryResponse.getResults();
if (!results.isEmpty()) {
Metacard metacard = results.get(0)
.getMetacard();
String sourceIdOfResult = metacard.getSourceId();
if (sourceIdOfResult != null && sourceIdOfResult.equals(getId())) {
// found entry on local source
supportedOptions = getOptionsFromLocalProvider(metacard);
} else if (sourceIdOfResult != null && !sourceIdOfResult.equals(getId())) {
// found entry on federated source
supportedOptions = getOptionsFromFederatedSource(metacard, sourceIdOfResult);
}
} else {
String message = "Unable to find metacard " + metacardId + " on enterprise.";
LOGGER.debug(message);
LOGGER.trace("EXITING: getEnterpriseResourceOptions");
throw new ResourceNotFoundException(message);
}
} catch (UnsupportedQueryException e) {
LOGGER.debug("Error finding metacard {}", metacardId, e);
LOGGER.trace("EXITING: getEnterpriseResourceOptions");
throw new ResourceNotFoundException("Error finding metacard due to Unsuppported Query",
e);
} catch (FederationException e) {
LOGGER.debug("Error federating query for metacard {}", metacardId, e);
LOGGER.trace("EXITING: getEnterpriseResourceOptions");
throw new ResourceNotFoundException("Error finding metacard due to Federation issue",
e);
} catch (IllegalArgumentException e) {
LOGGER.debug("Metacard couldn't be found {}", metacardId, e);
LOGGER.trace("EXITING: getEnterpriseResourceOptions");
throw new ResourceNotFoundException("Query returned null metacard", e);
}
LOGGER.trace("EXITING: getEnterpriseResourceOptions");
return Collections.singletonMap(ResourceRequest.OPTION_ARGUMENT, supportedOptions);
}
public ResourceResponse getLocalResource(ResourceRequest request, boolean fanoutEnabled)
throws IOException, ResourceNotFoundException, ResourceNotSupportedException {
String methodName = "getLocalResource";
LOGGER.debug("ENTERING: {}", methodName);
ResourceResponse resourceResponse;
if (fanoutEnabled) {
LOGGER.debug("getLocalResource call received, fanning it out to all sites.");
resourceResponse = getEnterpriseResource(request, fanoutEnabled);
} else {
resourceResponse = getResource(request, false, getId(), fanoutEnabled);
}
LOGGER.debug("EXITING: {} ", methodName);
return resourceResponse;
}
public Map<String, Set<String>> getLocalResourceOptions(String metacardId,
boolean fanoutEnabled) throws ResourceNotFoundException {
LOGGER.trace("ENTERING: getLocalResourceOptions");
Map<String, Set<String>> optionsMap;
try {
QueryRequest queryRequest = new QueryRequestImpl(createMetacardIdQuery(metacardId),
false,
Collections.singletonList(getId()),
null);
QueryResponse queryResponse = queryOperations.query(queryRequest,
null,
false,
fanoutEnabled);
List<Result> results = queryResponse.getResults();
if (!results.isEmpty()) {
Metacard metacard = results.get(0)
.getMetacard();
optionsMap = Collections.singletonMap(ResourceRequest.OPTION_ARGUMENT,
getOptionsFromLocalProvider(metacard));
} else {
String message = "Could not find metacard " + metacardId + " on local source";
ResourceNotFoundException resourceNotFoundException = new ResourceNotFoundException(
message);
LOGGER.trace("EXITING: getLocalResourceOptions");
throw resourceNotFoundException;
}
} catch (UnsupportedQueryException e) {
LOGGER.debug("Error finding metacard {}", metacardId, e);
LOGGER.trace("EXITING: getLocalResourceOptions");
throw new ResourceNotFoundException("Error finding metacard due to Unsuppported Query",
e);
} catch (FederationException e) {
LOGGER.debug("Error federating query for metacard {}", metacardId, e);
LOGGER.trace("EXITING: getLocalResourceOptions");
throw new ResourceNotFoundException("Error finding metacard due to Federation issue",
e);
} catch (IllegalArgumentException e) {
LOGGER.debug("Metacard couldn't be found {}", metacardId, e);
LOGGER.trace("EXITING: getLocalResourceOptions");
throw new ResourceNotFoundException("Query returned null metacard", e);
}
LOGGER.trace("EXITING: getLocalResourceOptions");
return optionsMap;
}
public ResourceResponse getResource(ResourceRequest request, String resourceSiteName,
boolean fanoutEnabled)
throws IOException, ResourceNotFoundException, ResourceNotSupportedException {
String methodName = "getResource";
LOGGER.debug("ENTERING: {}", methodName);
ResourceResponse resourceResponse;
if (fanoutEnabled) {
LOGGER.debug("getResource call received, fanning it out to all sites.");
resourceResponse = getEnterpriseResource(request, true);
} else {
resourceResponse = getResource(request, false, resourceSiteName, false);
}
LOGGER.debug("EXITING: {}", methodName);
return resourceResponse;
}
public Map<String, Set<String>> getResourceOptions(String metacardId, String sourceId,
boolean fanoutEnabled) throws ResourceNotFoundException {
LOGGER.trace("ENTERING: getResourceOptions");
Map<String, Set<String>> optionsMap;
try {
LOGGER.debug("source id to get options from: {}", sourceId);
QueryRequest queryRequest = new QueryRequestImpl(createMetacardIdQuery(metacardId),
false,
Collections.singletonList(sourceId == null ? this.getId() : sourceId),
null);
QueryResponse queryResponse = queryOperations.query(queryRequest,
null,
false,
fanoutEnabled);
List<Result> results = queryResponse.getResults();
if (!results.isEmpty()) {
Metacard metacard = results.get(0)
.getMetacard();
// DDF-1763: Check if the source ID passed in is null, empty,
// or the local provider.
if (StringUtils.isEmpty(sourceId) || sourceId.equals(getId())) {
optionsMap = Collections.singletonMap(ResourceRequest.OPTION_ARGUMENT,
getOptionsFromLocalProvider(metacard));
} else {
optionsMap = Collections.singletonMap(ResourceRequest.OPTION_ARGUMENT,
getOptionsFromFederatedSource(metacard, sourceId));
}
} else {
String message = "Could not find metacard " + metacardId + " on source " + sourceId;
throw new ResourceNotFoundException(message);
}
} catch (UnsupportedQueryException e) {
LOGGER.debug("Error finding metacard {}", metacardId, e);
throw new ResourceNotFoundException("Error finding metacard due to Unsuppported Query",
e);
} catch (FederationException e) {
LOGGER.debug("Error federating query for metacard {}", metacardId, e);
throw new ResourceNotFoundException("Error finding metacard due to Federation issue",
e);
} catch (IllegalArgumentException e) {
LOGGER.debug("Metacard couldn't be found {}", metacardId, e);
throw new ResourceNotFoundException("Query returned null metacard", e);
} finally {
LOGGER.trace("EXITING: getResourceOptions");
}
return optionsMap;
}
//
//
//
@SuppressWarnings("javadoc")
ResourceResponse getResource(ResourceRequest resourceRequest, boolean isEnterprise,
String resourceSiteName, boolean fanoutEnabled)
throws IOException, ResourceNotFoundException, ResourceNotSupportedException {
ResourceResponse resourceResponse = null;
ResourceRequest resourceReq = resourceRequest;
String resourceSourceName = resourceSiteName;
ResourceRetriever retriever = null;
if (fanoutEnabled) {
isEnterprise = true;
}
if (resourceSourceName == null && !isEnterprise) {
throw new ResourceNotFoundException(
"resourceSiteName cannot be null when obtaining resource.");
}
validateGetResourceRequest(resourceReq);
try {
resourceReq = preProcessPreAuthorizationPlugins(resourceReq);
resourceReq = processPreResourcePolicyPlugins(resourceReq);
resourceReq = processPreResourceAccessPlugins(resourceReq);
resourceReq = processPreResourcePlugins(resourceReq);
Map<String, Serializable> requestProperties = resourceReq.getProperties();
LOGGER.debug("Attempting to get resource from siteName: {}", resourceSourceName);
// At this point we pull out the properties and use them.
Serializable sourceIdProperty = requestProperties.get(ResourceRequest.SOURCE_ID);
if (sourceIdProperty != null) {
resourceSourceName = sourceIdProperty.toString();
}
Serializable enterpriseProperty = requestProperties.get(ResourceRequest.IS_ENTERPRISE);
if (enterpriseProperty != null) {
if (Boolean.parseBoolean(enterpriseProperty.toString())) {
isEnterprise = true;
}
}
// check if the resourceRequest has an ID only
// If so, the metacard needs to be found and the Resource URI
StringBuilder resolvedSourceIdHolder = new StringBuilder();
ResourceInfo resourceInfo = getResourceInfo(resourceReq,
resourceSourceName,
isEnterprise,
resolvedSourceIdHolder,
requestProperties,
fanoutEnabled);
if (resourceInfo == null) {
throw new ResourceNotFoundException(
"Resource could not be found for the given attribute value: "
+ resourceReq.getAttributeValue());
}
URI responseURI = resourceInfo.getResourceUri();
Metacard metacard = resourceInfo.getMetacard();
String resolvedSourceId = resolvedSourceIdHolder.toString();
LOGGER.debug("resolvedSourceId = {}", resolvedSourceId);
LOGGER.debug("ID = {}", getId());
if (isEnterprise) {
// since resolvedSourceId specifies what source the product
// metacard resides on, we can just
// change resourceSiteName to be that value, and then the
// following if-else statements will
// handle retrieving the product on the correct source
resourceSourceName = resolvedSourceId;
}
// retrieve product from specified federated site if not in cache
if (!resourceSourceName.equals(getId())) {
LOGGER.debug("Searching federatedSource {} for resource.", resourceSourceName);
LOGGER.debug("metacard for product found on source: {}", resolvedSourceId);
FederatedSource source = frameworkProperties.getFederatedSources()
.get(resourceSourceName);
if (source != null) {
LOGGER.debug("Adding federated site to federated query: {}", source.getId());
LOGGER.debug("Retrieving product from remote source {}", source.getId());
retriever = new RemoteResourceRetriever(source, responseURI, requestProperties);
} else {
LOGGER.debug("Could not find federatedSource: {}", resourceSourceName);
}
} else {
LOGGER.debug("Retrieving product from local source {}", resourceSourceName);
retriever = new LocalResourceRetriever(frameworkProperties.getResourceReaders(),
responseURI,
requestProperties);
}
try {
resourceResponse = frameworkProperties.getReliableResourceDownloadManager()
.download(resourceRequest, metacard, retriever);
} catch (DownloadException e) {
LOGGER.info("Unable to download resource", e);
}
resourceResponse = putPropertiesInResponse(resourceRequest, resourceResponse);
resourceResponse = validateFixGetResourceResponse(resourceResponse, resourceReq);
resourceResponse = postProcessPreAuthorizationPlugins(resourceResponse, metacard);
resourceResponse = processPostResourcePolicyPlugins(resourceResponse, metacard);
resourceResponse = processPostResourceAccessPlugins(resourceResponse, metacard);
resourceResponse = processPostResourcePlugins(resourceResponse);
resourceResponse.getProperties()
.put(Constants.METACARD_PROPERTY, metacard);
} catch (DataUsageLimitExceededException e) {
LOGGER.info("RuntimeException caused by: ", e);
throw e;
} catch (RuntimeException e) {
LOGGER.info("RuntimeException caused by: ", e);
throw new ResourceNotFoundException("Unable to find resource");
} catch (StopProcessingException e) {
LOGGER.info("Resource not supported", e);
throw new ResourceNotSupportedException(FAILED_BY_GET_RESOURCE_PLUGIN + e.getMessage());
}
return resourceResponse;
}
private ResourceResponse putPropertiesInResponse(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) {
if (resourceResponse != null) {
// must add the request properties into response properties in case the source forgot to
Map<String, Serializable> properties = new HashMap<>(resourceResponse.getProperties());
resourceRequest.getProperties()
.forEach(properties::putIfAbsent);
resourceResponse = new ResourceResponseImpl(resourceResponse.getRequest(),
properties,
resourceResponse.getResource());
}
return resourceResponse;
}
private ResourceResponse processPostResourcePlugins(ResourceResponse resourceResponse)
throws StopProcessingException {
for (PostResourcePlugin plugin : frameworkProperties.getPostResource()) {
try {
resourceResponse = plugin.process(resourceResponse);
} catch (PluginExecutionException e) {
LOGGER.debug("Plugin processing failed. This is allowable. Skipping to next plugin.",
e);
}
}
return resourceResponse;
}
private ResourceResponse processPostResourceAccessPlugins(ResourceResponse resourceResponse,
Metacard metacard) throws StopProcessingException {
for (AccessPlugin plugin : frameworkProperties.getAccessPlugins()) {
resourceResponse = plugin.processPostResource(resourceResponse, metacard);
}
return resourceResponse;
}
private ResourceResponse processPostResourcePolicyPlugins(ResourceResponse resourceResponse,
Metacard metacard) throws StopProcessingException {
HashMap<String, Set<String>> responsePolicyMap = new HashMap<>();
for (PolicyPlugin plugin : frameworkProperties.getPolicyPlugins()) {
PolicyResponse policyResponse = plugin.processPostResource(resourceResponse, metacard);
opsSecuritySupport.buildPolicyMap(responsePolicyMap,
policyResponse.operationPolicy()
.entrySet());
}
resourceResponse.getProperties()
.put(PolicyPlugin.OPERATION_SECURITY, responsePolicyMap);
return resourceResponse;
}
private ResourceRequest processPreResourcePlugins(ResourceRequest resourceReq)
throws StopProcessingException {
for (PreResourcePlugin plugin : frameworkProperties.getPreResource()) {
try {
ResourceRequest processed = plugin.process(resourceReq);
if (processed != null) {
resourceReq = processed;
}
} catch (PluginExecutionException e) {
LOGGER.debug("Plugin processing failed. This is allowable. Skipping to next plugin.",
e);
}
}
return resourceReq;
}
private ResourceRequest processPreResourceAccessPlugins(ResourceRequest resourceReq)
throws StopProcessingException {
for (AccessPlugin plugin : frameworkProperties.getAccessPlugins()) {
resourceReq = plugin.processPreResource(resourceReq);
}
return resourceReq;
}
private ResourceRequest processPreResourcePolicyPlugins(ResourceRequest resourceReq)
throws StopProcessingException {
HashMap<String, Set<String>> requestPolicyMap = new HashMap<>();
for (PolicyPlugin plugin : frameworkProperties.getPolicyPlugins()) {
PolicyResponse policyResponse = plugin.processPreResource(resourceReq);
opsSecuritySupport.buildPolicyMap(requestPolicyMap,
policyResponse.operationPolicy()
.entrySet());
}
resourceReq.getProperties()
.put(PolicyPlugin.OPERATION_SECURITY, requestPolicyMap);
return resourceReq;
}
private ResourceRequest preProcessPreAuthorizationPlugins(ResourceRequest resourceRequest)
throws StopProcessingException {
for (PreAuthorizationPlugin plugin : frameworkProperties.getPreAuthorizationPlugins()) {
resourceRequest = plugin.processPreResource(resourceRequest);
}
return resourceRequest;
}
private ResourceResponse postProcessPreAuthorizationPlugins(ResourceResponse resourceResponse,
Metacard metacard) throws StopProcessingException {
for (PreAuthorizationPlugin plugin : frameworkProperties.getPreAuthorizationPlugins()) {
resourceResponse = plugin.processPostResource(resourceResponse, metacard);
}
return resourceResponse;
}
/**
* Retrieves a resource by URI.
* <p/>
* The {@link ResourceRequest} can specify either the product's URI or ID. If the product ID is
* specified, then the matching {@link Metacard} must first be retrieved and the product URI
* extracted from this {@link Metacard}.
*
* @param resourceRequest
* @param site
* @param isEnterprise
* @param federatedSite
* @param requestProperties
* @param fanoutEnabled
* @return
* @throws ResourceNotSupportedException
* @throws ResourceNotFoundException
*/
protected ResourceInfo getResourceInfo(ResourceRequest resourceRequest, String site,
boolean isEnterprise, StringBuilder federatedSite,
Map<String, Serializable> requestProperties, boolean fanoutEnabled)
throws ResourceNotSupportedException, ResourceNotFoundException {
Metacard metacard;
URI resourceUri;
String name = resourceRequest.getAttributeName();
try {
if (ResourceRequest.GET_RESOURCE_BY_PRODUCT_URI.equals(name)) {
// because this is a get resource by product uri, we already
// have the product uri to return
LOGGER.debug("get resource by product uri");
Object value = resourceRequest.getAttributeValue();
if (value instanceof URI) {
resourceUri = (URI) value;
if (StringUtils.isNotBlank(resourceUri.getFragment())) {
resourceRequest.getProperties()
.put(ContentItem.QUALIFIER, resourceUri.getFragment());
try {
resourceUri = new URI(resourceUri.getScheme(),
resourceUri.getSchemeSpecificPart(),
null);
} catch (URISyntaxException e) {
throw new ResourceNotFoundException(
"Could not resolve URI by doing a URI based query: " + value);
}
}
Query propertyEqualToUriQuery =
createPropertyIsEqualToQuery(Metacard.RESOURCE_URI,
resourceUri.toString());
// if isEnterprise, go out and obtain the actual source
// where the product's metacard is stored.
QueryRequest queryRequest = new QueryRequestImpl(anyTag(propertyEqualToUriQuery,
site,
isEnterprise),
isEnterprise,
Collections.singletonList(site == null ? this.getId() : site),
resourceRequest.getProperties());
QueryResponse queryResponse = queryOperations.query(queryRequest,
null,
true,
fanoutEnabled);
if (!queryResponse.getResults()
.isEmpty()) {
metacard = queryResponse.getResults()
.get(0)
.getMetacard();
federatedSite.append(metacard.getSourceId());
LOGGER.debug("Trying to lookup resource URI {} for metacardId: {}",
resourceUri,
resourceUri);
if (!requestProperties.containsKey(Metacard.ID)) {
requestProperties.put(Metacard.ID, metacard.getId());
}
if (!requestProperties.containsKey(Metacard.RESOURCE_URI)) {
requestProperties.put(Metacard.RESOURCE_URI, metacard.getResourceURI());
}
} else {
throw new ResourceNotFoundException(
"Could not resolve source id for URI by doing a URI based query: "
+ resourceUri);
}
} else {
throw new ResourceNotSupportedException(
"The GetResourceRequest with attribute value of class '"
+ value.getClass()
+ "' is not supported by this instance of the CatalogFramework.");
}
} else if (ResourceRequest.GET_RESOURCE_BY_ID.equals(name)) {
// since this is a get resource by id, we need to obtain the
// product URI
LOGGER.debug("get resource by id");
Object value = resourceRequest.getAttributeValue();
if (value instanceof String) {
String metacardId = (String) value;
LOGGER.debug("metacardId = {}, site = {}", metacardId, site);
QueryRequest queryRequest = new QueryRequestImpl(anyTag(createMetacardIdQuery(
metacardId), site, isEnterprise),
isEnterprise,
Collections.singletonList(site == null ? this.getId() : site),
resourceRequest.getProperties());
QueryResponse queryResponse = queryOperations.query(queryRequest,
null,
true,
fanoutEnabled);
if (!queryResponse.getResults()
.isEmpty()) {
metacard = queryResponse.getResults()
.get(0)
.getMetacard();
resourceUri = metacard.getResourceURI();
federatedSite.append(metacard.getSourceId());
LOGGER.debug("Trying to lookup resource URI {} for metacardId: {}",
resourceUri,
metacardId);
} else {
throw new ResourceNotFoundException(
"Could not resolve source id for URI by doing an id based query: "
+ metacardId);
}
if (!requestProperties.containsKey(Metacard.ID)) {
requestProperties.put(Metacard.ID, metacardId);
}
if (!requestProperties.containsKey(Metacard.RESOURCE_URI)) {
requestProperties.put(Metacard.RESOURCE_URI, resourceUri);
}
} else {
throw new ResourceNotSupportedException(
"The GetResourceRequest with attribute value of class '"
+ value.getClass()
+ "' is not supported by this instance of the CatalogFramework.");
}
} else {
throw new ResourceNotSupportedException(
"The GetResourceRequest with attribute name '" + name
+ "' is not supported by this instance of the CatalogFramework.");
}
} catch (UnsupportedQueryException | FederationException e) {
throw new ResourceNotFoundException(DEFAULT_RESOURCE_NOT_FOUND_MESSAGE, e);
}
LOGGER.debug("Returning resourceURI: {}", resourceUri);
if (resourceUri == null) {
throw new ResourceNotFoundException(DEFAULT_RESOURCE_NOT_FOUND_MESSAGE);
}
return new ResourceInfo(metacard, resourceUri);
}
private Query anyTag(Query query, String site, boolean isEnterprise) {
if (isEnterprise || !getId().equals(site)) {
return query;
}
Filter anyTag = frameworkProperties.getFilterBuilder()
.attribute(Metacard.TAGS)
.is()
.like()
.text(FilterDelegate.WILDCARD_CHAR);
Filter filter = frameworkProperties.getFilterBuilder()
.allOf(anyTag, query);
return new QueryImpl(filter,
query.getStartIndex(),
query.getPageSize(),
query.getSortBy(),
query.requestsTotalResultsCount(),
query.getTimeoutMillis());
}
protected static class ResourceInfo {
private final Metacard metacard;
private final URI resourceUri;
public ResourceInfo(Metacard metacard, URI uri) {
this.metacard = metacard;
this.resourceUri = uri;
}
public Metacard getMetacard() {
return metacard;
}
public URI getResourceUri() {
return resourceUri;
}
}
/**
* Get the supported options from the {@link ResourceReader} that matches the scheme in the
* specified {@link Metacard}'s URI. Only look in the local provider for the specified
* {@link Metacard}.
*
* @param metacard the {@link Metacard} to get the supported options for
* @return the {@link Set} of supported options for the metacard
*/
@Deprecated
private Set<String> getOptionsFromLocalProvider(Metacard metacard) {
LOGGER.trace("ENTERING: getOptionsFromLocalProvider");
Set<String> supportedOptions = Collections.emptySet();
URI resourceUri = metacard.getResourceURI();
for (ResourceReader reader : frameworkProperties.getResourceReaders()) {
LOGGER.debug("reader id: {}", reader.getId());
Set<String> rrSupportedSchemes = reader.getSupportedSchemes();
String metacardScheme = resourceUri.getScheme();
if (metacardScheme != null && rrSupportedSchemes.contains(metacardScheme)) {
supportedOptions = reader.getOptions(metacard);
}
}
LOGGER.trace("EXITING: getOptionsFromLocalProvider");
return supportedOptions;
}
/**
* Get the supported options from the {@link ResourceReader} that matches the scheme in the
* specified {@link Metacard}'s URI. Only look in the specified source for the {@link Metacard}.
*
* @param metacard the {@link Metacard} to get the supported options for
* @param sourceId the ID of the federated source to look for the {@link Metacard}
* @return the {@link Set} of supported options for the metacard
* @throws ResourceNotFoundException if the {@link ddf.catalog.source.Source} cannot be found for the source ID
*/
@Deprecated
private Set<String> getOptionsFromFederatedSource(Metacard metacard, String sourceId)
throws ResourceNotFoundException {
LOGGER.trace("ENTERING: getOptionsFromFederatedSource");
FederatedSource source = frameworkProperties.getFederatedSources()
.get(sourceId);
if (source != null) {
LOGGER.trace("EXITING: getOptionsFromFederatedSource");
return source.getOptions(metacard);
} else {
String message = "Unable to find source corresponding to given site name: " + sourceId;
LOGGER.trace("EXITING: getOptionsFromFederatedSource");
throw new ResourceNotFoundException(message);
}
}
protected Query createMetacardIdQuery(String metacardId) {
return createPropertyIsEqualToQuery(Metacard.ID, metacardId);
}
protected Query createPropertyIsEqualToQuery(String propertyName, String literal) {
return new QueryImpl(new PropertyIsEqualToLiteral(new PropertyNameImpl(propertyName),
new LiteralImpl(literal)));
}
/**
* Validates that the {@link ResourceResponse} has a {@link ddf.catalog.resource.Resource} in it that was retrieved,
* and that the original {@link ResourceRequest} is included in the response.
*
* @param getResourceResponse the original {@link ResourceResponse} returned from the source
* @param getResourceRequest the original {@link ResourceRequest} sent to the source
* @return the updated {@link ResourceResponse}
* @throws ResourceNotFoundException if the original {@link ResourceResponse} is null or the resource could not be
* found
*/
protected ResourceResponse validateFixGetResourceResponse(ResourceResponse getResourceResponse,
ResourceRequest getResourceRequest) throws ResourceNotFoundException {
ResourceResponse resourceResponse = getResourceResponse;
if (getResourceResponse != null) {
if (getResourceResponse.getResource() == null) {
throw new ResourceNotFoundException(
"Resource was returned as null, meaning it could not be found.");
}
if (getResourceResponse.getRequest() == null) {
resourceResponse = new ResourceResponseImpl(getResourceRequest,
getResourceResponse.getProperties(),
getResourceResponse.getResource());
}
} else {
throw new ResourceNotFoundException(
"CatalogProvider returned null ResourceResponse Object.");
}
return resourceResponse;
}
/**
* Validates that the {@link ResourceRequest} is non-null, a non-null attribute name (which
* specifies if the retrieval is being done by product URI or ID), and a non-null attribute
* value.
*
* @param getResourceRequest the {@link ResourceRequest}
* @throws ResourceNotSupportedException if the {@link ResourceRequest} is null, or has a null attribute value or name
*/
protected void validateGetResourceRequest(ResourceRequest getResourceRequest)
throws ResourceNotSupportedException {
if (getResourceRequest == null) {
throw new ResourceNotSupportedException(
"GetResourceRequest was null, either passed in from endpoint, or as output from PreResourcePlugin");
}
Serializable value = getResourceRequest.getAttributeValue();
if (value == null || getResourceRequest.getAttributeName() == null) {
throw new ResourceNotSupportedException(
"Cannot perform getResource with null attribute value or null attributeName, either passed in from endpoint, or as output from PreResourcePlugin");
}
}
}