/** * Copyright: 2013 Regents of the University of California and the * National Center for Ecological Analysis and Synthesis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.ucsb.nceas.metacat.common.query; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.ParserConfigurationException; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.XML; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SchemaField; import org.apache.solr.servlet.SolrRequestParsers; import org.dataone.service.exceptions.NotFound; import org.dataone.service.exceptions.NotImplemented; import org.dataone.service.exceptions.UnsupportedType; import org.dataone.service.types.v1.Identifier; import org.dataone.service.types.v1.Subject; import org.xml.sax.SAXException; import edu.ucsb.nceas.metacat.common.query.SolrQueryResponseTransformer; /** *The query service of the embedded solr server. * @author tao * */ public class EmbeddedSolrQueryService extends SolrQueryService { private EmbeddedSolrServer solrServer = null; private CoreContainer coreContainer = null; private String collectionName = null; private SolrCore solrCore = null; /** * Constructor. * @param solrServer * @param solrCore * @throws NotFound */ public EmbeddedSolrQueryService(EmbeddedSolrServer solrServer, CoreContainer coreContainer, String collectionName) throws NotFound { if(solrServer == null) { throw new NullPointerException("EmbeddedSolrQueryService.constructor - the EmbeddedSolrServer parameter can't be null."); } if(coreContainer == null) { throw new NullPointerException("EmbeddedSolrQueryService.constructor - the CoreContainer parameter can't be null."); } if(collectionName == null || collectionName.trim().equals("")) { throw new NullPointerException("EmbeddedSolrQueryService.constructor - the name of Collection parameter can't be null or empty."); } this.solrServer = solrServer; this.coreContainer = coreContainer; this.collectionName = collectionName; this.solrCore = this.coreContainer.getCore(collectionName); if(solrCore == null) { throw new NotFound("0000","EmbeddedSolrQueryService.constructor - There is no SolrCore named "+collectionName+"."); } schema = solrCore.getSchema(); fieldMap = schema.getFields(); } /** * Query the Solr server with specified query and user's identity. If the Subjects * is null, there will be no access rules for the query. This is the for the http solr server. * @param query the query string * @param subjects the user's identity which sent the query * @return the response * @throws Exception */ /*public InputStream query(String query, Setsubjects) throws Exception { throw new NotImplemented("0000", "EmbeddSolrQueryService - the method of query(String query, Setsubjects) is not for the EmbeddedSolrServer. We donot need to implemente it"); }*/ /** * Query the Solr server with specified query and user's identity. If the Subjects * is null, there will be no access rules for the query. This is for the embedded solr server. * @param query the query params. * @param subjects the user's identity which sent the query * @return the response * @throws SAXException * @throws IOException * @throws ParserConfigurationException * @throws SolrServerException * @throws UnsupportedType * @throws Exception */ public InputStream query(SolrParams query, Setsubjects) throws ParserConfigurationException, IOException, SAXException, SolrServerException, UnsupportedType { InputStream inputStream = null; String wt = query.get(WT); query = appendAccessFilterParams(query, subjects); SolrQueryResponseTransformer solrTransformer = new SolrQueryResponseTransformer(solrCore); // handle normal and skin-based queries if (isSupportedWT(wt)) { // just handle as normal solr query //reload the core before query. Only after reloading the core, the query result can reflect the change made in metacat-index module. coreContainer.reload(collectionName); QueryResponse response = solrServer.query(query); inputStream = solrTransformer.transformResults(query, response, wt); } else { throw new UnsupportedType("0000","EmbeddSolrQueryService.query - the wt type "+wt+" in the solr query is not supported"); } return inputStream; } /** * Get the fields map of the index schema * @return the fields map (the field name is the key and the SchemaField is the value). */ public Map getIndexSchemaFields() { return fieldMap; } /** * Get the list of the valid field name (moved the fields names of the CopyFieldTarget). * @return */ public List getValidSchemaField() { return super.getValidSchemaFields(); } /** * Get the version of the solr server. * @return */ public String getSolrServerVersion() { if( solrSpecVersion !=null ) { return solrSpecVersion; } else { Package p = SolrCore.class.getPackage(); StringWriter tmp = new StringWriter(); solrSpecVersion = p.getSpecificationVersion(); if (null != solrSpecVersion) { try { XML.escapeCharData(solrSpecVersion, tmp); solrSpecVersion = tmp.toString(); } catch (IOException e) { e.printStackTrace(); } } if (solrSpecVersion == null || solrSpecVersion.trim().equals("")) { solrSpecVersion = UNKNOWN; } return solrSpecVersion; } } /** * If there is a solr doc for the given id. * @param id - the specified id. * @return true if there is a solr doc for this id. */ public boolean hasSolrDoc(Identifier id) throws ParserConfigurationException, SolrServerException, IOException, SAXException{ boolean hasIt = false; if(id != null && id.getValue() != null && !id.getValue().trim().equals("") ) { SolrParams query = buildIdQuery(id.getValue()); coreContainer.reload(collectionName); QueryResponse response = solrServer.query(query); hasIt = hasResult(response); } return hasIt; } /** * Build a query for decide if the solr server has the id. * @param id * @return the query */ public static SolrParams buildIdQuery(String id) { String query = "select?q=id:"+id; query = query.replaceAll("\\+", "%2B"); SolrParams solrParams = SolrRequestParsers.parseQueryString(query); return solrParams; } /** * Determine if the response has any solr documents. * @param response * @return true if it has at least one solr document; */ public static boolean hasResult(QueryResponse response) { boolean hasResult = false; if(response != null) { SolrDocumentList list = response.getResults(); if(list != null && list.getNumFound() >0) { hasResult = true; } } return hasResult; } }