Design Principal: SolrParams defines common behavior, but doesn't defines how it should be implemented - the data structure SolrParams uses.
SolrParams.wrapDefaults wraps 2 SolrParams, one additional default SolrParams, if get(name) can't find value in the first map, it will get value from the default SolrParams.
In org.apache.solr.handler.RequestHandlerBase.handleRequestBody(SolrQueryRequest, SolrQueryResponse), it will wrap params from request, and add defaults,appends and invariant params from the request handler in solrconfig.xml.
In org.apache.solr.handler.RequestHandlerBase.init(NamedList), it reads params in defaults section into variable defaults, params in appends section into variable appends, params in invariants section into variable invariants, .
In org.apache.solr.handler.RequestHandlerBase.handleRequest(SolrQueryRequest, SolrQueryResponse), it wraps defaults,appends,invariants into SolrParams in request.
SolrPluginUtils.setDefaults(req,defaults,appends,invariants);
Example like below:
<requestHandler name="/update/asyncXML" class="solr.AsyncXmlUpdateRequestHandler"> <str name="unique_field_name">contentid</str> <str name="clientId_param_name">clientId</str> <lst name="defaults"> <str name="update.contentType">application/xml</str> </lst> </requestHandler>The SolrParams in a RequestHandler.handleRequestBody is a DefaultSolrParams, through it, you can get the key/value paris in solrconfig.xml.
NamedList
In the NamedList in RequestHandler.init() method, if you want to access the value defined in defaults section, you can:
1. run super.init(args);, which will read defaults section into variable defaults SolrParams, then you can: defaults.get("update.contentType");
2. Or you can NamedList<Object> defautNl = args.get("defaults"); then read defautNl.
If you run SolrParams params = SolrParams.toSolrParams(args); the SolrParams is MapSolrParams, not a DefaultSolrParams, this means it doesn't wrap normal configuration, defaults,appends,invariants into one SolrParams. If you run params.get("update.contentType"); it will return null.
Change SolrParams in a request
ModifiableSolrParams newParams = new ModifiableSolrParams(req.getParams());
req.setParams(newParams);
Set Content Type
1. Set default content stream type for a request handler in solrconfig.xml:
<lst name="defaults">
<str name="update.contentType">application/xml</str>
</lst>
2. Set default content stream type for a request handler in code.
In init(NamedList) method of the requestHandler.
setAssumeContentType("application/xml");
3. Set content stream type in url:
&stream.contentType=application/xml
How SolrParams is created:
org.apache.solr.servlet.SolrRequestParsers.parseQueryString(String, Map<String, String[]>) // this input stream emulates to get the raw bytes from the URL as passed to servlet container, it disallows any byte > 127 and enforces to %-escape them: final InputStream in = new InputStream() { int pos = 0; @Override public int read() { if (pos < len) { final char ch = queryString.charAt(pos); if (ch > 127) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "URLDecoder: The query string contains a not-%-escaped byte > 127 at position " + pos); } pos++; return ch; } else { return -1; } } };SolrRequestParsers converts the queryString into an InputStream..
In SolrRequestParsers.parseFormDataContent(InputStream, long, Charset, Map<String, String[]>), read the InputStream, use currentStreamcurrentStream to switch between 2 ByteArrayOutputStream2: keyStream, valueStream. Handle these special characters: &, =, %, +.
/** Makes the buffer of ByteArrayOutputStream available without copy. */ static final class ByteArrayOutputStream2 extends ByteArrayOutputStream { byte[] buffer() { return buf; } }