package org.ovirt.engine.core.bll;
import java.util.ArrayList;
import java.util.List;
import org.ovirt.engine.core.bll.adbroker.AdActionType;
import org.ovirt.engine.core.bll.adbroker.LdapBrokerUtils;
import org.ovirt.engine.core.bll.adbroker.LdapFactory;
import org.ovirt.engine.core.bll.adbroker.LdapQueryData;
import org.ovirt.engine.core.bll.adbroker.LdapQueryDataImpl;
import org.ovirt.engine.core.bll.adbroker.LdapQueryType;
import org.ovirt.engine.core.bll.adbroker.LdapSearchByQueryParameters;
import org.ovirt.engine.core.common.businessentities.AdUser;
import org.ovirt.engine.core.common.businessentities.AuditLog;
import org.ovirt.engine.core.common.businessentities.DbUser;
import org.ovirt.engine.core.common.businessentities.IVdcQueryable;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSGroup;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.businessentities.ad_groups;
import org.ovirt.engine.core.common.businessentities.storage_domains;
import org.ovirt.engine.core.common.businessentities.storage_pool;
import org.ovirt.engine.core.common.businessentities.vm_pools;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.errors.SearchEngineIllegalCharacterException;
import org.ovirt.engine.core.common.errors.SqlInjectionException;
import org.ovirt.engine.core.common.queries.SearchParameters;
import org.ovirt.engine.core.common.queries.SearchReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.compat.DateTime;
import org.ovirt.engine.core.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.compat.TimeSpan;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.searchbackend.ISyntaxChecker;
import org.ovirt.engine.core.searchbackend.SearchObjects;
import org.ovirt.engine.core.searchbackend.SyntaxCheckerFactory;
import org.ovirt.engine.core.searchbackend.SyntaxContainer;
import org.ovirt.engine.core.searchbackend.SyntaxError;
public class SearchQuery<P extends SearchParameters> extends QueriesCommandBase<P> {
private static java.util.HashMap<String, QueryData2> mQueriesCache = new java.util.HashMap<String, QueryData2>();
private static ISyntaxChecker _defaultSyntaxChecker;
static {
// Dictionary<string, string> dictionary =
// LicenseManager.LicenseManager.Instance.GetLicenseProperties();
// if (dictionary.ContainsKey("ProductTypeProperty") &&
// dictionary["ProductTypeProperty"].Contains("Desktop"))
// {
_defaultSyntaxChecker = SyntaxCheckerFactory.CreateBackendSyntaxChecker(Config
.<String> GetValue(ConfigValues.AuthenticationMethod));
// }
// else
// {
// _defaultSyntaxChecker =
// SyntaxCheckerFactory.CreateBackendSyntaxCheckerServersOnly();
// }
}
public SearchQuery(P parameters) {
super(parameters);
}
private SearchReturnValue getSearchReturnValue() {
VdcQueryReturnValue tempVar = getQueryReturnValue();
return (SearchReturnValue) ((tempVar instanceof SearchReturnValue) ? tempVar : null);
}
@Override
protected void ProceedOnFail() {
getSearchReturnValue().setIsSearchValid(false);
}
@Override
protected void executeQueryCommand() {
List<? extends IVdcQueryable> returnValue = new ArrayList<IVdcQueryable>();
switch (getParameters().getSearchTypeValue()) {
case VM: {
returnValue = searchVmsFromDb();
break;
}
case AdGroup: {
returnValue = searchAdGroups();
break;
}
case AdUser: {
returnValue = searchAdUsers();
break;
}
case AuditLog: {
returnValue = searchAuditLogEvents();
break;
}
case DBUser: {
returnValue = searchDbUsers();
break;
}
case VDS: {
returnValue = searchVDSsByDb();
break;
}
case VmTemplate: {
returnValue = searchVMTemplates();
break;
}
case VmPools: {
returnValue = searchVmPools();
break;
}
case Cluster: {
returnValue = searchClusters();
break;
}
case StoragePool: {
returnValue = searchStoragePool();
break;
}
case StorageDomain: {
returnValue = searchStorageDomain();
break;
}
default: {
break;
}
}
getSearchReturnValue().setReturnValue(returnValue);
}
protected List<VM> searchVmsFromDb() {
List<VM> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<VM>();
getQueryReturnValue().setExceptionString(getSearchReturnValue().getExceptionString());
} else {
returnValue = DbFacade.getInstance().getVmDAO().getAllUsingQuery(data.getQuery());
for (VM vm : returnValue) {
// VmHandler.updateDisksFromDb(vm);
// vm.Interfaces =
// DbFacade.Instance.getIterfacesByVmId(vm.vm_guid);
VmHandler.UpdateVmGuestAgentVersion(vm);
}
}
return returnValue;
}
protected List<VDS> searchVDSsByDb() {
List<VDS> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<VDS>();
} else {
returnValue = DbFacade.getInstance().getVdsDAO().getAllWithQuery(data.getQuery());
for (VDS vds : returnValue) {
vds.setCpuName(CpuFlagsManagerHandler.FindMaxServerCpuByFlags(vds.getcpu_flags(),
vds.getvds_group_compatibility_version()));
}
}
return returnValue;
}
protected java.util.ArrayList<AdUser> searchAdUsers() {
QueryData2 data = InitQueryData(true);
if (data == null) {
return new java.util.ArrayList<AdUser>();
} else {
LdapQueryData ldapQueryData = new LdapQueryDataImpl();
ldapQueryData.setLdapQueryType(LdapQueryType.searchUsers);
ldapQueryData.setFilterParameters(new Object[] { data.getQueryForAdBroker() });
ldapQueryData.setDomain(data.getDomain());
java.util.ArrayList<AdUser> result = (java.util.ArrayList<AdUser>) LdapFactory
.getInstance(data.getDomain())
.RunAdAction(AdActionType.SearchUserByQuery,
new LdapSearchByQueryParameters(data.getDomain(), ldapQueryData))
.getReturnValue();
return (result != null) ? result : new java.util.ArrayList<AdUser>();
}
}
protected List<DbUser> searchDbUsers() {
List<DbUser> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<DbUser>();
} else {
returnValue = DbFacade.getInstance().getDbUserDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
protected java.util.ArrayList<ad_groups> searchAdGroups() {
QueryData2 data = InitQueryData(true);
if (data == null) {
return new java.util.ArrayList<ad_groups>();
} else {
LdapQueryData ldapQueryData = new LdapQueryDataImpl();
ldapQueryData.setLdapQueryType(LdapQueryType.searchGroups);
ldapQueryData.setDomain(data.getDomain());
ldapQueryData.setFilterParameters(new Object[] { data.getQueryForAdBroker() });
java.util.ArrayList<ad_groups> result = (java.util.ArrayList<ad_groups>) LdapFactory
.getInstance(data.getDomain())
.RunAdAction(AdActionType.SearchGroupsByQuery,
new LdapSearchByQueryParameters(data.getDomain(), ldapQueryData))
.getReturnValue();
return (result != null) ? result : new java.util.ArrayList<ad_groups>();
}
}
protected List<VmTemplate> searchVMTemplates() {
List<VmTemplate> returnValue;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<VmTemplate>();
} else {
List<VmTemplate> tmp = DbFacade.getInstance().getVmTemplateDAO().getAllWithQuery(data.getQuery());
for (IVdcQueryable vmt_helper : tmp) {
VmTemplate vmt = (VmTemplate) vmt_helper;
VmTemplateHandler.UpdateDisksFromDb(vmt);
}
returnValue = tmp;
}
return returnValue;
}
protected List<AuditLog> searchAuditLogEvents() {
List<AuditLog> returnValue = null;
QueryData2 data = InitQueryData(false);
if (data == null) {
returnValue = new ArrayList<AuditLog>();
} else {
returnValue = DbFacade.getInstance().getAuditLogDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
protected List<vm_pools> searchVmPools() {
List<vm_pools> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<vm_pools>();
} else {
returnValue = DbFacade.getInstance().getVmPoolDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
protected List<VDSGroup> searchClusters() {
List<VDSGroup> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<VDSGroup>();
} else {
returnValue = DbFacade.getInstance().getVdsGroupDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
protected List<storage_pool> searchStoragePool() {
List<storage_pool> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<storage_pool>();
} else {
returnValue = DbFacade.getInstance().getStoragePoolDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
protected List<storage_domains> searchStorageDomain() {
List<storage_domains> returnValue = null;
QueryData2 data = InitQueryData(true);
if (data == null) {
returnValue = new ArrayList<storage_domains>();
} else {
returnValue = DbFacade.getInstance().getStorageDomainDAO().getAllWithQuery(data.getQuery());
}
return returnValue;
}
private QueryData2 InitQueryData(boolean useCache) {
QueryData2 data = null;
boolean isExistsValue = false;
boolean IsFromYesterday = false;
boolean isSafe = false;
String searchKey = "";
try {
String searchText = getParameters().getSearchPattern();
// find if this is a trivial search expression (like 'Vms:' etc).
isSafe = SearchObjects.isSafeExpression(searchText);
getSearchReturnValue().setIsSearchValid(true);
if (useCache) {
// first lets check the cache of queries.
searchKey = String.format("%1$s,%2$s", searchText, getParameters().getMaxCount());
isExistsValue = (data = mQueriesCache.get(searchKey)) != null;
if (isExistsValue) {
TimeSpan span = DateTime.getNow().Subtract(data.getDate());
if (span.Days >= 1) {
IsFromYesterday = true;
}
}
}
// query not in cache or the cached entry is too old, process the
// search text.
if (!isExistsValue || IsFromYesterday) {
log.debugFormat("ResourceManager::searchBusinessObjects(''{0}'') - entered", searchText);
data = new QueryData2();
data.setPreQueryCommand(DbFacade.getInstance().getDbEngineDialect().getPreSearchQueryCommand());
ISyntaxChecker curSyntaxChecker;
String[] splitted = searchText.split("[:@ ]");
if ((StringHelper.EqOp(splitted[0].toUpperCase(), SearchObjects.AD_USER_OBJ_NAME))
|| (StringHelper.EqOp(splitted[0].toUpperCase(), SearchObjects.AD_USER_PLU_OBJ_NAME))
|| (StringHelper.EqOp(splitted[0].toUpperCase(), SearchObjects.AD_GROUP_OBJ_NAME))
|| (StringHelper.EqOp(splitted[0].toUpperCase(), SearchObjects.AD_GROUP_PLU_OBJ_NAME))) {
if (searchText.indexOf('@') > 0 && splitted.length > 1) {
data.setDomain(splitted[1]);
searchText = searchText.substring(0, searchText.indexOf('@'))
+ searchText.substring(searchText.indexOf(':'));
} else {
String domain = LdapBrokerUtils.getDomainsList().get(0);
data.setDomain(domain);
}
curSyntaxChecker = SyntaxCheckerFactory.CreateADSyntaxChecker(Config
.<String> GetValue(ConfigValues.AuthenticationMethod));
} else {
curSyntaxChecker = _defaultSyntaxChecker;
}
SyntaxContainer searchObj = curSyntaxChecker.analyzeSyntaxState(searchText, true);
// set the case-sensitive flag
searchObj.setCaseSensitive(getParameters().getCaseSensitive());
searchObj.setMaxCount(getParameters().getMaxCount() == -1 ? Config
.<Integer> GetValue(ConfigValues.SearchResultsLimit) : getParameters().getMaxCount());
// setting FromSearch value
searchObj.setSearchFrom(getParameters().getSearchFrom());
if (searchObj.getError() != SyntaxError.NO_ERROR) {
getSearchReturnValue().setIsSearchValid(false);
log.warnFormat("ResourceManager::searchBusinessObjects - erroneous search text - ''{0}''",
searchText);
// throw new
// VdcBLLException(VdcBllErrors.SEARCH_ERRORNOUS_SEARCH_TEXT);
int startPos = searchObj.getErrorStartPos();
int endPos = searchObj.getErrorEndPos();
int length = endPos - startPos;
String error =
(length > 0 && ((startPos + 1 + length) < searchText.length())
&& (endPos + 1 < searchText.length()))
?
searchText.substring(0, startPos)
+ "$"
+ searchText.substring(startPos + 1, startPos + 1
+ length) + "$"
+ searchText.substring(endPos + 1)
:
searchObj.getError().toString();
getSearchReturnValue().setExceptionString(error);
return null;
}
if (searchObj.getvalid() != true) {
getSearchReturnValue().setIsSearchValid(false);
log.warnFormat("ResourceManager::searchBusinessObjects - Invalid search text - ''{0}''", searchText);
// throw new
// VdcBLLException(VdcBllErrors.SEARCH_INVALID_SEARCH_TEXT);
return null;
}
// An expression is considered safe if matches a trivial search.
data.setQType(searchObj.getSearchObjectStr());
data.setQuery(curSyntaxChecker.generateQueryFromSyntaxContainer(searchObj, isSafe));
data.setDate(new java.util.Date());
// when looking for tags , the query contains all parent children tag id's
// statically, therefore , in order to reflect changes in the parent tree
// we should not rely on the cached query in such case and have to build the
// query from scratch.
if (!containsStaticInValues(data.getQuery()))
mQueriesCache.put(searchKey, data);
}
} catch (SearchEngineIllegalCharacterException e){
log.error("Search expression can not end with ESCAPE character:" + getParameters().getSearchPattern());
data = null;
getSearchReturnValue().setIsSearchValid(false);
} catch (SqlInjectionException e) {
log.error("Sql Injection in search: " + getParameters().getSearchPattern());
data = null;
getSearchReturnValue().setIsSearchValid(false);
} catch (RuntimeException ex) {
log.warn("Illegal search: " + getParameters().getSearchPattern(), ex);
data = null;
getSearchReturnValue().setIsSearchValid(false);
}
return data;
}
private boolean containsStaticInValues(String query) {
final String MATCH_IN_TAG_ID_CLAUSE = "with_tags.tag_id in";
return query.toLowerCase().contains(MATCH_IN_TAG_ID_CLAUSE);
}
private static LogCompat log = LogFactoryCompat.getLog(SearchQuery.class);
}