org.apache.solr.response.BinaryResponseWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of solr-core Show documentation
Show all versions of solr-core Show documentation
Apache Solr (module: core)
/*
* 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.solr.response;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Utf8CharSequence;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocList;
import org.apache.solr.search.ReturnFields;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.solr.common.util.ByteArrayUtf8CharSequence.convertCharSeq;
public class BinaryResponseWriter implements BinaryQueryResponseWriter {
// public static boolean useUtf8CharSeq = true;
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public void write(OutputStream out, SolrQueryRequest req, SolrQueryResponse response) throws IOException {
Resolver resolver = new Resolver(req, response.getReturnFields());
if (req.getParams().getBool(CommonParams.OMIT_HEADER, false)) response.removeResponseHeader();
try (JavaBinCodec jbc = new JavaBinCodec(resolver)) {
jbc.setWritableDocFields(resolver).marshal(response.getValues(), out);
}
}
private static void serialize(SolrQueryResponse response,Resolver resolver, String f) throws IOException {
try (JavaBinCodec jbc = new JavaBinCodec(resolver); FileOutputStream fos = new FileOutputStream(f)) {
jbc.setWritableDocFields(resolver).marshal(response.getValues(), fos);
fos.flush();
}
}
@Override
public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
throw new RuntimeException("This is a binary writer , Cannot write to a characterstream");
}
@Override
public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
return BinaryResponseParser.BINARY_CONTENT_TYPE;
}
@Override
public void init(NamedList args) {
/* NOOP */
}
public static class Resolver implements JavaBinCodec.ObjectResolver , JavaBinCodec.WritableDocFields {
protected final SolrQueryRequest solrQueryRequest;
protected IndexSchema schema;
protected ReturnFields returnFields;
public Resolver(SolrQueryRequest req, ReturnFields returnFields) {
solrQueryRequest = req;
this.returnFields = returnFields;
}
@Override
public Object resolve(Object o, JavaBinCodec codec) throws IOException {
if (o instanceof StoredField) {
CharSequence val = ((StoredField) o).getCharSequenceValue();
if (val instanceof Utf8CharSequence) {
codec.writeUTF8Str((Utf8CharSequence) val);
return null;
}
}
if (o instanceof ResultContext) {
ReturnFields orig = returnFields;
ResultContext res = (ResultContext)o;
if(res.getReturnFields()!=null) {
returnFields = res.getReturnFields();
}
// if (useUtf8CharSeq) {
ResultContext.READASBYTES.set(fieldName -> {
SchemaField fld = res.getRequest().getSchema().getFieldOrNull(fieldName);
return fld != null && fld.getType().isUtf8Field();
});
try {
writeResults(res, codec);
} finally {
ResultContext.READASBYTES.remove();
}
returnFields = orig;
return null; // null means we completely handled it
}
if (o instanceof DocList) {
ResultContext ctx = new BasicResultContext((DocList)o, returnFields, null, null, solrQueryRequest);
writeResults(ctx, codec);
return null; // null means we completely handled it
}
if( o instanceof IndexableField ) {
if(schema == null) schema = solrQueryRequest.getSchema();
IndexableField f = (IndexableField)o;
SchemaField sf = schema.getFieldOrNull(f.name());
try {
o = DocsStreamer.getValue(sf, f);
} catch (Exception e) {
log.warn("Error reading a field : " + o, e);
}
}
return o;
}
@Override
public boolean isWritable(String name) {
return returnFields.wantsField(name);
}
@Override
public boolean wantsAllFields() {
return returnFields.wantsAllFields();
}
protected void writeResultsBody( ResultContext res, JavaBinCodec codec ) throws IOException {
codec.writeTag(JavaBinCodec.ARR, res.getDocList().size());
Iterator docStreamer = res.getProcessedDocuments();
while (docStreamer.hasNext()) {
SolrDocument doc = docStreamer.next();
codec.writeSolrDocument(doc);
}
}
public void writeResults(ResultContext ctx, JavaBinCodec codec) throws IOException {
codec.writeTag(JavaBinCodec.SOLRDOCLST);
List l = new ArrayList(3);
l.add((long) ctx.getDocList().matches());
l.add((long) ctx.getDocList().offset());
Float maxScore = null;
if (ctx.wantsScores()) {
maxScore = ctx.getDocList().maxScore();
}
l.add(maxScore);
codec.writeArray(l);
// this is a seprate function so that streaming responses can use just that part
writeResultsBody( ctx, codec );
}
}
/**
* TODO -- there may be a way to do this without marshal at all...
*
* @return a response object equivalent to what you get from the XML/JSON/javabin parser. Documents become
* SolrDocuments, DocList becomes SolrDocumentList etc.
*
* @since solr 1.4
*/
@SuppressWarnings("unchecked")
public static NamedList