org.apache.oodt.cas.filemgr.catalog.solr.SolrClient.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.oodt.cas.filemgr.catalog.solr.SolrClient.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.oodt.cas.filemgr.catalog.solr;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.oodt.cas.filemgr.structs.ProductType;
import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Class containing client-side functionality for interacting with a Solr server.
 * This class uses an {@link HttpClient} for all HTTP communication.
 * 
 * @author Luca Cinquini
 *
 */
public class SolrClient {

    // base URL of Solr server
    private String solrUrl;

    private final Logger LOG = Logger.getLogger(this.getClass().getName());

    /**
     * Constructor initializes the Solr URL
     * @param url
     */
    public SolrClient(final String url) {

        solrUrl = url;

    }

    /**
     * Method to send one or more documents to be indexed to Solr.
     * 
     * @param docs
     * @param commit
     * @param mimeType : the mime-type format of the documents
     * @return
     * @throws CatalogException
     */
    public String index(List<String> docs, boolean commit, String mimeType) throws CatalogException {

        try {

            final String url = this.buildUpdateUrl();

            // build message
            StringBuilder message = new StringBuilder("<add>");
            for (String doc : docs) {
                message.append(doc);
            }
            message.append("</add>");

            // send POST request
            LOG.info("Posting message:" + message + " to URL:" + url);
            String response = doPost(url, message.toString(), mimeType);
            LOG.info(response);

            // commit changes ?
            if (commit) {
                this.commit();
            }

            LOG.info(response);
            return response;

        } catch (Exception e) {
            LOG.log(Level.SEVERE, e.getMessage());
            throw new CatalogException(e.getMessage());
        }

    }

    /**
     * Method to send a message containing a 'delete' instruction to Solr.
     * @param id
     * @param commit
     * @return
     * @throws CatalogException
     */
    public String delete(String id, boolean commit) throws CatalogException {

        try {

            // build POST request
            String url = this.buildUpdateUrl();
            if (commit) {
                url += "?commit=true";
            }
            String message = "<delete><query>id:" + id + "</query></delete>";

            // send POST request
            LOG.info("Posting message:" + message + " to URL:" + url);

            return doPost(url, message, Parameters.MIME_TYPE_XML);

        } catch (Exception e) {
            LOG.log(Level.SEVERE, e.getMessage());
            throw new CatalogException(e.getMessage());
        }

    }

    /**
     * Method to query the Solr index for a product with the specified id.
     * @param id
     * @return
     */
    public String queryProductById(String id, String mimeType) throws CatalogException {

        ConcurrentHashMap<String, String[]> params = new ConcurrentHashMap<String, String[]>();
        params.put("q", new String[] { Parameters.PRODUCT_ID + ":" + id });
        return query(params, mimeType);

    }

    /**
     * Method to query the Solr index for a product with the specified name.
     * @param name
     * @param mimeType
     * @return
     */
    public String queryProductByName(String name, String mimeType) throws CatalogException {

        ConcurrentHashMap<String, String[]> params = new ConcurrentHashMap<String, String[]>();
        params.put("q", new String[] { Parameters.PRODUCT_NAME + ":" + name });
        return query(params, mimeType);

    }

    /**
     * Method to query Solr for the most recent 'n' products.
     * @param n
     * @return
     * @throws CatalogException
     */
    public String queryProductsByDate(int n, String mimeType) throws CatalogException {

        ConcurrentHashMap<String, String[]> params = new ConcurrentHashMap<String, String[]>();
        params.put("q", new String[] { "*:*" });
        params.put("rows", new String[] { "" + n });
        params.put("sort", new String[] { Parameters.PRODUCT_RECEIVED_TIME + " desc" });
        return query(params, mimeType);

    }

    /**
     * Method to query Solr for the most recent 'n' products of a specified type.
     * @param n
     * @return
     * @throws CatalogException
     */
    public String queryProductsByDateAndType(int n, ProductType type, String mimeType) throws CatalogException {

        ConcurrentHashMap<String, String[]> params = new ConcurrentHashMap<String, String[]>();
        params.put("q", new String[] { Parameters.PRODUCT_TYPE_NAME + type.getName() });
        params.put("rows", new String[] { "" + n });
        params.put("sort", new String[] { Parameters.PRODUCT_RECEIVED_TIME + " desc" });
        return query(params, mimeType);

    }

    /**
     * Method to commit the current changes to the Solr index.
     * @throws Exception
     */
    public void commit() throws IOException, CatalogException {

        String message = "<commit waitSearcher=\"true\"/>";
        String url = this.buildUpdateUrl();
        doPost(url, message, Parameters.MIME_TYPE_XML);

    }

    /**
     * Method to send a generic query to the Solr server.
     * 
     * @param parameters
     * @param mimeType : the desired mime type for the results (XML, JSON, ...)
     * @return
     */
    public String query(Map<String, String[]> parameters, String mimeType) throws CatalogException {

        try {

            // build HTTP request
            String url = this.buildSelectUrl();

            // execute request
            return this.doGet(url, parameters, mimeType);

        } catch (Exception e) {
            LOG.log(Level.SEVERE, e.getMessage());
            throw new CatalogException(e.getMessage());
        }

    }

    /**
     * Method to execute a GET request to the given URL with the given parameters.
     * @param url
     * @param parameters
     * @return
     */
    private String doGet(String url, Map<String, String[]> parameters, String mimeType)
            throws IOException, CatalogException {

        // build HTTP/GET request
        GetMethod method = new GetMethod(url);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String[]> key : parameters.entrySet()) {
            for (String value : key.getValue()) {
                nvps.add(new NameValuePair(key.getKey(), value));
            }
        }
        // request results in JSON format
        if (mimeType.equals(Parameters.MIME_TYPE_JSON)) {
            nvps.add(new NameValuePair("wt", "json"));
        }
        method.setQueryString(nvps.toArray(new NameValuePair[nvps.size()]));
        LOG.info("GET url: " + url + " query string: " + method.getQueryString());

        // send HTTP/GET request, return response
        return doHttp(method);

    }

    /**
     * Method to execute a POST request to the given URL.
     * @param url
     * @param document
     * @return
     */
    private String doPost(String url, String document, String mimeType) throws IOException, CatalogException {

        // build HTTP/POST request
        PostMethod method = new PostMethod(url);
        StringRequestEntity requestEntity = new StringRequestEntity(document, mimeType, "UTF-8");
        method.setRequestEntity(requestEntity);

        // send HTTP/POST request, return response
        return doHttp(method);

    }

    /**
     * Common functionality for HTTP GET and POST requests.
     * @param method
     * @return
     * @throws Exception
     */
    private String doHttp(HttpMethod method) throws IOException, CatalogException {

        StringBuilder response = new StringBuilder();
        BufferedReader br = null;
        try {

            // send request
            HttpClient httpClient = new HttpClient();
            // OODT-719 Prevent httpclient from spawning closewait tcp connections
            method.setRequestHeader("Connection", "close");

            int statusCode = httpClient.executeMethod(method);

            // read response
            if (statusCode != HttpStatus.SC_OK) {

                // still consume the response
                method.getResponseBodyAsString();
                throw new CatalogException("HTTP method failed: " + method.getStatusLine());

            } else {

                // read the response body.
                br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
                String readLine;
                while (((readLine = br.readLine()) != null)) {
                    response.append(readLine);
                }

            }

        } finally {
            // must release the connection even if an exception occurred
            method.releaseConnection();
            if (br != null) {
                try {
                    br.close();
                } catch (Exception ignored) {
                }
            }
        }

        return response.toString();

    }

    /**
     * Builds the URL used to update the Solr index.
     * 
     * Example: http://localhost:8983/solr/update?
     * @return
     */
    private String buildUpdateUrl() {

        return solrUrl + (solrUrl.endsWith("/") ? "" : "/") + "update";

    }

    /**
     * Builds the URL used to query the Solr index.
     * 
     * Example: http://localhost:8983/solr/select?
     * @return
     */
    private String buildSelectUrl() {

        return solrUrl + (solrUrl.endsWith("/") ? "" : "/") + "select";

    }

}