Java tutorial
/** * Copyright (C) 2014 Cohesive Integrations, LLC (info@cohesiveintegrations.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.di2e.ecdr.source.rest; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import net.di2e.ecdr.api.cache.Cache; import net.di2e.ecdr.api.cache.CacheManager; import net.di2e.ecdr.commons.constants.SearchConstants; import net.di2e.ecdr.commons.filter.AbstractFilterDelegate.SupportedGeosOptions; import net.di2e.ecdr.commons.filter.config.AtomSearchResponseTransformerConfig; import net.di2e.ecdr.commons.filter.config.AtomSearchResponseTransformerConfig.AtomContentXmlWrapOption; import net.di2e.ecdr.commons.util.SearchUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.transport.http.HTTPConduit; import org.opengis.filter.sort.SortBy; import org.opengis.filter.sort.SortOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.catalog.data.Metacard; import ddf.catalog.data.Result; import ddf.catalog.util.impl.MaskableImpl; public abstract class CDRSourceConfiguration extends MaskableImpl { private static final Logger LOGGER = LoggerFactory.getLogger(CDRSourceConfiguration.class); public enum PingMethod { GET, HEAD, NONE } // matches 'user-friendly' OS terms with value used produced by the filter delegate private static Map<String, String> parameterMatchMap = new HashMap<>(); static { parameterMatchMap.put("os:searchTerms", SearchConstants.KEYWORD_PARAMETER); parameterMatchMap.put("os:count", SearchConstants.COUNT_PARAMETER); parameterMatchMap.put("os:startIndex", SearchConstants.STARTINDEX_PARAMETER); parameterMatchMap.put("cdrs:timeout", SearchConstants.TIMEOUT_PARAMETER); parameterMatchMap.put("cdrsx:originQueryID", SearchConstants.OID_PARAMETER); parameterMatchMap.put("ddf:resource-uri", SearchConstants.RESOURCE_URI_PARAMETER); parameterMatchMap.put("cdrb:path", SearchConstants.PATH_PARAMETER); parameterMatchMap.put("cdrsx:strictMode", SearchConstants.STRICTMODE_PARAMETER); parameterMatchMap.put("cdrsx:caseSensitive", SearchConstants.CASESENSITIVE_PARAMETER); parameterMatchMap.put("ecdr:fuzzy", SearchConstants.FUZZY_PARAMETER); parameterMatchMap.put("ecdr:collections", SearchConstants.CONTENT_COLLECTIONS_PARAMETER); parameterMatchMap.put("ddf:metadata-content-type", SearchConstants.CONTENT_TYPE_PARAMETER); parameterMatchMap.put("ecdr:textPath", SearchConstants.TEXTPATH_PARAMETER); parameterMatchMap.put("time:start", SearchConstants.STARTDATE_PARAMETER); parameterMatchMap.put("time:end", SearchConstants.ENDDATE_PARAMETER); parameterMatchMap.put("cdrsx:dateType", SearchConstants.DATETYPE_PARAMETER); parameterMatchMap.put("time:relation", SearchConstants.DATE_RELATION_PARAMETER); parameterMatchMap.put("geo:uid", SearchConstants.UID_PARAMETER); parameterMatchMap.put("geo:box", SearchConstants.BOX_PARAMETER); parameterMatchMap.put("geo:lat", SearchConstants.LATITUDE_PARAMETER); parameterMatchMap.put("geo:lon", SearchConstants.LONGITUDE_PARAMETER); parameterMatchMap.put("geo:radius", SearchConstants.RADIUS_PARAMETER); parameterMatchMap.put("geo:geometry", SearchConstants.GEOMETRY_PARAMETER); parameterMatchMap.put("geo:polygon", SearchConstants.POLYGON_PARAMETER); parameterMatchMap.put("geo:spatialOp", SearchConstants.GEO_RELATION_PARAMETER); parameterMatchMap.put("sru:sortKeys", SearchConstants.SORTKEYS_PARAMETER); } private AtomSearchResponseTransformerConfig atomTransformerConfig = null; private CacheManager<Metacard> cacheManager = null; private Cache<Metacard> metacardCache = null; private String cacheId = null; private long receiveTimeout = 0; private long connectionTimeout = 30000; private long availableCheckCacheTime = 120000; private int maxResultsCount = 0; private boolean disableCNCheck = false; private boolean sendSecurityCookie = false; private PingMethod pingMethod = PingMethod.HEAD; private String responseTransformer = null; private Map<String, String> hardcodedParamMap = null; private Map<String, String> parameterMap = null; private Map<String, String> sortMap = null; private Map<String, String> hardcodedHttpHeaders = null; private Map<String, String> dateTypeMap = null; private Map<String, String> propertyMap = null; private List<String> httpHeaders = null; private SupportedGeosOptions supportedGeoOption = null; public CDRSourceConfiguration(CacheManager<Metacard> manager) { super(); hardcodedParamMap = new HashMap<>(); hardcodedParamMap.put(SearchConstants.FORMAT_PARAMETER, "atom-ddms"); hardcodedParamMap.put(SearchConstants.QUERYLANGUAGE_PARAMETER, SearchConstants.CDR_CQL_QUERY_LANGUAGE); sortMap = new HashMap<>(); sortMap = SearchUtils.convertToMap(Metacard.TITLE + "=title," + Metacard.MODIFIED + "=updated," + Metacard.EFFECTIVE + "=published," + Metacard.CREATED + "=created," + Result.RELEVANCE + "=score," + Result.DISTANCE + "=distance"); parameterMap = new HashMap<>(); parameterMap.putAll(parameterMatchMap); hardcodedHttpHeaders = new HashMap<>(); httpHeaders = new ArrayList<>(); httpHeaders.add("EMID"); dateTypeMap = new HashMap<String, String>(); dateTypeMap.put(Metacard.MODIFIED, "updated"); dateTypeMap.put(Metacard.EFFECTIVE, "published"); dateTypeMap.put(Metacard.CREATED, "created"); propertyMap = new HashMap<String, String>(); propertyMap.put(Metacard.ID, SearchConstants.UID_PARAMETER); cacheManager = manager; atomTransformerConfig = new AtomSearchResponseTransformerConfig(); } protected abstract WebClient getRestClient(); protected abstract void setRestClient(WebClient webClient); protected abstract WebClient getPingClient(); protected abstract void setPingClient(WebClient webClient); public void setId(String sourceId) { LOGGER.debug("ConfigUpdate: Updating the id value from [{}] to [{}]", getId(), sourceId); super.setId(sourceId); } public synchronized void setUrl(String endpointUrl) { if (StringUtils.isNotBlank(endpointUrl)) { WebClient client = getRestClient(); LOGGER.debug("ConfigUpdate: Updating the source endpoint url value from [{}] to [{}] for sourceId [{}]", client == null ? null : client.getCurrentURI(), endpointUrl, getId()); setRestClient(WebClient.create(endpointUrl, true)); HTTPConduit conduit = WebClient.getConfig(getRestClient()).getHttpConduit(); conduit.getClient().setReceiveTimeout(receiveTimeout); conduit.getClient().setConnectionTimeout(connectionTimeout); // conduit.setTlsClientParameters( TLSUtil.getTlsClientParameters( disableCNCheck ) ); TLSUtil.setTLSOptions(getRestClient(), getDisableCNCheck()); } else { LOGGER.warn("OpenSearch Source Endpoint URL is not a valid value, so cannot update it [{}]", endpointUrl); } } public void setReceiveTimeoutSeconds(Integer seconds) { seconds = seconds == null ? 0 : seconds; long millis = seconds * 1000L; if (millis != receiveTimeout) { LOGGER.debug( "ConfigUpdate: Updating the source endpoint receive timeout value from [{}] to [{}] milliseconds", receiveTimeout, millis); receiveTimeout = millis; WebClient.getConfig(getRestClient()).getHttpConduit().getClient().setReceiveTimeout(receiveTimeout); } } public void setConnectionTimeoutSeconds(Integer seconds) { seconds = seconds == null ? 0 : seconds; long millis = seconds * 1000L; if (millis != connectionTimeout) { LOGGER.debug( "ConfigUpdate: Updating the source endpoint connection timeout value from [{}] to [{}] milliseconds", connectionTimeout, millis); connectionTimeout = millis; WebClient.getConfig(getRestClient()).getHttpConduit().getClient() .setConnectionTimeout(connectionTimeout); } } public synchronized void setPingUrl(String url) { if (StringUtils.isNotBlank(url)) { LOGGER.debug( "ConfigUpdate: Updating the ping (site availability check) endpoint url value from [{}] to [{}]", getPingClient() == null ? null : getPingClient().getCurrentURI().toString(), url); setPingClient(WebClient.create(url, true)); HTTPConduit conduit = WebClient.getConfig(getPingClient()).getHttpConduit(); conduit.getClient().setReceiveTimeout(receiveTimeout); conduit.getClient().setConnectionTimeout(connectionTimeout); TLSUtil.setTLSOptions(getPingClient(), getDisableCNCheck()); // conduit.setTlsClientParameters( TLSUtil.getTlsClientParameters( disableCNCheck ) ); } else { LOGGER.debug( "ConfigUpdate: Updating the ping (site availability check) endpoint url to [null], will not be performing ping checks"); } } public void setPingMethodString(String method) { try { LOGGER.debug("ConfigUpdate: Updating the httpPing method value from [{}] to [{}]", pingMethod, method); if (method != null) { pingMethod = PingMethod.valueOf(method); } } catch (IllegalArgumentException e) { LOGGER.warn("Could not update the http ping method due to invalid valus [{}], so leaving at [{}]", method, pingMethod); } } /** * Sets the time (in seconds) that availability should be cached (that is, the minimum amount of time between 2 * perform availability checks). For example if set to 60 seconds, then if an availability check is called 30 * seconds after a previous availability check was called, the second call will just return a cache value and not do * another check. * <p/> * This settings allow admins to ensure that a site is not overloaded with availability checks * * @param newCacheTime * New time period, in seconds, to check the availability of the federated source. */ public void setAvailableCheckCacheTime(long newCacheTime) { if (newCacheTime < 1) { newCacheTime = 1; } LOGGER.debug("ConfigUpdate: Updating the Available Check Cache Time value from [{}] to [{}] seconds", availableCheckCacheTime / 1000, newCacheTime); this.availableCheckCacheTime = newCacheTime * 1000; } public void setResponseTransformer(String transformer) { LOGGER.debug("ConfigUpdate: Updating the ResponseTransformer value from [{}] to [{}]", responseTransformer, transformer); this.responseTransformer = transformer; } public void setWrapContentWithXmlOption(String option) { if (StringUtils.isNotBlank(option)) { LOGGER.debug("ConfigUpdate: Updating the WrapContentWithXmlOption value from [{}] to [{}]", atomTransformerConfig.getAtomContentXmlWrapOption(), option); atomTransformerConfig.setAtomContentXmlWrapOption(AtomContentXmlWrapOption.valueOf(option)); } else { LOGGER.debug( "ConfigUpdateError: Configuration update for wrapContentWithXml option was empty or null so leaving at existing value for [{}]", atomTransformerConfig.getAtomContentXmlWrapOption()); } } public void setThumbnailLinkRelation(String rel) { LOGGER.debug("ConfigUpdate: Updating the Thumbnail Link Relation value from [{}] to [{}]", atomTransformerConfig.getThumbnailLinkRelation(), rel); atomTransformerConfig.setThumbnailLinkRelation(rel); } public void setMetadataLinkRelation(String rel) { LOGGER.debug("ConfigUpdate: Updating the Metadata Link Relation value from [{}] to [{}]", atomTransformerConfig.getMetadataLinkRelation(), rel); atomTransformerConfig.setMetadataLinkRelation(rel); } public void setProductLinkRelation(String rel) { LOGGER.debug("ConfigUpdate: Updating the Product Link Relation value from [{}] to [{}]", atomTransformerConfig.getProductLinkRelation(), rel); atomTransformerConfig.setProductLinkRelation(rel); } public void setProxyProductUrls(boolean proxy) { LOGGER.debug("ConfigUpdate: Updating the Proxy URLs through Local Instance value from [{}] to [{}]", atomTransformerConfig.isProxyProductUrl(), proxy); atomTransformerConfig.setProxyProductUrl(proxy); } public void setStartIndexStartNumber(String startNumber) { if (StringUtils.isNotBlank(startNumber)) { try { // get the existing start index (0 or 1) to use in the log statement after setting the index String oldIndex = atomTransformerConfig.isZeroBasedStartIndex() ? "0" : "1"; atomTransformerConfig.setZeroBasedStartIndex(Integer.parseInt(startNumber) == 0); LOGGER.debug("ConfigUpdate: Updating the Start Index Numbering value from [{}] to [{}]", oldIndex, startNumber); } catch (NumberFormatException e) { LOGGER.warn( "ConfigUpdate Failed: Attempted to update the 'start index number method' due to non valid (must be 1 or 0) start index numbering passed in[" + startNumber + "]"); } } else { LOGGER.debug( "ConfigUpdateError: Configuration update for startNumber was empty or null so leaving at existing value for isZeroBasedStartIndex=[{}]", atomTransformerConfig.isZeroBasedStartIndex()); } } public void setHardCodedParameters(List<String> hardcodedString) { LOGGER.debug("ConfigUpdate: Updating the hard coded parameters to [{}]", hardcodedString); hardcodedParamMap = SearchUtils.convertToMap(hardcodedString); } public void setDateParameterMap(List<String> dates) { LOGGER.debug("ConfigUpdate: Updating the date parameters map for source [{}] to [{}]", getId(), dates); dateTypeMap = SearchUtils.convertToMap(dates); } public void setPropertyParameterMap(List<String> props) { LOGGER.debug("ConfigUpdate: Updating the property parameters map for source [{}] to [{}]", getId(), props); propertyMap = SearchUtils.convertToMap(props); } public void setParameterMap(List<String> parameterMapStr) { Map<String, String> convertedMap = SearchUtils.convertToMap(parameterMapStr); Map<String, String> translateMap = new HashMap<>(convertedMap.size()); for (Entry<String, String> entry : convertedMap.entrySet()) { if (parameterMatchMap.containsKey(entry.getKey())) { translateMap.put(parameterMatchMap.get(entry.getKey()), entry.getValue()); } else { translateMap.put(entry.getKey(), entry.getValue()); } } LOGGER.debug("ConfigUpdate: Updating parameterMap with new entries: {}", convertedMap.toString()); parameterMap = translateMap; } public void setHttpHeaders(List<String> headers) { hardcodedHttpHeaders.clear(); httpHeaders.clear(); if (CollectionUtils.isNotEmpty(headers)) { for (String header : headers) { if (header.contains("=")) { hardcodedHttpHeaders.putAll(SearchUtils.convertToMap(header)); } else { httpHeaders.add(header); } } } } public void setCacheExpirationMinutes(Long minutes) { if (minutes == null || minutes == 0) { LOGGER.debug( "ConfigUpdate: Clearing any existing cached Metacards, and no longer using the Cache for id lookups for source [{}]", getId()); if (metacardCache != null) { metacardCache.destroy(); } } else { if (metacardCache != null) { metacardCache.destroy(); cacheManager.removeCacheInstance(cacheId); } cacheId = getId() + "-" + UUID.randomUUID(); LOGGER.debug( "ConfigUpdate: Creating a cache with id [{}] for Metacard id lookups for source [{}] with an cache expiration time of [{}] minutes", cacheId, getId(), minutes); Map<String, Object> cacheProps = new HashMap<String, Object>(); cacheProps.put(CacheManager.CACHE_EXPIRE_AFTER_MINUTES, minutes); metacardCache = cacheManager.createCacheInstance(cacheId, cacheProps); } } public void setSortMap(List<String> sortMapStr) { Map<String, String> convertedMap = SearchUtils.convertToMap(sortMapStr); LOGGER.debug("ConfigUpdate: Updating sortMap with new entries: {}", convertedMap); sortMap = convertedMap; } public void setDisableCNCheck(boolean disableCheck) { if (disableCNCheck != disableCheck) { LOGGER.debug( "ConfigUpdate: Updating the Disable CN Check (for certificates) boolean value from [{}] to [{}]", disableCNCheck, disableCheck); disableCNCheck = disableCheck; WebClient client = getPingClient(); if (client != null) { URI pingUri = client.getCurrentURI(); if (pingUri != null) { setPingUrl(pingUri.toString()); } } client = getRestClient(); if (client != null) { URI pingUri = client.getCurrentURI(); if (pingUri != null) { setUrl(pingUri.toString()); } } } } public boolean getDisableCNCheck() { return disableCNCheck; } public void setSendSecurityCookie(boolean sendCookie) { LOGGER.debug("ConfigUpdate: Updating the Send Security Cookie boolean value from [{}] to [{}]", sendSecurityCookie, sendCookie); this.sendSecurityCookie = sendCookie; } public void setMaxResultCount(Integer count) { count = count == null ? 0 : count; LOGGER.debug("ConfigUpdate: Updating the max results count value from [{}] to [{}]", maxResultsCount, count); maxResultsCount = count; } protected Cache<Metacard> getMetacardCache() { return metacardCache; } protected Map<String, String> getParameterMap() { return parameterMap; } protected Map<String, String> getPropertyMap() { return propertyMap; } protected Map<String, String> getDateTypeMap() { return dateTypeMap; } protected Map<String, String> getHardcodedQueryParameters() { return hardcodedParamMap; } protected Map<String, String> getHardcodedHttpHeaders() { return hardcodedHttpHeaders; } protected List<String> getHttpHeaderList() { return httpHeaders; } protected AtomSearchResponseTransformerConfig getAtomResponseTransformerConfig() { return atomTransformerConfig; } protected PingMethod getPingMethod() { return pingMethod; } protected long getAvailableCheckCacheTime() { return availableCheckCacheTime; } protected String getResponseTransformerName() { return responseTransformer; } protected boolean isSendSecurityCookie() { return sendSecurityCookie; } protected long getMaxResultsCount() { return maxResultsCount; } public void setSupportedGeoOption(String option) { LOGGER.debug("ConfigUpdate: Updating the supported geo option value from [{}] to [{}]", supportedGeoOption, option); supportedGeoOption = SupportedGeosOptions.valueOf(option); } protected SupportedGeosOptions getSupportedGeoOption() { return supportedGeoOption; } protected String getSortOrderString(SortBy sortBy) { String sortOrderString = null; if (sortBy != null) { SortOrder sortOrder = sortBy.getSortOrder(); String sortProperty = sortBy.getPropertyName().getPropertyName(); LOGGER.trace("Translating sort order from original form order=[{}] and propertyName=[{}] to CDR form", sortOrder, sortProperty); String sortField = sortMap.get(sortProperty); if (sortField != null) { sortOrderString = sortField + (SortOrder.DESCENDING.equals(sortOrder) ? ",,false" : ",,true"); } } return sortOrderString; } public void cleanUp() { LOGGER.debug("Shutting down CDR Federated Source with id [{}]", getId()); if (metacardCache != null) { metacardCache.destroy(); } } }