Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.servlet;
import javax.servlet.MultipartConfigElement;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.input.CloseShieldInputStream;
import org.apache.lucene.util.IOUtils;
import org.apache.solr.api.V2HttpCall;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MultiMapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.CommandOperation;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.common.util.FastInputStream;
import org.apache.solr.core.RequestHandlers;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryRequestBase;
import org.apache.solr.util.RTimerTree;
import org.apache.solr.util.tracing.GlobalTracer;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.MultiParts;
import org.eclipse.jetty.server.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.solr.common.params.CommonParams.PATH;
public class SolrRequestParsers {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
// Should these constants be in a more public place?
public static final String MULTIPART = "multipart";
public static final String FORMDATA = "formdata";
public static final String RAW = "raw";
public static final String SIMPLE = "simple";
public static final String STANDARD = "standard";
private static final Charset CHARSET_US_ASCII = Charset.forName("US-ASCII");
public static final String INPUT_ENCODING_KEY = "ie";
private static final byte[] INPUT_ENCODING_BYTES = INPUT_ENCODING_KEY.getBytes(CHARSET_US_ASCII);
public static final String REQUEST_TIMER_SERVLET_ATTRIBUTE = "org.apache.solr.RequestTimer";
private final HashMap parsers =
new HashMap<>();
private final boolean enableRemoteStreams;
private final boolean enableStreamBody;
private StandardRequestParser standard;
private boolean handleSelect = true;
private boolean addHttpRequestToContext;
/** Default instance for e.g. admin requests. Limits to 2 MB uploads and does not allow remote streams. */
public static final SolrRequestParsers DEFAULT = new SolrRequestParsers();
/**
* Pass in an xml configuration. A null configuration will enable
* everything with maximum values.
*/
public SolrRequestParsers( SolrConfig globalConfig ) {
final int multipartUploadLimitKB, formUploadLimitKB;
if( globalConfig == null ) {
multipartUploadLimitKB = formUploadLimitKB = Integer.MAX_VALUE;
enableRemoteStreams = false;
enableStreamBody = false;
handleSelect = false;
addHttpRequestToContext = false;
} else {
multipartUploadLimitKB = globalConfig.getMultipartUploadLimitKB();
formUploadLimitKB = globalConfig.getFormUploadLimitKB();
enableRemoteStreams = globalConfig.isEnableRemoteStreams();
enableStreamBody = globalConfig.isEnableStreamBody();
// Let this filter take care of /select?xxx format
handleSelect = globalConfig.isHandleSelect();
addHttpRequestToContext = globalConfig.isAddHttpRequestToContext();
}
init(multipartUploadLimitKB, formUploadLimitKB);
}
private SolrRequestParsers() {
enableRemoteStreams = false;
enableStreamBody = false;
handleSelect = false;
addHttpRequestToContext = false;
init(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
private void init( int multipartUploadLimitKB, int formUploadLimitKB) {
MultipartRequestParser multi = new MultipartRequestParser( multipartUploadLimitKB );
RawRequestParser raw = new RawRequestParser();
FormDataRequestParser formdata = new FormDataRequestParser( formUploadLimitKB );
standard = new StandardRequestParser( multi, raw, formdata );
// I don't see a need to have this publicly configured just yet
// adding it is trivial
parsers.put( MULTIPART, multi );
parsers.put( FORMDATA, formdata );
parsers.put( RAW, raw );
parsers.put( SIMPLE, new SimpleRequestParser() );
parsers.put( STANDARD, standard );
parsers.put( "", standard );
}
private static RTimerTree getRequestTimer(HttpServletRequest req)
{
final Object reqTimer = req.getAttribute(REQUEST_TIMER_SERVLET_ATTRIBUTE);
if (reqTimer != null && reqTimer instanceof RTimerTree) {
return ((RTimerTree) reqTimer);
}
return new RTimerTree();
}
public SolrQueryRequest parse( SolrCore core, String path, HttpServletRequest req ) throws Exception
{
SolrRequestParser parser = standard;
// TODO -- in the future, we could pick a different parser based on the request
// Pick the parser from the request...
ArrayList streams = new ArrayList<>(1);
SolrParams params = parser.parseParamsAndFillStreams( req, streams );
if (GlobalTracer.get().tracing()) {
GlobalTracer.getTracer().activeSpan().setTag("params", params.toString());
}
SolrQueryRequest sreq = buildRequestFrom(core, params, streams, getRequestTimer(req), req);
// Handlers and login will want to know the path. If it contains a ':'
// the handler could use it for RESTful URLs
sreq.getContext().put(PATH, RequestHandlers.normalize(path));
sreq.getContext().put("httpMethod", req.getMethod());
if(addHttpRequestToContext) {
sreq.getContext().put("httpRequest", req);
}
return sreq;
}
public SolrQueryRequest buildRequestFrom(SolrCore core, SolrParams params, Collection streams) throws Exception {
return buildRequestFrom(core, params, streams, new RTimerTree(), null);
}
private SolrQueryRequest buildRequestFrom(SolrCore core, SolrParams params, Collection streams,
RTimerTree requestTimer, final HttpServletRequest req) throws Exception {
// The content type will be applied to all streaming content
String contentType = params.get( CommonParams.STREAM_CONTENTTYPE );
// Handle anything with a remoteURL
String[] strs = params.getParams( CommonParams.STREAM_URL );
if( strs != null ) {
if( !enableRemoteStreams ) {
throw new SolrException( ErrorCode.BAD_REQUEST, "Remote Streaming is disabled." );
}
for( final String url : strs ) {
ContentStreamBase stream = new ContentStreamBase.URLStream( new URL(url) );
if( contentType != null ) {
stream.setContentType( contentType );
}
streams.add( stream );
}
}
// Handle streaming files
strs = params.getParams( CommonParams.STREAM_FILE );
if( strs != null ) {
if( !enableRemoteStreams ) {
throw new SolrException( ErrorCode.BAD_REQUEST, "Remote Streaming is disabled. See http://lucene.apache.org/solr/guide/requestdispatcher-in-solrconfig.html for help" );
}
for( final String file : strs ) {
ContentStreamBase stream = new ContentStreamBase.FileStream( new File(file) );
if( contentType != null ) {
stream.setContentType( contentType );
}
streams.add( stream );
}
}
// Check for streams in the request parameters
strs = params.getParams( CommonParams.STREAM_BODY );
if( strs != null ) {
if( !enableStreamBody ) {
throw new SolrException( ErrorCode.BAD_REQUEST, "Stream Body is disabled. See http://lucene.apache.org/solr/guide/requestdispatcher-in-solrconfig.html for help" );
}
for( final String body : strs ) {
ContentStreamBase stream = new ContentStreamBase.StringStream( body );
if( contentType != null ) {
stream.setContentType( contentType );
}
streams.add( stream );
}
}
final HttpSolrCall httpSolrCall = req == null ? null : (HttpSolrCall) req.getAttribute(HttpSolrCall.class.getName());
SolrQueryRequestBase q = new SolrQueryRequestBase(core, params, requestTimer) {
@Override
public Principal getUserPrincipal() {
return req == null ? null : req.getUserPrincipal();
}
@Override
public List getCommands(boolean validateInput) {
if (httpSolrCall != null) {
return httpSolrCall.getCommands(validateInput);
}
return super.getCommands(validateInput);
}
@Override
public Map getPathTemplateValues() {
if (httpSolrCall != null && httpSolrCall instanceof V2HttpCall) {
return ((V2HttpCall) httpSolrCall).getUrlParts();
}
return super.getPathTemplateValues();
}
@Override
public HttpSolrCall getHttpSolrCall() {
return httpSolrCall;
}
};
if( streams != null && streams.size() > 0 ) {
q.setContentStreams( streams );
}
return q;
}
private static HttpSolrCall getHttpSolrCall(HttpServletRequest req) {
return req == null ? null : (HttpSolrCall) req.getAttribute(HttpSolrCall.class.getName());
}
/**
* Given a url-encoded query string (UTF-8), map it into solr params
*/
public static MultiMapSolrParams parseQueryString(String queryString) {
Map map = new HashMap<>();
parseQueryString(queryString, map);
return new MultiMapSolrParams(map);
}
/**
* Given a url-encoded query string (UTF-8), map it into the given map
* @param queryString as given from URL
* @param map place all parameters in this map
*/
static void parseQueryString(final String queryString, final Map map) {
if (queryString != null && queryString.length() > 0) {
try {
final int len = queryString.length();
// 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(ErrorCode.BAD_REQUEST, "URLDecoder: The query string contains a not-%-escaped byte > 127 at position " + pos);
}
pos++;
return ch;
} else {
return -1;
}
}
};
parseFormDataContent(in, Long.MAX_VALUE, StandardCharsets.UTF_8, map, true);
} catch (IOException ioe) {
throw new SolrException(ErrorCode.BAD_REQUEST, ioe);
}
}
}
/**
* Given a url-encoded form from POST content (as InputStream), map it into the given map.
* The given InputStream should be buffered!
* @param postContent to be parsed
* @param charset to be used to decode resulting bytes after %-decoding
* @param map place all parameters in this map
*/
@SuppressWarnings({"fallthrough", "resource"})
static long parseFormDataContent(final InputStream postContent, final long maxLen, Charset charset, final Map map, boolean supportCharsetParam) throws IOException {
CharsetDecoder charsetDecoder = supportCharsetParam ? null : getCharsetDecoder(charset);
final LinkedList