Java tutorial
/* * $HeadURL$ * $Id$ * * Copyright (c) 2006-2011 by Public Library of Science * http://plos.org * http://ambraproject.org * * 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.ambraproject.service.search; import org.ambraproject.util.XPathUtil; import org.apache.commons.configuration.Configuration; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.Map; /** * Implementation of {@link org.ambraproject.service.search.SolrHttpService} that uses URL objects to make http requests to * the solr server. * <p/> * This bean should be injected via spring to the action classes that make use of it, so there will only be one copy of * the bean per ambra instance * <p/> * @author Alex Kudlick Date: Feb 15, 2011 * <p/> * org.ambraproject.solr */ public class SolrHttpServiceImpl implements SolrHttpService { private static final Logger log = LoggerFactory.getLogger(SolrHttpServiceImpl.class); private XPathUtil xPathUtil = new XPathUtil(); private String solrUrl; private Configuration config; private HttpClient httpClient; private static final String XML = "xml"; private static final String URL_CONFIG_PARAM = "ambra.services.search.server.url"; private static final String RETURN_TYPE_PARAM = "wt"; private static final String Q_PARAM = "q"; private static final String NO_FILTER = "*:*"; /** * number of milliseconds to wait on a url connection to SOLR */ private static final int CONNECTION_TIMEOUT = 100; /** * @inheritDoc */ @Override public Document makeSolrRequest(Map<String, String> params) throws SolrException { if (solrUrl == null || solrUrl.isEmpty()) { setSolrUrl(config.getString(URL_CONFIG_PARAM)); } //make sure the return type is xml if (!params.keySet().contains(RETURN_TYPE_PARAM) || !params.get(RETURN_TYPE_PARAM).equals(XML)) { params.put(RETURN_TYPE_PARAM, XML); } //make sure that we include a 'q' parameter if (!params.keySet().contains(Q_PARAM)) { params.put(Q_PARAM, NO_FILTER); } String queryString = "?"; for (String param : params.keySet()) { String value = params.get(param); if (queryString.length() > 1) { queryString += "&"; } queryString += (cleanInput(param) + "=" + cleanInput(value)); } URL url; String urlString = solrUrl + queryString; log.debug("Making Solr http request to " + urlString); try { url = new URL(urlString); } catch (MalformedURLException e) { throw new SolrException("Bad Solr Url: " + urlString, e); } InputStream urlStream = null; Document doc = null; try { URLConnection connection = url.openConnection(); connection.setConnectTimeout(CONNECTION_TIMEOUT); connection.connect(); urlStream = connection.getInputStream(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); doc = builder.parse(urlStream); } catch (IOException e) { throw new SolrException("Error connecting to the Solr server at " + solrUrl, e); } catch (ParserConfigurationException e) { throw new SolrException("Error configuring parser xml parser for solr response", e); } catch (SAXException e) { throw new SolrException("Solr Returned bad XML for url: " + urlString, e); } finally { //Close the input stream if (urlStream != null) { try { urlStream.close(); } catch (IOException e) { log.error("Error closing url stream to Solr", e); } } } return doc; } /** * Clean a string input for insertion into a url * * @param param * @return */ private String cleanInput(String param) { try { return URLEncoder.encode(param, "UTF-8"); } catch (UnsupportedEncodingException e) { return param; } } public void setSolrUrl(String solrUrl) { if (solrUrl.contains("/select")) { this.solrUrl = solrUrl; } else { this.solrUrl = solrUrl.endsWith("/") ? solrUrl + "select" : solrUrl + "/select"; } this.solrUrl = this.solrUrl.replaceAll("\\?", ""); } /** * @inheritDoc */ public Document makeSolrRequestForRss(String queryString) throws SolrException { if (solrUrl == null || solrUrl.isEmpty()) { setSolrUrl(config.getString(URL_CONFIG_PARAM)); } queryString = "?" + queryString; URL url; String urlString = solrUrl + queryString; log.debug("Making Solr http request to " + urlString); try { url = new URL(urlString); } catch (MalformedURLException e) { throw new SolrException("Bad Solr Url: " + urlString, e); } InputStream urlStream = null; Document doc = null; try { URLConnection connection = url.openConnection(); connection.setConnectTimeout(CONNECTION_TIMEOUT); connection.connect(); urlStream = connection.getInputStream(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); doc = builder.parse(urlStream); } catch (IOException e) { throw new SolrException("Error connecting to the Solr server at " + solrUrl, e); } catch (ParserConfigurationException e) { throw new SolrException("Error configuring parser xml parser for solr response", e); } catch (SAXException e) { throw new SolrException("Solr Returned bad XML for url: " + urlString, e); } finally { //Close the input stream if (urlStream != null) { try { urlStream.close(); } catch (IOException e) { log.error("Error closing url stream to Solr", e); } } } return doc; } /** * @inheritDoc */ @Override public void makeSolrPostRequest(Map<String, String> params, String data, boolean isCSV) throws SolrException { String postUrl = config.getString(URL_CONFIG_PARAM); String queryString = "?"; for (String param : params.keySet()) { String value = params.get(param); if (queryString.length() > 1) { queryString += "&"; } queryString += (cleanInput(param) + "=" + cleanInput(value)); } String filename; String contentType; if (isCSV) { postUrl = postUrl + "/update/csv" + queryString; filename = "data.csv"; contentType = "text/plain"; } else { postUrl = postUrl + "/update" + queryString; filename = "data.xml"; contentType = "text/xml"; } log.debug("Making Solr http post request to " + postUrl); PostMethod filePost = new PostMethod(postUrl); try { filePost.setRequestEntity(new MultipartRequestEntity(new Part[] { new FilePart(filename, new ByteArrayPartSource(filename, data.getBytes("UTF-8")), contentType, "UTF-8") }, filePost.getParams())); } catch (UnsupportedEncodingException ex) { throw new SolrException(ex); } try { int response = httpClient.executeMethod(filePost); if (response == 200) { log.info("Request Complete: {}", response); //Confirm SOLR result status is 0 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource source = new InputSource(filePost.getResponseBodyAsStream()); Document doc = db.parse(source); String result = xPathUtil.evaluate(doc, "//int[@name=\'status\']"); if (!"0".equals(result)) { log.error("SOLR Returned non zero result: {}", result); throw new SolrException("SOLR Returned non zero result: " + result); } } else { log.error("Request Failed: {}", response); throw new SolrException("Request Failed: " + response); } } catch (IOException ex) { throw new SolrException(ex); } catch (ParserConfigurationException ex) { throw new SolrException(ex); } catch (SAXException ex) { throw new SolrException(ex); } catch (XPathExpressionException ex) { throw new SolrException(ex); } } @Required public void setConfig(Configuration config) { this.config = config; } @Required public void setHttpClient(HttpClient httpClient) { this.httpClient = httpClient; } }