/* * Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * 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 org.wso2.carbon.registry.indexing.service; import org.apache.axis2.AxisFault; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrException; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.registry.admin.api.indexing.IContentBasedSearchService; import org.wso2.carbon.registry.common.ResourceData; import org.wso2.carbon.registry.common.TermData; import org.wso2.carbon.registry.common.services.RegistryAbstractAdmin; import org.wso2.carbon.registry.common.utils.CommonUtil; import org.wso2.carbon.registry.common.utils.UserUtil; import org.wso2.carbon.registry.core.ActionConstants; import org.wso2.carbon.registry.core.Collection; import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.pagination.PaginationContext; import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.registry.indexing.IndexingConstants; import org.wso2.carbon.registry.indexing.IndexingManager; import org.wso2.carbon.registry.indexing.indexer.IndexerException; import org.wso2.carbon.registry.indexing.solr.SolrClient; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.UserStoreException; import java.util.*; public class ContentBasedSearchService extends RegistryAbstractAdmin implements IContentBasedSearchService { private static final Log log = LogFactory.getLog(ContentBasedSearchService.class); public SearchResultsBean getContentSearchResults(String searchQuery) throws AxisFault{ try { UserRegistry registry = (UserRegistry) getRootRegistry(); return searchContent(searchQuery, registry); } catch (Exception e) { log.error("Error " + e.getMessage() + "at the content search back end component.", e ); } return new SearchResultsBean(); } public SearchResultsBean getAttributeSearchResults(String[][] attributes) throws AxisFault{ try { final Map<String, String> map = new HashMap<String, String>(attributes.length); UserRegistry registry = (UserRegistry) getRootRegistry(); for (String[] mapping : attributes) { map.put(mapping[0], mapping[1]); } return searchByAttribute(map, registry); } catch (Exception e) { log.error("Error occurred while getting the attribute search result.", e ); } return new SearchResultsBean(); } public SearchResultsBean getTermSearchResults(String[][] attributes) throws AxisFault{ try { final Map<String, String> map = new HashMap<String, String>(attributes.length); UserRegistry registry = (UserRegistry) getRootRegistry(); for (String[] mapping : attributes) { map.put(mapping[0], mapping[1]); } return searchTerms(map, registry); } catch (IndexerException | RegistryException e) { log.error("Error occurred while getting the term search result.", e ); } return new SearchResultsBean(); } @Deprecated private String[] sortByDateIfRequired(String[] authorizedPaths, final UserRegistry registry, PaginationContext paginationContext) throws RegistryException { if(paginationContext.getSortBy().equalsIgnoreCase("meta_created_date")) { if(paginationContext.getSortOrder().equalsIgnoreCase("ASC")) { Arrays.sort(authorizedPaths, new Comparator<String>() { public int compare(String path1, String path2) { try { return registry.getMetaData(path1).getCreatedTime().compareTo(registry.getMetaData(path2).getCreatedTime()); } catch(RegistryException ex) { return 0 ; } } }); } else if(paginationContext.getSortOrder().equalsIgnoreCase("DES")) { Arrays.sort(authorizedPaths, new Comparator<String>() { public int compare(String path1, String path2) { try { return registry.getMetaData(path2).getCreatedTime().compareTo(registry.getMetaData(path1).getCreatedTime()); } catch(RegistryException ex) { return 0 ; } } }); } } else if(paginationContext.getSortBy().equalsIgnoreCase("meta_last_updated_date")) { if(paginationContext.getSortOrder().equalsIgnoreCase("ASC")) { Arrays.sort(authorizedPaths, new Comparator<String>() { public int compare(String path1, String path2) { try { return registry.getMetaData(path1).getLastModified().compareTo(registry.getMetaData(path2).getLastModified()); } catch(RegistryException ex) { return 0 ; } } }); } else if(paginationContext.getSortOrder().equalsIgnoreCase("DES")) { Arrays.sort(authorizedPaths, new Comparator<String>() { public int compare(String path1, String path2) { try { return registry.getMetaData(path2).getLastModified().compareTo(registry.getMetaData(path1).getLastModified()); } catch(RegistryException ex) { return 0 ; } } }); } } return authorizedPaths; } /** * Method to get the SolrDocumentList * @param searchQuery search query * @param attributes search attributes map * @param registry Registry * @return SearchResultsBean * @throws IndexerException * @throws RegistryException */ private SearchResultsBean searchContentInternal(String searchQuery, Map<String, String> attributes, UserRegistry registry) throws IndexerException, RegistryException { SearchResultsBean resultsBean = new SearchResultsBean(); SolrClient client = SolrClient.getInstance(); // To verify advance search and metadata search // boolean isMetaDataSearch = true; String advanceSearchAttribute = attributes.get(IndexingConstants.ADVANCE_SEARCH); if (advanceSearchAttribute != null && advanceSearchAttribute.equals("true")) { // isMetaDataSearch = false; attributes.remove(IndexingConstants.ADVANCE_SEARCH); } SolrDocumentList results = new SolrDocumentList(); try { results = attributes.size() > 0 ? client.query(registry.getTenantId(), attributes) : client.query(searchQuery, registry.getTenantId()); } catch (SolrException e) { // catching the solr exception to avoid blank pages for invalid solr query, // so that it will return empty list and log the error message. log.error("Invalid Search Query, query contains invalid characters",e); } if (log.isDebugEnabled()) log.debug("result received " + results); List<ResourceData> filteredResults = new ArrayList<ResourceData>(); // check the authorization again for the filtered results for (SolrDocument solrDocument : results) { String path = getPathFromId((String) solrDocument.getFirstValue("id")); if ((isAuthorized(registry, path, ActionConstants.GET)) && (registry.resourceExists(path))) { filteredResults.add(loadResourceByPath(registry, path)); } } //commenting this, we don't need to do pagination here, we are using solr pagination. /* MessageContext messageContext = MessageContext.getCurrentMessageContext(); if (((messageContext != null && PaginationUtils.isPaginationHeadersExist(messageContext)) || PaginationContext.getInstance() != null) && isMetaDataSearch) { try { PaginationContext paginationContext; if (messageContext != null) { paginationContext = PaginationUtils.initPaginationContext(messageContext); } else { paginationContext = PaginationContext.getInstance(); } List<String> authorizedPathList = new ArrayList<String>(); for (SolrDocument solrDocument : results) { if (paginationContext.getLimit() > 0 && authorizedPathList.size() == paginationContext.getLimit()) { break; } String path = getPathFromId((String) solrDocument.getFirstValue("id")); if (registry.resourceExists(path) && isAuthorized(registry, path, ActionConstants.GET)) { authorizedPathList.add(path); } } String[] authorizedPaths = authorizedPathList.toArray(new String[authorizedPathList.size()]); // Fix for REGISTRY-3132 //sortByDateIfRequired(authorizedPaths, registry, paginationContext); String[] paginatedPaths; int start = paginationContext.getStart(); int count = paginationContext.getCount(); int rowCount = authorizedPaths.length; if (messageContext != null) { PaginationUtils.setRowCount(messageContext, Integer.toString(rowCount)); } paginationContext.setLength(authorizedPaths.length); int startIndex = start; *//*if (start == 1) { startIndex = 0; } else { startIndex = start; } *//* if (rowCount < start + count) { if(rowCount - startIndex < 0) { String msg = "PaginationContext parameter's start index seems to be greater than the limit count. Please verify your parameters"; if(log.isDebugEnabled()) { log.debug(msg); } resultsBean.setErrorMessage(msg); return resultsBean; } paginatedPaths = new String[rowCount - startIndex]; System.arraycopy(authorizedPaths, startIndex, paginatedPaths, 0, (rowCount - startIndex)); } else { paginatedPaths = new String[count]; System.arraycopy(authorizedPaths, startIndex, paginatedPaths, 0, count); } for (String path : paginatedPaths) { ResourceData resourceData = loadResourceByPath(registry, path); if (resourceData != null) { filteredResults.add(resourceData); } } } finally { if (messageContext != null) { PaginationContext.destroy(); } } } else { for (SolrDocument solrDocument : results) { String path = getPathFromId((String) solrDocument.getFirstValue("id")); if ((isAuthorized(registry, path, ActionConstants.GET))) { ResourceData resourceData = loadResourceByPath(registry, path); if (resourceData != null) { filteredResults.add(resourceData); } } } }*/ if (log.isDebugEnabled()) { log.debug("filtered results " + filteredResults + " for user " + registry.getUserName()); } resultsBean.setResourceDataList(filteredResults.toArray(new ResourceData[filteredResults.size()])); return resultsBean; } public SearchResultsBean searchContent(String searchQuery, UserRegistry registry) throws IndexerException, RegistryException { return searchContentInternal(searchQuery, Collections.<String, String>emptyMap(), registry); } public SearchResultsBean searchByAttribute(Map<String, String> attributes, UserRegistry registry) throws IndexerException, RegistryException { return searchContentInternal(null, attributes, registry); } public void restartIndexing() throws RegistryException { IndexingManager manager = IndexingManager.getInstance(); manager.restartIndexing(); } private String getPathFromId(String id) { return id.substring(0, id.lastIndexOf(IndexingConstants.FIELD_TENANT_ID)); } private boolean isAuthorized(UserRegistry registry, String resourcePath, String action) throws RegistryException{ UserRealm userRealm = registry.getUserRealm(); String userName = getLoggedInUserName(); try { if (!userRealm.getAuthorizationManager().isUserAuthorized(userName, resourcePath, action)) { return false; } } catch (UserStoreException e) { throw new RegistryException("Error at Authorizing " + resourcePath + " with user " + userName + ":" + e.getMessage(), e); } return true; } private ResourceData loadResourceByPath(UserRegistry registry, String path) throws RegistryException { ResourceData resourceData = new ResourceData(); resourceData.setResourcePath(path); if (path != null) { if (RegistryConstants.ROOT_PATH.equals(path)) { resourceData.setName("root"); } else { String[] parts = path.split(RegistryConstants.PATH_SEPARATOR); resourceData.setName(parts[parts.length - 1]); } } Resource child; //---------------------------------------------------------------------------------------------------------Ajith //This fix is to improve the performance of the artifact search //When we delete the artifacts that goes to activity logs and Solr indexer delete that resource from indexed //files as well. Therefore no need an extra ResourceExist() check for the result path which is returned //from Solr search. try { child = registry.get(path); } catch (RegistryException e) { log.debug("Failed to load resource from path which is returned from Solr search" + e.getMessage()); return null; } //---------------------------------------------------------------------------------------------------------Ajith resourceData.setResourceType(child instanceof Collection ? "collection" : "resource"); resourceData.setAuthorUserName(child.getAuthorUserName()); resourceData.setDescription(child.getDescription()); resourceData.setAverageRating(registry .getAverageRating(child.getPath())); Calendar createdDateTime = Calendar.getInstance(); createdDateTime.setTime(child.getCreatedTime()); resourceData.setCreatedOn(createdDateTime); CommonUtil.populateAverageStars(resourceData); String user = child.getProperty("registry.user"); if (registry.getUserName().equals(user)) { resourceData.setPutAllowed(true); resourceData.setDeleteAllowed(true); resourceData.setGetAllowed(true); } else { resourceData.setPutAllowed( UserUtil.isPutAllowed(registry.getUserName(), path, registry)); resourceData.setDeleteAllowed( UserUtil.isDeleteAllowed(registry.getUserName(), path, registry)); resourceData.setGetAllowed( UserUtil.isGetAllowed(registry.getUserName(), path, registry)); } child.discard(); return resourceData; } public static String getLoggedInUserName(){ return PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); } public SearchResultsBean searchTerms(Map<String, String> attributes, UserRegistry registry) throws IndexerException, RegistryException { return searchTermsInternal(null, null, attributes, registry); } public SearchResultsBean searchTermsByQuery(String searchQuery, String facetField, UserRegistry registry) throws IndexerException, RegistryException { return searchTermsInternal(searchQuery, facetField, Collections.<String, String>emptyMap(), registry); } private SearchResultsBean searchTermsInternal(String searchQuery, String facetField, Map<String, String> attributes, UserRegistry registry) throws IndexerException, RegistryException { SearchResultsBean resultsBean = new SearchResultsBean(); SolrClient client = SolrClient.getInstance(); //authenticate required attribute is not used, since we are going to authorize each time and not depends on this flag. attributes.remove(IndexingConstants.AUTH_REQUIRED); List<FacetField.Count> results = (searchQuery == null) ? client.facetQuery(registry.getTenantId(), attributes) : client.facetQuery(searchQuery, facetField, registry.getTenantId()); if (log.isDebugEnabled()) { log.debug("result for the term search: " + results); } List<TermData> termDataList = new ArrayList<>(); for (FacetField.Count count : results) { termDataList.add(new TermData(count.getName(), count.getCount())); } resultsBean.setTermDataList(termDataList.toArray(new TermData[termDataList.size()])); return resultsBean; } }