/**
* 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.resourcemanagement.query.plugin;
import java.util.Date;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.geotools.filter.text.ecql.ECQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.operation.QueryRequest;
import ddf.catalog.source.Source;
import ddf.security.SecurityConstants;
import ddf.security.Subject;
import ddf.security.SubjectUtils;
/**
* {@link ActiveSearch} provides relevant data pertaining to a search that is currently active (a search
* that has not yet completed). Includes the client information {@link String}, CQL query {@link String},
* start time of the search {@link java.util.Date}, source being searched {@link ddf.catalog.source.Source},
* and uniqueID {@link java.util.UUID}
*/
public class ActiveSearch {
private static final Logger LOGGER = LoggerFactory.getLogger(ActiveSearch.class);
private String cqlQuery = "";
private Date startTime;
private Source source;
private UUID uniqueID = null;
private String clientInfo = "";
public static final int USER_PAD_LENGTH = 20;
public static final int SOURCE_PAD_LENGTH = 40;
public static final int SEARCH_PAD_LENGTH = 33;
public static final int TIME_PAD_LENGTH = 30;
public static final int UUID_PAD_LENGTH = 37;
public static final int USER_MAX_LENGTH = 20;
public static final int SOURCE_MAX_LENGTH = 40;
public static final int SEARCH_MAX_LENGTH = 33;
public static final int TIME_MAX_LENGTH = 30;
public static final int UUID_MAX_LENGTH = 37;
public static final String FORMAT_STRING =
"%1$-" + USER_PAD_LENGTH + "." + USER_MAX_LENGTH + "s %2$-" + SOURCE_PAD_LENGTH + "."
+ SOURCE_MAX_LENGTH + "s %3$-" + SEARCH_PAD_LENGTH + "." + SEARCH_MAX_LENGTH
+ "s %4$-" + TIME_PAD_LENGTH + "." + TIME_MAX_LENGTH + "s %5$-"
+ UUID_PAD_LENGTH + "." + UUID_MAX_LENGTH + "s %n";
public String getCQL() {
return cqlQuery;
}
/**
* Returns a {@link Date} representing the approximate time this search started.
*
* @return {@link Date} representing the approximate time the search started.
*/
public Date getStartTime() {
return (Date) startTime.clone();
}
/**
* Returns the source information for this {@link ActiveSearch}
*
* @return {@link Source} representing the source being queried by this {@link ActiveSearch}.
* Can return {@code null} when the object was created using a null source parameter to the constructor.
*/
public Source getSource() {
return source;
}
/**
* Returns the {@link UUID} for this {@link ActiveSearch}
*
* @return {@link UUID} representing the unique identifier for this {@link ActiveSearch}.
*/
public UUID getUniqueID() {
return uniqueID;
}
/**
* Returns the client information for this {@link ActiveSearch}
*
* @return {@link String} representing the client info that queried the {@link Source}.
*/
public String getClientInfo() {
return clientInfo;
}
/**
* Constructor for an {@link ActiveSearch}.
*
* @param cqlQuery {@link String} that represents the query.
* @param source {@link Source} that the search is querying.
* @param uniqueID {@link UUID} a unique ID that is used to uniquely identify the search.
*/
public ActiveSearch(String cqlQuery, Source source, UUID uniqueID, String clientInfo) {
if (cqlQuery == null) {
cqlQuery = "unknownCQLQuery";
LOGGER.debug("CQLQuery for new ActiveSearch is null. Being set as 'unknownCQLQuery'.");
}
this.cqlQuery = cqlQuery;
if (source == null) {
LOGGER.debug("Source for new ActiveSearch is null.");
}
this.source = source;
startTime = new Date();
if (uniqueID == null) {
this.uniqueID = java.util.UUID.randomUUID();
LOGGER.debug("uniqueID for new ActiveSearch is null. Setting the ID as {}", uniqueID);
} else {
this.uniqueID = uniqueID;
}
if (clientInfo == null) {
this.clientInfo = "unknownClient";
} else {
this.clientInfo = clientInfo;
}
}
private static String getCqlFromQueryRequest(QueryRequest request) {
String cqlQuery;
if (request == null) {
return "";
} else {
cqlQuery = ECQL.toCQL(request.getQuery());
}
return cqlQuery;
}
public String toFormattedString() {
if (source == null) {
return String.format(FORMAT_STRING,
clientInfo,
"Unknown Source",
cqlQuery,
startTime.toString(),
uniqueID.toString());
} else {
return String.format(FORMAT_STRING,
clientInfo,
source.getId(),
cqlQuery,
startTime.toString(),
uniqueID.toString());
}
}
public ActiveSearch(Source source, QueryRequest request) {
this(getCqlFromQueryRequest(request), source, UUID.randomUUID(), "client");
if (request == null) {
LOGGER.debug("QueryRequest in ActiveSearch Constructor was null.");
} else {
clientInfo =
SubjectUtils.getName((Subject) request.getPropertyValue(SecurityConstants.SECURITY_SUBJECT),
"unknown",
true);
if (clientInfo.contains(",CN=")) {
clientInfo = StringUtils.substringBetween(clientInfo, ",CN=", ",OU=");
}
}
}
}