no.trank.openpipe.solr.SolrHttpDocumentPoster.java Source code

Java tutorial

Introduction

Here is the source code for no.trank.openpipe.solr.SolrHttpDocumentPoster.java

Source

/*
 * Copyright 2007  T-Rank AS
 * 
 * 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 no.trank.openpipe.solr;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLStreamException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;

import no.trank.openpipe.api.PipelineException;

/**
 * @version $Revision$
 */
public class SolrHttpDocumentPoster {
    private int docsPerPost = 0;
    private int unpostedDocs = 0;
    private int uncommitedDocs = 0;
    private String postUrl;
    private String encoding = "UTF-8";
    private HttpClient httpClient = new HttpClient();
    private SolrXmlDocumentWriter solrDocumentWriter;
    private boolean inAdd = false;
    private XMLBufferRequestEntity buf;
    private UpdateOptions updateOptions = new UpdateOptions();
    private String user;
    private String password;
    private File storePostsDir;
    private int postCount = 0;
    private boolean prettyXML;

    public void prepare() throws IOException {
        URL url = new URL(postUrl);
        AuthScope authScope = new AuthScope(url.getHost(), url.getPort());
        if (user != null) {
            httpClient.getState().setCredentials(authScope, new UsernamePasswordCredentials(user, password));
        }
        if (storePostsDir != null && !storePostsDir.isDirectory()) {
            if (!storePostsDir.mkdirs()) {
                throw new IOException("No such directory: " + storePostsDir.getAbsolutePath());
            }
        }
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void setPostUrl(String postUrl) {
        this.postUrl = postUrl;
    }

    public void setDocsPerPost(int docsPerPost) {
        this.docsPerPost = docsPerPost;
    }

    public UpdateOptions getUpdateOptions() {
        return updateOptions;
    }

    public void setUpdateOptions(UpdateOptions updateOptions) {
        this.updateOptions = updateOptions;
    }

    public File getStorePostsDir() {
        return storePostsDir;
    }

    public void setStorePostsDir(File storePostsDir) {
        this.storePostsDir = storePostsDir;
    }

    public boolean isPrettyXML() {
        return prettyXML;
    }

    public void setPrettyXML(boolean prettyXML) {
        this.prettyXML = prettyXML;
    }

    public void add(HashMap<String, List<String>> solrOutputDoc, Map<String, String> attribs)
            throws XMLStreamException, PipelineException {
        addDocument(solrOutputDoc, attribs);
        uncommitedDocs++;
        if (++unpostedDocs >= docsPerPost) {
            endAdd();
        }
    }

    public void optimize() throws PipelineException, XMLStreamException {
        endAdd();
        openPostStream();
        solrDocumentWriter.optimize();
        closePostStream();
    }

    public void commit() throws XMLStreamException, PipelineException {
        endAdd();
        openPostStream();
        solrDocumentWriter.commit();
        closePostStream();
        uncommitedDocs = 0;
    }

    public void finish() throws XMLStreamException, PipelineException {
        if (uncommitedDocs > 0) {
            commit();
        }
    }

    public void delete(List<String> fieldValueList) throws PipelineException, XMLStreamException {
        endAdd();
        if (fieldValueList != null && !fieldValueList.isEmpty()) {
            openPostStream();
            solrDocumentWriter.deleteById(fieldValueList);
            closePostStream();
        } else {
            throw new PipelineException("Can not delete document. The id field is not set.");
        }
        uncommitedDocs++;
    }

    private void addDocument(HashMap<String, List<String>> solrOutputDoc, Map<String, String> attribs)
            throws XMLStreamException, PipelineException {
        startAdd();
        solrDocumentWriter.startDoc(attribs);
        for (Map.Entry<String, List<String>> fieldEntry : solrOutputDoc.entrySet()) {
            for (String fieldValue : fieldEntry.getValue()) {
                solrDocumentWriter.writeField(fieldEntry.getKey(), fieldValue);
            }
        }
        solrDocumentWriter.endDoc();
    }

    private void startAdd() throws PipelineException, XMLStreamException {
        if (!inAdd) {
            openPostStream();
            solrDocumentWriter.startAdd();
            inAdd = true;
        }
    }

    private void endAdd() throws XMLStreamException, PipelineException {
        if (inAdd) {
            solrDocumentWriter.endAdd();
            inAdd = false;
            closePostStream();
            unpostedDocs = 0;
        }
    }

    private void openPostStream() throws PipelineException {
        try {
            if (buf == null) {
                buf = new XMLBufferRequestEntity(4096);
            } else {
                buf.reset();
            }
            solrDocumentWriter = new SolrXmlDocumentWriter(new OutputStreamWriter(buf, encoding), updateOptions,
                    prettyXML);
        } catch (IOException e) {
            throw new PipelineException("Could not create post streams", e);
        } catch (XMLStreamException e) {
            throw new PipelineException("Could not create solrXmlDocWriter", e);
        }
    }

    private void closePostStream() throws PipelineException {
        // Closing the writer
        if (solrDocumentWriter != null) {
            try {
                solrDocumentWriter.close();
            } catch (Exception e) {
                // Do nothing
            }
            solrDocumentWriter = null;
        }

        // Flushing the data to solr
        try {
            final PostMethod postMethod = new PostMethod(postUrl);
            try {
                postMethod.setRequestEntity(buf);
                writePostToFile();
                int status = httpClient.executeMethod(postMethod);
                if (status < 200 || status >= 300) {
                    throw new PipelineException(
                            "Solr post returned status: " + status + "\n" + postMethod.getResponseBodyAsString());
                }
            } finally {
                postMethod.releaseConnection();
            }
        } catch (IOException e) {
            throw new PipelineException("Could not post document(s) to solr", e);
        } finally {
            try {
                buf.close();
            } catch (Exception e) {
                // Do nothing
            }
            buf = null;
        }
    }

    private void writePostToFile() throws IOException {
        if (storePostsDir != null) {
            final FileOutputStream fout = new FileOutputStream(new File(storePostsDir, createFileName()));
            try {
                buf.writeRequest(fout);
            } finally {
                try {
                    fout.close();
                } catch (IOException e) {
                    // Ignoring
                }
            }
        }
    }

    private String createFileName() {
        return new Formatter().format("%1$04d.xml", postCount++).toString();
    }

    private static class XMLBufferRequestEntity extends ByteArrayOutputStream implements RequestEntity {

        private XMLBufferRequestEntity(int size) {
            super(size);
        }

        @Override
        public boolean isRepeatable() {
            return true;
        }

        @Override
        public void writeRequest(OutputStream out) throws IOException {
            out.write(buf, 0, count);
        }

        @Override
        public long getContentLength() {
            return count;
        }

        @Override
        public String getContentType() {
            return "text/xml";
        }
    }
}