/*
* 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.producer;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import no.trank.openpipe.api.Pipeline;
import no.trank.openpipe.solr.producer.xml.XmlStreamDocumentReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Translates Solr update posts into <code>Document</code> instances and feeds them into the <code>Pipeline</code>
* instance.
*
* @version $Revision$
*/
public class SolrUpdateServlet extends HttpServlet {
private static final Logger log = LoggerFactory.getLogger(SolrUpdateServlet.class);
private Pipeline pipeline;
private final XMLInputFactory inputFactory;
private final XMLOutputFactory outputFactory;
public SolrUpdateServlet() {
inputFactory = XMLInputFactory.newInstance();
outputFactory = XMLOutputFactory.newInstance();
}
/**
* Handles update POSTs. Keeps the connection open until all documents have been fed into the pipeline.
* Sets the response status code to 200 on success, 400 on failure to read XML.
*/
@Override
protected void doPost(final HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
long time = System.currentTimeMillis();
log.debug("Post uri: {}", req.getRequestURI());
int status;
final InputStream is = req.getInputStream();
try {
final XMLStreamReader reader = inputFactory.createXMLStreamReader(is);
try {
final XmlStreamDocumentReader documents = new XmlStreamDocumentReader(reader);
if (pipeline.run(documents)) {
status = documents.isFailure() ? HttpServletResponse.SC_BAD_REQUEST : HttpServletResponse.SC_OK;
} else {
status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
} finally {
try {
reader.close();
} catch (XMLStreamException e) {
// Igonring
}
}
} catch (XMLStreamException e) {
log.warn("Error creating xml stream", e);
status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} finally {
is.close();
}
resp.setStatus(status);
if (status == HttpServletResponse.SC_OK) {
writeSuccess(resp, System.currentTimeMillis() - time);
}
else {
writeFailure(resp, status);
}
resp.flushBuffer();
log.info("Took {} ms. Success: {}", System.currentTimeMillis() - time, status);
}
private void writeSuccess(HttpServletResponse resp, long time) throws IOException {
resp.setCharacterEncoding("UTF-8");
XMLStreamWriter writer = null;
try {
writer = outputFactory.createXMLStreamWriter(resp.getOutputStream(), "UTF-8");
writer.writeStartDocument("UTF-8", "1.0");
writer.writeStartElement("response");
writer.writeStartElement("lst");
writer.writeAttribute("name", "responseHeader");
writer.writeStartElement("int");
writer.writeAttribute("name", "status");
writer.writeCharacters("0");
writer.writeEndElement();
writer.writeStartElement("int");
writer.writeAttribute("name", "QTime");
writer.writeCharacters("" + time);
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
} catch (XMLStreamException e) {
log.warn("Error writing success XML", e);
}
finally {
if (writer != null) {
try {
writer.close();
} catch (XMLStreamException e) {
// ignore
}
}
}
}
private void writeFailure(HttpServletResponse resp, int status) throws IOException {
resp.setCharacterEncoding("ISO-8859-1");
PrintWriter pw = new PrintWriter(resp.getOutputStream());
pw.write("<html>\n");
pw.write("<head>\n");
pw.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"/>\n");
pw.write("<title>Error " + status + " </title>\n");
pw.write("</head>\n");
pw.write("<body><h2>HTTP ERROR: " + status + "</h2></body>\n");
pw.write("</html>");
pw.flush();
}
public void setPipeline(Pipeline pipeline) {
this.pipeline = pipeline;
}
}