001/* 002 * Copyright 2024 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.solr; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Map; 021import java.util.Set; 022 023import org.apache.avalon.framework.activity.Initializable; 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.avalon.framework.service.Serviceable; 028import org.apache.commons.lang3.exception.ExceptionUtils; 029import org.apache.solr.client.solrj.SolrClient; 030import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteSolrException; 031import org.apache.solr.client.solrj.request.json.DirectJsonQueryRequest; 032import org.apache.solr.client.solrj.response.QueryResponse; 033 034import org.ametys.cms.content.indexing.solr.SolrIndexer; 035import org.ametys.cms.search.solr.SearcherFactory; 036import org.ametys.cms.search.solr.SolrClientProvider; 037import org.ametys.core.ui.Callable; 038import org.ametys.runtime.plugin.component.AbstractLogEnabled; 039 040/** 041 * Handler to execute Solr JSON queries 042 */ 043public class SolrQueryHandler extends AbstractLogEnabled implements Component, Serviceable, Initializable 044{ 045 /** Avalon role. */ 046 public static final String ROLE = SolrQueryHandler.class.getName(); 047 048 /** The searcher factory. */ 049 protected SearcherFactory _searcherFactory; 050 /** The solr client */ 051 protected SolrClient _solrClient; 052 /** The Solr indexer */ 053 protected SolrIndexer _solrIndexer; 054 /** The solr client provider */ 055 protected SolrClientProvider _solrClientProvider; 056 057 public void service(ServiceManager manager) throws ServiceException 058 { 059 _searcherFactory = (SearcherFactory) manager.lookup(SearcherFactory.ROLE); 060 _solrClientProvider = (SolrClientProvider) manager.lookup(SolrClientProvider.ROLE); 061 _solrIndexer = (SolrIndexer) manager.lookup(SolrIndexer.ROLE); 062 } 063 064 public void initialize() throws Exception 065 { 066 _solrClient = _solrClientProvider.getReadClient(); 067 } 068 069 /** 070 * Execute a solr query. 071 * @param query The query as a String representing a JSON. 072 * @param coreName The solr core name 073 * @return The result as a JSON String 074 * @throws Exception If an error occurs 075 */ 076 @Callable(rights = "CMS_Rights_Solr_Query", context = "/admin") 077 public Map<String, Object> executeSolrQuery(String query, String coreName) throws Exception 078 { 079 DirectJsonQueryRequest queryRequest = new DirectJsonQueryRequest(query); 080 081 try 082 { 083 QueryResponse response = queryRequest.process(_solrClient, _solrClientProvider.getCollectionName(coreName)); 084 return Map.of("result", response.jsonStr()); 085 } 086 catch (RemoteSolrException e) 087 { 088 return Map.of("errorMessage", e.getMessage(), 089 "errorStackTrace", ExceptionUtils.getStackTrace(e)); 090 } 091 } 092 093 /** 094 * Get the solr core names 095 * @return The solr core names 096 * @throws Exception If an error occurs 097 */ 098 @Callable(rights = "CMS_Rights_Solr_Query", context = "/admin") 099 public List<Map<String, String>> getSolrCoreNames() throws Exception 100 { 101 List<Map<String, String>> results = new ArrayList<>(); 102 Set<String> coreNames = _solrIndexer.getCoreNames(); 103 for (String coreName : coreNames) 104 { 105 results.add(Map.of("name", coreName)); 106 } 107 return results; 108 } 109}