This commit is contained in:
Cao Manh Dat 2017-05-18 11:24:58 +07:00
commit 896270d132
63 changed files with 1718 additions and 594 deletions

View File

@ -93,7 +93,6 @@ Other
(Daniel Jelinski via Adrien Grand)
======================= Lucene 6.7.0 =======================
(No Changes)
======================= Lucene 6.6.0 =======================
@ -134,6 +133,11 @@ Bug Fixes
* LUCENE-7824: Fix graph query analysis for multi-word synonym rules with common terms (eg. new york, new york city).
(Jim Ferenczi)
* LUCENE-7817: Pass cached query to onQueryCache instead of null.
(Christoph Kaser via Adrien Grand)
* LUCENE-7831: CodecUtil should not seek to negative offsets. (Adrien Grand)
Improvements
* LUCENE-7782: OfflineSorter now passes the total number of items it

View File

@ -331,6 +331,9 @@ public final class CodecUtil {
/** Retrieves the full footer from the provided {@link IndexInput}. This throws
* {@link CorruptIndexException} if this file does not have a valid footer. */
public static byte[] readFooter(IndexInput in) throws IOException {
if (in.length() < footerLength()) {
throw new CorruptIndexException("misplaced codec footer (file truncated?): length=" + in.length() + " but footerLength==" + footerLength(), in);
}
in.seek(in.length() - footerLength());
validateFooter(in);
in.seek(in.length() - footerLength());
@ -516,6 +519,9 @@ public final class CodecUtil {
clone.seek(0);
ChecksumIndexInput in = new BufferedChecksumIndexInput(clone);
assert in.getFilePointer() == 0;
if (in.length() < footerLength()) {
throw new CorruptIndexException("misplaced codec footer (file truncated?): length=" + in.length() + " but footerLength==" + footerLength(), input);
}
in.seek(in.length() - footerLength());
return checkFooter(in);
}

View File

@ -303,4 +303,17 @@ public class TestCodecUtil extends LuceneTestCase {
fakeChecksum.set((1L << 32) - 1); // ok
CodecUtil.writeCRC(fakeOutput);
}
public void testTruncatedFileThrowsCorruptIndexException() throws IOException {
RAMFile file = new RAMFile();
IndexOutput output = new RAMOutputStream(file, false);
output.close();
IndexInput input = new RAMInputStream("file", file);
CorruptIndexException e = expectThrows(CorruptIndexException.class,
() -> CodecUtil.checksumEntireFile(input));
assertEquals("misplaced codec footer (file truncated?): length=0 but footerLength==16 (resource=RAMInputStream(name=file))", e.getMessage());
e = expectThrows(CorruptIndexException.class,
() -> CodecUtil.retrieveChecksum(input));
assertEquals("misplaced codec footer (file truncated?): length=0 but footerLength==16 (resource=RAMInputStream(name=file))", e.getMessage());
}
}

View File

@ -70,6 +70,9 @@ Upgrading from Solr 6.x
query text will not be split on whitespace before analysis. See
https://lucidworks.com/2017/04/18/multi-word-synonyms-solr-adds-query-time-support/ .
* Setting <solrQueryParser defaultOperator="..."/> in schema is no longer allowed and will cause an exception.
Please use "q.op" parameter on the request instead. For more details, see SOLR-10584.
New Features
----------------------
* SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@ -102,7 +105,7 @@ Bug Fixes
* SOLR-10408: v2 API introspect should return useful message for non-existent command (Cao Manh Dat)
* SOLR-10411: v2 Collection API "modify" command specification's replicationFactor property is incorrectly typed as string,
* SOLR-10411: v2 Collection API "modify" command specification's replicationFactor property is incorrectly typed as string,
should be integer (Cao Manh Dat)
* SOLR-10405: v2 API introspect response contains multiple copies of the experimental format WARNING (Cao Manh Dat)
@ -128,6 +131,7 @@ Optimizations
(yonik)
Other Changes
----------------------
* SOLR-10236: Removed FieldType.getNumericType(). Use getNumberType() instead. (Tomás Fernández Löbbe)
* SOLR-10347: Removed index level boost support from "documents" section of the admin UI (Amrit Sarkar via
@ -148,6 +152,11 @@ Other Changes
* SOLR-10647: Move the V1 <-> V2 API mapping to SolrJ (noble)
* SOLR-10584: We'll now always throw an exception if defaultOperator is found in schema. This config has
been deprecated since 3.6, and enforced for new configs since 6.6 (janhoy)
* SOLR-10414: RecoveryStrategy is now a Runnable instead of a Thread. (Tomás Fernández Löbbe)
================== 6.7.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
@ -164,13 +173,18 @@ Jetty 9.3.14.v20161028
Detailed Change List
----------------------
New Features
----------------------
* SOLR-10307: Allow Passing SSL passwords through environment variables. (Mano Kovacs via Mark Miller)
Other Changes
----------------------
* SOLR-10617: JDBCStream accepts columns of type TIME, DATE & TIMESTAMP as well as CLOBs and decimal
numeric types (James Dyer)
* SOLR-10400: Replace (instanceof TrieFooField || instanceof FooPointField) constructs with
* SOLR-10400: Replace (instanceof TrieFooField || instanceof FooPointField) constructs with
FieldType.getNumberType() or SchemaField.getSortField() where appropriate. (hossman, Steve Rowe)
================== 6.6.0 ==================
@ -361,9 +375,9 @@ Bug Fixes
* SOLR-10549: The new 'large' attribute had been forgotten in /schema/fieldtypes?showDefaults=true (David Smiley)
* SOLR-10615: requests are suspended until SolrDispatchFilter initialization is completed.
After core container shutdown or severe initialization problem Solr responds with
http stauts 404 Not Found instead of 500 as it was before (Mikhail Khludnev)
* SOLR-10615: requests are suspended until SolrDispatchFilter initialization is completed.
After core container shutdown or severe initialization problem Solr responds with
http stauts 404 Not Found instead of 500 as it was before (Mikhail Khludnev)
* SOLR-8149: Admin UI - Plugins / Stats - active item is now highlighted (Labuzov Dmitriy via janhoy)
@ -438,9 +452,9 @@ Other Changes
* SOLR-10601: StreamExpressionParser should handle white space around = in named parameters (Joel Bernstein)
* SOLR-10614: Static fields have turned to instance's field in SimplePostTool.
* SOLR-10614: Static fields have turned to instance's field in SimplePostTool.
Enabled TestSolrCLIRunExample.testTechproductsExample(). (Andrey Kudryavtsev, Mikhail Khludnev)
* SOLR-10522: Revert SpellCheckComponent response format change from SOLR-9972 (rel. 6.5.0). While this
was an improvement for the json "arrntv" format, it caused problems for the default json format.
(James Dyer, reported by Nikita Pchelintsev)

View File

@ -251,9 +251,9 @@ solr_uid="`id -u "$SOLR_USER"`"
if [ $? -ne 0 ]; then
echo "Creating new user: $SOLR_USER"
if [ "$distro" == "RedHat" ] || [ "$distro" == "CentOS" ] ; then
adduser "$SOLR_USER"
adduser --system -U -m --home-dir "$SOLR_VAR_DIR" "$SOLR_USER"
elif [ "$distro" == "SUSE" ]; then
useradd -m "$SOLR_USER"
useradd --system -U -m --home-dir "$SOLR_VAR_DIR" "$SOLR_USER"
else
adduser --system --shell /bin/bash --group --disabled-password --home "$SOLR_VAR_DIR" "$SOLR_USER"
fi
@ -331,8 +331,8 @@ SOLR_LOGS_DIR=\"$SOLR_VAR_DIR/logs\"
SOLR_PORT=\"$SOLR_PORT\"
" >> "/etc/default/$SOLR_SERVICE.in.sh"
fi
chown ${SOLR_USER}: "/etc/default/$SOLR_SERVICE.in.sh"
chmod 0660 "/etc/default/$SOLR_SERVICE.in.sh"
chown root:${SOLR_USER} "/etc/default/$SOLR_SERVICE.in.sh"
chmod 0640 "/etc/default/$SOLR_SERVICE.in.sh"
# install data directories and files
mkdir -p "$SOLR_VAR_DIR/data"

View File

@ -163,13 +163,20 @@ fi
SOLR_URL_SCHEME=http
SOLR_JETTY_CONFIG=()
SOLR_SSL_OPTS=""
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
if [ -z "$SOLR_SSL_ENABLED" ]; then
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_ENABLED="true" # implicitly from earlier behaviour
else
SOLR_SSL_ENABLED="false"
fi
fi
if [ "$SOLR_SSL_ENABLED" == "true" ]; then
SOLR_JETTY_CONFIG+=("--module=https")
SOLR_URL_SCHEME=https
SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore=$SOLR_SSL_KEY_STORE"
if [ -n "$SOLR_SSL_KEY_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore.password=$SOLR_SSL_KEY_STORE_PASSWORD"
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore=$SOLR_SSL_KEY_STORE"
fi
if [ -n "$SOLR_SSL_KEY_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore.type=$SOLR_SSL_KEY_STORE_TYPE"
fi
@ -177,9 +184,6 @@ if [ -n "$SOLR_SSL_KEY_STORE" ]; then
if [ -n "$SOLR_SSL_TRUST_STORE" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.truststore=$SOLR_SSL_TRUST_STORE"
fi
if [ -n "$SOLR_SSL_TRUST_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.truststore.password=$SOLR_SSL_TRUST_STORE_PASSWORD"
fi
if [ -n "$SOLR_SSL_TRUST_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.truststore.type=$SOLR_SSL_TRUST_STORE_TYPE"
fi
@ -194,9 +198,6 @@ if [ -n "$SOLR_SSL_KEY_STORE" ]; then
if [ -n "$SOLR_SSL_CLIENT_KEY_STORE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStore=$SOLR_SSL_CLIENT_KEY_STORE"
if [ -n "$SOLR_SSL_CLIENT_KEY_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStorePassword=$SOLR_SSL_CLIENT_KEY_STORE_PASSWORD"
fi
if [ -n "$SOLR_SSL_CLIENT_KEY_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStoreType=$SOLR_SSL_CLIENT_KEY_STORE_TYPE"
fi
@ -204,9 +205,6 @@ if [ -n "$SOLR_SSL_KEY_STORE" ]; then
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStore=$SOLR_SSL_KEY_STORE"
fi
if [ -n "$SOLR_SSL_KEY_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStorePassword=$SOLR_SSL_KEY_STORE_PASSWORD"
fi
if [ -n "$SOLR_SSL_KEY_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStoreType=$SOLR_SSL_KEYSTORE_TYPE"
fi
@ -215,10 +213,6 @@ if [ -n "$SOLR_SSL_KEY_STORE" ]; then
if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStore=$SOLR_SSL_CLIENT_TRUST_STORE"
if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStorePassword=$SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD"
fi
if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStoreType=$SOLR_SSL_CLIENT_TRUST_STORE_TYPE"
fi
@ -227,10 +221,6 @@ if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStore=$SOLR_SSL_TRUST_STORE"
fi
if [ -n "$SOLR_SSL_TRUST_STORE_PASSWORD" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStorePassword=$SOLR_SSL_TRUST_STORE_PASSWORD"
fi
if [ -n "$SOLR_SSL_TRUST_STORE_TYPE" ]; then
SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStoreType=$SOLR_SSL_TRUST_STORE_TYPE"
fi
@ -294,7 +284,7 @@ function print_usage() {
if [ -z "$CMD" ]; then
echo ""
echo "Usage: solr COMMAND OPTIONS"
echo " where COMMAND is one of: start, stop, restart, status, healthcheck, create, create_core, create_collection, delete, version, zk"
echo " where COMMAND is one of: start, stop, restart, status, healthcheck, create, create_core, create_collection, delete, version, zk, auth"
echo ""
echo " Standalone server example (start Solr running in the background on port 8984):"
echo ""
@ -544,6 +534,35 @@ function print_usage() {
echo " <path>: The Zookeeper path to create. Leading slash is assumed if not present."
echo " Intermediate nodes are created as needed if not present."
echo ""
elif [ "$CMD" == "auth" ]; then
echo ""
echo "Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown <true|false>] [-updateIncludeFileOnly <true|false>]"
echo " solr auth enable [-type basicAuth] -prompt <true|false> [-blockUnknown <true|false>] [-updateIncludeFileOnly <true|false>]"
echo " solr auth disable [-updateIncludeFileOnly <true|false>]"
echo ""
echo " -type <type> The authentication mechanism to enable. Defaults to 'basicAuth'."
echo ""
echo " -credentials <user:pass> The username and password of the initial user"
echo " Note: only one of -prompt or -credentials must be provided"
echo ""
echo " -prompt <true|false> Prompts the user to provide the credentials"
echo " Note: only one of -prompt or -credentials must be provided"
echo ""
echo " -blockUnknown <true|false> When true, this blocks out access to unauthenticated users. When not provided,"
echo " this defaults to false (i.e. unauthenticated users can access all endpoints, except the"
echo " operations like collection-edit, security-edit, core-admin-edit etc.). Check the reference"
echo " guide for Basic Authentication for more details."
echo ""
echo " -updateIncludeFileOnly <true|false> Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling"
echo " authentication (i.e. don't update security.json)"
echo ""
echo " -z zkHost Zookeeper connection string"
echo ""
echo " -d <dir> Specify the Solr server directory"
echo ""
echo " -s <dir> Specify the Solr home directory. This is where any credentials or authentication"
echo " configuration files (e.g. basicAuth.conf) would be placed."
echo ""
fi
} # end print_usage
@ -1187,19 +1206,130 @@ if [[ "$SCRIPT_CMD" == "zk" ]]; then
fi
if [[ "$SCRIPT_CMD" == "auth" ]]; then
if [ -z "$AUTH_PORT" ]; then
for ID in `ps auxww | grep java | grep start\.jar | awk '{print $2}' | sort -r`
do
port=`jetty_port "$ID"`
if [ "$port" != "" ]; then
AUTH_PORT=$port
declare -a AUTH_PARAMS
if [ $# -gt 0 ]; then
while true; do
case "$1" in
enable|disable)
AUTH_OP=$1
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "$AUTH_OP")
shift
;;
-z|-zkhost|zkHost)
ZK_HOST="$2"
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-zkHost" "$ZK_HOST")
shift 2
;;
-t|-type)
AUTH_TYPE="$2"
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-type" "$AUTH_TYPE")
shift 2
;;
-credentials)
AUTH_CREDENTIALS="$2"
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-credentials" "$AUTH_CREDENTIALS")
shift 2
;;
-solrIncludeFile)
SOLR_INCLUDE="$2"
shift 2
;;
-prompt)
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-prompt" "$2")
shift
;;
-blockUnknown)
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-blockUnknown" "$2")
shift
break
fi
done
;;
-updateIncludeFileOnly)
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-updateIncludeFileOnly" "$2")
shift
break
;;
-d|-dir)
if [[ -z "$2" || "${2:0:1}" == "-" ]]; then
print_usage "$SCRIPT_CMD" "Server directory is required when using the $1 option!"
exit 1
fi
if [[ "$2" == "." || "$2" == "./" || "$2" == ".." || "$2" == "../" ]]; then
SOLR_SERVER_DIR="$(pwd)/$2"
else
# see if the arg value is relative to the tip vs full path
if [[ "$2" != /* ]] && [[ -d "$SOLR_TIP/$2" ]]; then
SOLR_SERVER_DIR="$SOLR_TIP/$2"
else
SOLR_SERVER_DIR="$2"
fi
fi
# resolve it to an absolute path
SOLR_SERVER_DIR="$(cd "$SOLR_SERVER_DIR"; pwd)"
shift 2
;;
-s|-solr.home)
if [[ -z "$2" || "${2:0:1}" == "-" ]]; then
print_usage "$SCRIPT_CMD" "Solr home directory is required when using the $1 option!"
exit 1
fi
SOLR_HOME="$2"
shift 2
;;
-help|-usage|-h)
print_usage "$SCRIPT_CMD"
exit 0
;;
--)
shift
break
;;
*)
shift
break
;;
esac
done
fi
if [ -z "$SOLR_SERVER_DIR" ]; then
SOLR_SERVER_DIR="$DEFAULT_SERVER_DIR"
fi
if [ ! -e "$SOLR_SERVER_DIR" ]; then
echo -e "\nSolr server directory $SOLR_SERVER_DIR not found!\n"
exit 1
fi
if [ -z "$SOLR_HOME" ]; then
SOLR_HOME="$SOLR_SERVER_DIR/solr"
else
if [[ $SOLR_HOME != /* ]] && [[ -d "$SOLR_SERVER_DIR/$SOLR_HOME" ]]; then
SOLR_HOME="$SOLR_SERVER_DIR/$SOLR_HOME"
SOLR_PID_DIR="$SOLR_HOME"
elif [[ $SOLR_HOME != /* ]] && [[ -d "`pwd`/$SOLR_HOME" ]]; then
SOLR_HOME="$(pwd)/$SOLR_HOME"
fi
solr_include_file=$SOLR_INCLUDE
run_tool auth "$@" -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$AUTH_PORT/solr" -solrIncludeFile "$solr_include_file"
exit $?
fi
if [ -z "$AUTH_OP" ]; then
print_usage "$SCRIPT_CMD"
exit 0
fi
AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-solrIncludeFile" "$SOLR_INCLUDE")
if [ -z "$AUTH_PORT" ]; then
for ID in `ps auxww | grep java | grep start\.jar | awk '{print $2}' | sort -r`
do
port=`jetty_port "$ID"`
if [ "$port" != "" ]; then
AUTH_PORT=$port
break
fi
done
fi
run_tool auth ${AUTH_PARAMS[@]} -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$AUTH_PORT/solr" -authConfDir "$SOLR_HOME"
exit $?
fi
@ -1696,7 +1826,7 @@ function launch_solr() {
# If SSL-related system props are set, add them to SOLR_OPTS
if [ -n "$SOLR_SSL_OPTS" ]; then
if [ "$SOLR_SSL_ENABLED" ]; then
# If using SSL and solr.jetty.https.port not set explicitly, use the jetty.port
SSL_PORT_PROP="-Dsolr.jetty.https.port=$SOLR_PORT"
SOLR_OPTS+=($SOLR_SSL_OPTS "$SSL_PORT_PROP")

View File

@ -42,13 +42,21 @@ REM Select HTTP OR HTTPS related configurations
set SOLR_URL_SCHEME=http
set "SOLR_JETTY_CONFIG=--module=http"
set "SOLR_SSL_OPTS= "
IF DEFINED SOLR_SSL_KEY_STORE (
IF NOT DEFINED SOLR_SSL_ENABLED (
IF DEFINED SOLR_SSL_KEY_STORE (
set "SOLR_SSL_ENABLED=true"
) ELSE (
set "SOLR_SSL_ENABLED=false"
)
)
IF "%SOLR_SSL_ENABLED%"=="true" (
set "SOLR_JETTY_CONFIG=--module=https"
set SOLR_URL_SCHEME=https
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore=%SOLR_SSL_KEY_STORE%"
IF DEFINED SOLR_SSL_KEY_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore.password=%SOLR_SSL_KEY_STORE_PASSWORD%"
IF DEFINED SOLR_SSL_KEY_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore=%SOLR_SSL_KEY_STORE%"
)
IF DEFINED SOLR_SSL_KEY_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore.type=%SOLR_SSL_KEY_STORE_TYPE%"
)
@ -56,9 +64,6 @@ IF DEFINED SOLR_SSL_KEY_STORE (
IF DEFINED SOLR_SSL_TRUST_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore=%SOLR_SSL_TRUST_STORE%"
)
IF DEFINED SOLR_SSL_TRUST_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore.password=%SOLR_SSL_TRUST_STORE_PASSWORD%"
)
IF DEFINED SOLR_SSL_TRUST_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore.type=%SOLR_SSL_TRUST_STORE_TYPE%"
)
@ -73,9 +78,6 @@ IF DEFINED SOLR_SSL_KEY_STORE (
IF DEFINED SOLR_SSL_CLIENT_KEY_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_CLIENT_KEY_STORE%"
IF DEFINED SOLR_SSL_CLIENT_KEY_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStorePassword=%SOLR_SSL_CLIENT_KEY_STORE_PASSWORD%"
)
IF DEFINED SOLR_SSL_CLIENT_KEY_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_CLIENT_KEY_STORE_TYPE%"
)
@ -83,9 +85,6 @@ IF DEFINED SOLR_SSL_KEY_STORE (
IF DEFINED SOLR_SSL_KEY_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_KEY_STORE%"
)
IF DEFINED SOLR_SSL_KEY_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStorePassword=%SOLR_SSL_KEY_STORE_PASSWORD%"
)
IF DEFINED SOLR_SSL_KEY_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_KEY_STORE_TYPE%"
)
@ -94,10 +93,6 @@ IF DEFINED SOLR_SSL_KEY_STORE (
IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_CLIENT_TRUST_STORE%"
IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStorePassword=%SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD%"
)
IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_CLIENT_TRUST_STORE_TYPE%"
)
@ -105,9 +100,6 @@ IF DEFINED SOLR_SSL_KEY_STORE (
IF DEFINED SOLR_SSL_TRUST_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_TRUST_STORE%"
)
IF DEFINED SOLR_SSL_TRUST_STORE_PASSWORD (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStorePassword=%SOLR_SSL_TRUST_STORE_PASSWORD%"
)
IF DEFINED SOLR_SSL_TRUST_STORE_TYPE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_TRUST_STORE_TYPE%"
)
@ -276,7 +268,7 @@ goto done
:script_usage
@echo.
@echo Usage: solr COMMAND OPTIONS
@echo where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete, version, zk
@echo where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete, version, zk, auth
@echo.
@echo Standalone server example (start Solr running in the background on port 8984):
@echo.
@ -554,6 +546,35 @@ IF "%ZK_FULL%"=="true" (
)
goto done
:auth_usage
echo Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown ^<true|false^>] [-updateIncludeFileOnly ^<true|false^>]
echo solr auth enable [-type basicAuth] -prompt ^<true|false^> [-blockUnknown ^<true|false^>] [-updateIncludeFileOnly ^<true|false^>]
echo solr auth disable [-updateIncludeFileOnly ^<true|false^>]
echo
echo -type ^<type^> The authentication mechanism to enable. Defaults to 'basicAuth'.
echo
echo -credentials ^<user:pass^> The username and password of the initial user
echo Note: only one of -prompt or -credentials must be provided
echo
echo -prompt ^<true|false^> Prompts the user to provide the credentials
echo Note: only one of -prompt or -credentials must be provided
echo
echo -blockUnknown ^<true|false^> When true, this blocks out access to unauthenticated users. When not provided,
echo this defaults to false (i.e. unauthenticated users can access all endpoints, except the
echo operations like collection-edit, security-edit, core-admin-edit etc.). Check the reference
echo guide for Basic Authentication for more details.
echo
echo -updateIncludeFileOnly ^<true|false^> Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling"
echo authentication (i.e. don't update security.json)"
echo
echo -z zkHost Zookeeper connection string
echo
echo -d <dir> Specify the Solr server directory"
echo
echo -s <dir> Specify the Solr home directory. This is where any credentials or authentication"
echo configuration files (e.g. basicAuth.conf) would be placed."
echo
goto done
REM Really basic command-line arg parsing
:parse_args
@ -1110,7 +1131,7 @@ IF NOT "%REMOTE_JMX_OPTS%"=="" set "START_OPTS=%START_OPTS% %REMOTE_JMX_OPTS%"
IF NOT "%SOLR_ADDL_ARGS%"=="" set "START_OPTS=%START_OPTS% %SOLR_ADDL_ARGS%"
IF NOT "%SOLR_HOST_ARG%"=="" set "START_OPTS=%START_OPTS% %SOLR_HOST_ARG%"
IF NOT "%SOLR_OPTS%"=="" set "START_OPTS=%START_OPTS% %SOLR_OPTS%"
IF NOT "%SOLR_SSL_OPTS%"=="" (
IF "%SOLR_SSL_ENABLED%"=="true" (
set "SSL_PORT_PROP=-Dsolr.jetty.https.port=%SOLR_PORT%"
set "START_OPTS=%START_OPTS% %SOLR_SSL_OPTS% !SSL_PORT_PROP!"
)
@ -1648,6 +1669,44 @@ goto done
:run_auth
IF "%1"=="-help" goto usage
IF "%1"=="-usage" goto usage
REM Options parsing.
REM Note: With the following technique of parsing, it is not possible
REM to have an option without a value.
set "AUTH_PARAMS=%1"
set "option="
for %%a in (%*) do (
if not defined option (
set arg=%%a
if "!arg:~0,1!" equ "-" set "option=!arg!"
) else (
set "option!option!=%%a"
if "!option!" equ "-d" set "SOLR_SERVER_DIR=%%a"
if "!option!" equ "-s" set "SOLR_HOME=%%a"
if not "!option!" equ "-s" if not "!option!" equ "-d" (
set "AUTH_PARAMS=!AUTH_PARAMS! !option! %%a"
)
set "option="
)
)
IF "%SOLR_SERVER_DIR%"=="" set "SOLR_SERVER_DIR=%DEFAULT_SERVER_DIR%"
IF NOT EXIST "%SOLR_SERVER_DIR%" (
set "SCRIPT_ERROR=Solr server directory %SOLR_SERVER_DIR% not found!"
goto err
)
IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr"
IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%"
IF NOT EXIST "%SOLR_HOME%\" (
IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" (
set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%"
) ELSE (
set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!"
goto err
)
)
if "!AUTH_PORT!"=="" (
for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do (
set SOME_SOLR_PORT=
@ -1659,11 +1718,10 @@ if "!AUTH_PORT!"=="" (
)
)
)
for /f "tokens=1,* delims= " %%a in ("%*") do set auth_params=%%b
"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^
-Dlog4j.configuration="file:%DEFAULT_SERVER_DIR%\scripts\cloud-scripts\log4j.properties" ^
-classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^
org.apache.solr.util.SolrCLI auth %auth_params% -solrIncludeFile "%SOLR_INCLUDE%" ^
org.apache.solr.util.SolrCLI auth %AUTH_PARAMS% -solrIncludeFile "%SOLR_INCLUDE%" -authConfDir "%SOLR_HOME%" ^
-solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!AUTH_PORT!/solr
goto done

View File

@ -87,6 +87,9 @@ REM set SOLR_JETTY_HOST=0.0.0.0
REM Sets the port Solr binds to, default is 8983
REM set SOLR_PORT=8983
REM Enables HTTPS. It is implictly true if you set SOLR_SSL_KEY_STORE. Use this config
REM to enable https module with custom jetty configuration.
REM set SOLR_SSL_ENABLED=true
REM Uncomment to set SSL-related system properties
REM Be sure to update the paths to the correct keystore for your environment
REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks

View File

@ -106,6 +106,9 @@
# Sets the port Solr binds to, default is 8983
#SOLR_PORT=8983
# Enables HTTPS. It is implictly true if you set SOLR_SSL_KEY_STORE. Use this config
# to enable https module with custom jetty configuration.
#SOLR_SSL_ENABLED=true
# Uncomment to set SSL-related system properties
# Be sure to update the paths to the correct keystore for your environment
#SOLR_SSL_KEY_STORE=/home/shalin/work/oss/shalin-lusolr/solr/server/etc/solr-ssl.keystore.jks

View File

@ -74,7 +74,7 @@ import org.slf4j.LoggerFactory;
* between versions in terms of API or back compat behaviour.
* @lucene.experimental
*/
public class RecoveryStrategy extends Thread implements Closeable {
public class RecoveryStrategy implements Runnable, Closeable {
public static class Builder implements NamedListInitializedPlugin {
private NamedList args;
@ -124,7 +124,6 @@ public class RecoveryStrategy extends Thread implements Closeable {
this.cc = cc;
this.coreName = cd.getName();
this.recoveryListener = recoveryListener;
setName("RecoveryThread-"+this.coreName);
zkController = cc.getZkController();
zkStateReader = zkController.getZkStateReader();
baseUrl = zkController.getBaseUrl();
@ -370,7 +369,7 @@ public class RecoveryStrategy extends Thread implements Closeable {
}
Future<RecoveryInfo> replayFuture = null;
while (!successfulRecovery && !isInterrupted() && !isClosed()) { // don't use interruption or it will close channels though
while (!successfulRecovery && !Thread.currentThread().isInterrupted() && !isClosed()) { // don't use interruption or it will close channels though
try {
CloudDescriptor cloudDesc = core.getCoreDescriptor().getCloudDescriptor();
ZkNodeProps leaderprops = zkStateReader.getLeaderRetry(

View File

@ -146,12 +146,6 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
rsp.add(IndexSchema.DEFAULT_SEARCH_FIELD, defaultSearchFieldName);
break;
}
case "/schema/solrqueryparser": {
SimpleOrderedMap<Object> props = new SimpleOrderedMap<>();
props.add(IndexSchema.DEFAULT_OPERATOR, req.getSchema().getQueryParserDefaultOperator());
rsp.add(IndexSchema.SOLR_QUERY_PARSER, props);
break;
}
case "/schema/zkversion": {
int refreshIfBelowVersion = -1;
Object refreshParam = req.getParams().get("refreshIfBelowVersion");
@ -175,10 +169,6 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
rsp.add("zkversion", zkVersion);
break;
}
case "/schema/solrqueryparser/defaultoperator": {
rsp.add(IndexSchema.DEFAULT_OPERATOR, req.getSchema().getQueryParserDefaultOperator());
break;
}
default: {
List<String> parts = StrUtils.splitSmart(path, '/');
if (parts.get(0).isEmpty()) parts.remove(0);

View File

@ -174,6 +174,13 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
.withFunctionName("conv", ConvolutionEvaluator.class)
.withFunctionName("normalize", NormalizeEvaluator.class)
.withFunctionName("rev", ReverseEvaluator.class)
.withFunctionName("length", LengthEvaluator.class)
.withFunctionName("rank", RankEvaluator.class)
.withFunctionName("scale", ScaleEvaluator.class)
.withFunctionName("distance", DistanceEvaluator.class)
.withFunctionName("copyOf", CopyOfEvaluator.class)
.withFunctionName("percentile", PercentileEvaluator.class)
.withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
// metrics
.withFunctionName("min", MinMetric.class)

View File

@ -103,10 +103,6 @@ public class SchemaXmlWriter extends TextResponseWriter {
closeStartTag(false);
writer.write(val.toString());
endTag(IndexSchema.DEFAULT_SEARCH_FIELD, false);
} else if (schemaPropName.equals(IndexSchema.SOLR_QUERY_PARSER)) {
openStartTag(IndexSchema.SOLR_QUERY_PARSER);
writeAttr(IndexSchema.DEFAULT_OPERATOR, ((Map<String ,Object>) val).get(IndexSchema.DEFAULT_OPERATOR).toString());
closeStartTag(true);
} else if (schemaPropName.equals(IndexSchema.SIMILARITY)) {
writeSimilarity((SimpleOrderedMap<Object>) val);
} else if (schemaPropName.equals(IndexSchema.FIELD_TYPES)) {

View File

@ -94,7 +94,6 @@ import static java.util.Collections.singletonMap;
public class IndexSchema {
public static final String COPY_FIELD = "copyField";
public static final String COPY_FIELDS = COPY_FIELD + "s";
public static final String DEFAULT_OPERATOR = "defaultOperator";
public static final String DEFAULT_SCHEMA_FILE = "schema.xml";
public static final String DEFAULT_SEARCH_FIELD = "defaultSearchField";
public static final String DESTINATION = "dest";
@ -112,7 +111,6 @@ public class IndexSchema {
public static final String SCHEMA = "schema";
public static final String SIMILARITY = "similarity";
public static final String SLASH = "/";
public static final String SOLR_QUERY_PARSER = "solrQueryParser";
public static final String SOURCE = "source";
public static final String TYPE = "type";
public static final String TYPES = "types";
@ -148,9 +146,6 @@ public class IndexSchema {
protected List<SchemaAware> schemaAware = new ArrayList<>();
protected String defaultSearchFieldName=null;
protected String queryParserDefaultOperator = "OR";
protected boolean isExplicitQueryParserDefaultOperator = false;
protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<>();
public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); }
@ -312,13 +307,6 @@ public class IndexSchema {
return defaultSearchFieldName;
}
/**
* default operator ("AND" or "OR") for QueryParser
*/
public String getQueryParserDefaultOperator() {
return queryParserDefaultOperator;
}
protected SchemaField uniqueKeyField;
/**
@ -540,15 +528,10 @@ public class IndexSchema {
}
// /schema/solrQueryParser/@defaultOperator
expression = stepsToPath(SCHEMA, SOLR_QUERY_PARSER, AT + DEFAULT_OPERATOR);
expression = stepsToPath(SCHEMA, "solrQueryParser", AT + "defaultOperator");
node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
if (node==null) {
log.debug("Default query parser operator not set in Schema");
} else {
isExplicitQueryParserDefaultOperator = true;
queryParserDefaultOperator=node.getNodeValue().trim();
log.warn("[{}] query parser default operator is {}. WARNING: Deprecated, please use 'q.op' on request instead.",
coreName, queryParserDefaultOperator);
if (node != null) {
throw new SolrException(ErrorCode.SERVER_ERROR, "Setting default operator in schema (solrQueryParser/@defaultOperator) not supported");
}
// /schema/uniqueKey/text()
@ -1402,9 +1385,6 @@ public class IndexSchema {
VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()),
UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName),
DEFAULT_SEARCH_FIELD(IndexSchema.DEFAULT_SEARCH_FIELD, sp -> sp.schema.defaultSearchFieldName),
SOLR_QUERY_PARSER(IndexSchema.SOLR_QUERY_PARSER, sp -> sp.schema.isExplicitQueryParserDefaultOperator ?
singletonMap(DEFAULT_OPERATOR, sp.schema.queryParserDefaultOperator) :
null),
SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ?
sp.schema.similarityFactory.getNamedPropertyValues() :
null),

View File

@ -1358,8 +1358,6 @@ public final class ManagedIndexSchema extends IndexSchema {
newSchema.name = name;
newSchema.version = version;
newSchema.defaultSearchFieldName = defaultSearchFieldName;
newSchema.queryParserDefaultOperator = queryParserDefaultOperator;
newSchema.isExplicitQueryParserDefaultOperator = isExplicitQueryParserDefaultOperator;
newSchema.similarity = similarity;
newSchema.similarityFactory = similarityFactory;
newSchema.isExplicitSimilarity = isExplicitSimilarity;

View File

@ -156,7 +156,7 @@ public class ComplexPhraseQParserPlugin extends QParserPlugin {
lparser.setInOrder(inOrder);
QueryParser.Operator defaultOperator = QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(), getParam(QueryParsing.OP));
QueryParser.Operator defaultOperator = QueryParsing.parseOP(getParam(QueryParsing.OP));
if (QueryParser.Operator.AND.equals(defaultOperator))
lparser.setDefaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.AND);

View File

@ -52,14 +52,13 @@ public class DisMaxQParser extends QParser {
* Applies the appropriate default rules for the "mm" param based on the
* effective value of the "q.op" param
*
* @see QueryParsing#getQueryParserDefaultOperator
* @see QueryParsing#OP
* @see DisMaxParams#MM
*/
public static String parseMinShouldMatch(final IndexSchema schema,
final SolrParams params) {
org.apache.solr.parser.QueryParser.Operator op = QueryParsing.getQueryParserDefaultOperator
(schema, params.get(QueryParsing.OP));
org.apache.solr.parser.QueryParser.Operator op = QueryParsing.parseOP(params.get(QueryParsing.OP));
return params.get(DisMaxParams.MM,
op.equals(QueryParser.Operator.AND) ? "100%" : "0%");
}

View File

@ -990,8 +990,7 @@ public class ExtendedDismaxQParser extends QParser {
super(parser, defaultField);
// Respect the q.op parameter before mm will be applied later
SolrParams defaultParams = SolrParams.wrapDefaults(parser.getLocalParams(), parser.getParams());
QueryParser.Operator defaultOp = QueryParsing.getQueryParserDefaultOperator(
parser.getReq().getSchema(), defaultParams.get(QueryParsing.OP));
QueryParser.Operator defaultOp = QueryParsing.parseOP(defaultParams.get(QueryParsing.OP));
setDefaultOperator(defaultOp);
}

View File

@ -44,9 +44,7 @@ public class LuceneQParser extends QParser {
}
lparser = new SolrQueryParser(this, defaultField);
lparser.setDefaultOperator
(QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(),
getParam(QueryParsing.OP)));
lparser.setDefaultOperator(QueryParsing.parseOP(getParam(QueryParsing.OP)));
lparser.setSplitOnWhitespace(StrUtils.parseBool
(getParam(QueryParsing.SPLIT_ON_WHITESPACE), SolrQueryParser.DEFAULT_SPLIT_ON_WHITESPACE));

View File

@ -59,18 +59,15 @@ public class QueryParsing {
/**
* Returns the "preferred" default operator for use by Query Parsers,
* based on the settings in the IndexSchema which may be overridden using
* an optional String override value.
*
* @see IndexSchema#getQueryParserDefaultOperator()
* @see #OP
* Returns the default operator for use by Query Parsers, parsed from the df string
* @param notUsed is not used, but is there for back compat with 3rd party QParsers
* @param df the df string from request
* @deprecated this method is here purely not to break code back compat in 7.x
*/
public static QueryParser.Operator getQueryParserDefaultOperator(final IndexSchema sch,
final String override) {
String val = override;
if (null == val) val = sch.getQueryParserDefaultOperator();
return "AND".equals(val) ? QueryParser.Operator.AND : QueryParser.Operator.OR;
@Deprecated
public static QueryParser.Operator getQueryParserDefaultOperator(final IndexSchema notUsed,
final String df) {
return parseOP(df);
}
/**
@ -396,4 +393,12 @@ public class QueryParsing {
return out;
}
/**
* Parses default operator string into Operator object
* @param operator the string from request
* @return Operator.AND if string equals "AND", else return Operator.OR (default)
*/
public static QueryParser.Operator parseOP(String operator) {
return "and".equalsIgnoreCase(operator) ? QueryParser.Operator.AND : QueryParser.Operator.OR;
}
}

View File

@ -154,7 +154,7 @@ public class SimpleQParserPlugin extends QParserPlugin {
parser = new SolrSimpleQueryParser(req.getSchema().getQueryAnalyzer(), queryFields, enabledOps, this, schema);
// Set the default operator to be either 'AND' or 'OR' for the query.
QueryParser.Operator defaultOp = QueryParsing.getQueryParserDefaultOperator(req.getSchema(), defaultParams.get(QueryParsing.OP));
QueryParser.Operator defaultOp = QueryParsing.parseOP(defaultParams.get(QueryParsing.OP));
if (defaultOp == QueryParser.Operator.AND) {
parser.setDefaultOperator(BooleanClause.Occur.MUST);

View File

@ -73,6 +73,7 @@ import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.security.AuthenticationPlugin;
import org.apache.solr.security.PKIAuthenticationPlugin;
import org.apache.solr.util.SolrFileCleaningTracker;
import org.apache.solr.util.configuration.SSLConfigurationsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -139,6 +140,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
@Override
public void init(FilterConfig config) throws ServletException
{
SSLConfigurationsFactory.current().init();
log.trace("SolrDispatchFilter.init(): {}", this.getClass().getClassLoader());
CoreContainer coresInit = null;
try{

View File

@ -278,7 +278,7 @@ public final class DefaultSolrCoreState extends SolrCoreState implements Recover
@Override
public void doRecovery(CoreContainer cc, CoreDescriptor cd) {
Thread thread = new Thread() {
Runnable recoveryTask = new Runnable() {
@Override
public void run() {
MDCLoggingContext.setCoreDescriptor(cc, cd);
@ -355,7 +355,7 @@ public final class DefaultSolrCoreState extends SolrCoreState implements Recover
// The recovery executor is not interrupted on shutdown.
//
// avoid deadlock: we can't use the recovery executor here
cc.getUpdateShardHandler().getUpdateExecutor().submit(thread);
cc.getUpdateShardHandler().getUpdateExecutor().submit(recoveryTask);
} catch (RejectedExecutionException e) {
// fine, we are shutting down
}

View File

@ -61,6 +61,8 @@ import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.net.ssl.SSLPeerUnverifiedException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
@ -114,6 +116,7 @@ import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.security.Sha256AuthenticationProvider;
import org.apache.solr.util.configuration.SSLConfigurationsFactory;
import org.noggit.CharArr;
import org.noggit.JSONParser;
import org.noggit.JSONWriter;
@ -253,6 +256,8 @@ public class SolrCLI {
exit(0);
}
SSLConfigurationsFactory.current().init();
Tool tool = findTool(args);
CommandLine cli = parseCmdLine(args, tool.getOptions());
System.exit(tool.runTool(cli));
@ -867,6 +872,8 @@ public class SolrCLI {
while (System.nanoTime() < timeout) {
try {
return getStatus(solrUrl);
} catch (SSLPeerUnverifiedException exc) {
throw exc;
} catch (Exception exc) {
if (exceptionIsAuthRelated(exc)) {
throw exc;
@ -3526,49 +3533,59 @@ public class SolrCLI {
public Option[] getOptions() {
return new Option[]{
OptionBuilder
.withArgName("enable")
.withDescription("Enable authentication.")
.create("enable"),
.withArgName("type")
.hasArg()
.withDescription("The authentication mechanism to enable. Defaults to 'basicAuth'.")
.create("type"),
OptionBuilder
.withArgName("disable")
.withDescription("Disable existing authentication.")
.create("disable"),
.withArgName("credentials")
.hasArg()
.withDescription("Credentials in the format username:password. Example: -credentials solr:SolrRocks")
.create("credentials"),
OptionBuilder
.withArgName("type")
.hasArg()
.withDescription("basicAuth")
.create("type"),
.withArgName("prompt")
.hasArg()
.withDescription("Prompts the user to provide the credentials. Use either -credentials or -prompt, not both")
.create("prompt"),
OptionBuilder
.withArgName("credentials")
.hasArg()
.withDescription("Credentials in the format username:password. Example: -credentials solr:SolrRocks")
.create("credentials"),
.withArgName("blockUnknown")
.withDescription("Blocks all access for unknown users (requires authentication for all endpoints)")
.hasArg()
.create("blockUnknown"),
OptionBuilder
.withArgName("prompt")
.withDescription("Prompt for credentials. Use either -credentials or -prompt, not both")
.create("prompt"),
.withArgName("solrIncludeFile")
.hasArg()
.withDescription("The Solr include file which contains overridable environment variables for configuring Solr configurations")
.create("solrIncludeFile"),
OptionBuilder
.withArgName("blockUnknown")
.withDescription("Blocks all access for unknown users (requires authentication for all endpoints)")
.hasOptionalArg()
.create("blockUnknown"),
.withArgName("updateIncludeFileOnly")
.withDescription("Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling"
+ " authentication (i.e. don't update security.json)")
.hasArg()
.create("updateIncludeFileOnly"),
OptionBuilder
.withArgName("solrIncludeFile")
.hasArg()
.withDescription("The Solr include file which contains overridable environment variables for configuring Solr configurations")
.create("solrIncludeFile"),
.withArgName("authConfDir")
.hasArg()
.isRequired()
.withDescription("This is where any authentication related configuration files, if any, would be placed.")
.create("authConfDir"),
OptionBuilder
.withArgName("solrUrl")
.hasArg()
.withDescription("Solr URL")
.create("solrUrl"),
.withArgName("solrUrl")
.hasArg()
.withDescription("Solr URL")
.create("solrUrl"),
OptionBuilder
.withArgName("zkHost")
.hasArg()
.withDescription("ZooKeeper host")
.create("zkHost"),
};
}
@Override
public int runTool(CommandLine cli) throws Exception {
if (cli.getOptions().length == 0 || cli.getArgs().length > 0 || cli.hasOption("h")) {
new HelpFormatter().printHelp("bin/solr auth [OPTIONS]", getToolOptions(this));
if (cli.getOptions().length == 0 || cli.getArgs().length == 0 || cli.getArgs().length > 1 || cli.hasOption("h")) {
new HelpFormatter().printHelp("bin/solr auth <enable|disable> [OPTIONS]", getToolOptions(this));
return 1;
}
@ -3578,128 +3595,153 @@ public class SolrCLI {
exit(1);
}
if (cli.hasOption("enable") && cli.hasOption("disable")) {
System.out.println("You have specified both -enable and -disable. Only one should be provided.");
return 1;
}
if (cli.hasOption("enable")) {
String zkHost = getZkHost(cli);
if (zkHost == null) {
System.out.println("ZK Host not found. Solr should be running in cloud mode");
exit(1);
}
String cmd = cli.getArgs()[0];
boolean prompt = Boolean.parseBoolean(cli.getOptionValue("prompt", "false"));
boolean updateIncludeFileOnly = Boolean.parseBoolean(cli.getOptionValue("updateIncludeFileOnly", "false"));
switch (cmd) {
case "enable":
if (!prompt && !cli.hasOption("credentials")) {
System.out.println("Option -credentials or -prompt is required with enable.");
new HelpFormatter().printHelp("bin/solr auth <enable|disable> [OPTIONS]", getToolOptions(this));
exit(1);
} else if (!prompt && (cli.getOptionValue("credentials") == null || !cli.getOptionValue("credentials").contains(":"))) {
System.out.println("Option -credentials is not in correct format.");
new HelpFormatter().printHelp("bin/solr auth <enable|disable> [OPTIONS]", getToolOptions(this));
exit(1);
}
if (cli.hasOption("credentials") == false && cli.hasOption("prompt") == false) {
System.out.println("Option -credentials or -prompt is required with -enable.");
new HelpFormatter().printHelp("bin/solr auth [OPTIONS]", getToolOptions(this));
exit(1);
} else if (cli.hasOption("prompt") == false &&
(cli.getOptionValue("credentials") == null || !cli.getOptionValue("credentials").contains(":"))) {
System.out.println("Option -credentials is not in correct format.");
new HelpFormatter().printHelp("bin/solr auth [OPTIONS]", getToolOptions(this));
exit(1);
}
String zkHost = null;
String username, password;
if (cli.hasOption("credentials")) {
String credentials = cli.getOptionValue("credentials");
username = credentials.split(":")[0];
password = credentials.split(":")[1];
} else {
Console console = System.console();
username = console.readLine("Enter username: ");
password = new String(console.readPassword("Enter password: "));
}
// check if security is already enabled or not
try (SolrZkClient zkClient = new SolrZkClient(zkHost, 10000)) {
if (zkClient.exists("/security.json", true)) {
byte oldSecurityBytes[] = zkClient.getData("/security.json", null, null, true);
if (!"{}".equals(new String(oldSecurityBytes, StandardCharsets.UTF_8).trim())) {
System.out.println("Security is already enabled. You can disable it with 'bin/solr auth -disable'. Existing security.json: \n"
+ new String(oldSecurityBytes, StandardCharsets.UTF_8));
if (!updateIncludeFileOnly) {
try {
zkHost = getZkHost(cli);
} catch (Exception ex) {
if (cli.hasOption("zkHost")) {
System.out.println("Couldn't get ZooKeeper host. Please make sure that ZooKeeper is running and the correct zkHost has been passed in.");
} else {
System.out.println("Couldn't get ZooKeeper host. Please make sure Solr is running in cloud mode, or a zkHost has been passed in.");
}
exit(1);
}
if (zkHost == null) {
if (cli.hasOption("zkHost")) {
System.out.println("Couldn't get ZooKeeper host. Please make sure that ZooKeeper is running and the correct zkHost has been passed in.");
} else {
System.out.println("Couldn't get ZooKeeper host. Please make sure Solr is running in cloud mode, or a zkHost has been passed in.");
}
exit(1);
}
// check if security is already enabled or not
try (SolrZkClient zkClient = new SolrZkClient(zkHost, 10000)) {
if (zkClient.exists("/security.json", true)) {
byte oldSecurityBytes[] = zkClient.getData("/security.json", null, null, true);
if (!"{}".equals(new String(oldSecurityBytes, StandardCharsets.UTF_8).trim())) {
System.out.println("Security is already enabled. You can disable it with 'bin/solr auth disable'. Existing security.json: \n"
+ new String(oldSecurityBytes, StandardCharsets.UTF_8));
exit(1);
}
}
}
}
}
boolean blockUnknown = cli.getOptionValue("blockUnknown") == null ?
cli.hasOption("blockUnknown"): Boolean.valueOf(cli.getOptionValue("blockUnknown"));
String username, password;
if (cli.hasOption("credentials")) {
String credentials = cli.getOptionValue("credentials");
username = credentials.split(":")[0];
password = credentials.split(":")[1];
} else {
Console console = System.console();
username = console.readLine("Enter username: ");
password = new String(console.readPassword("Enter password: "));
}
String securityJson = "{" +
"\n \"authentication\":{" +
"\n \"blockUnknown\": " + blockUnknown + "," +
"\n \"class\":\"solr.BasicAuthPlugin\"," +
"\n \"credentials\":{\""+username+"\":\"" + Sha256AuthenticationProvider.getSaltedHashedValue(password) + "\"}" +
"\n }," +
"\n \"authorization\":{" +
"\n \"class\":\"solr.RuleBasedAuthorizationPlugin\"," +
"\n \"permissions\":[" +
"\n {\"name\":\"security-edit\", \"role\":\"admin\"}," +
"\n {\"name\":\"collection-admin-edit\", \"role\":\"admin\"}," +
"\n {\"name\":\"core-admin-edit\", \"role\":\"admin\"}" +
"\n ]," +
"\n \"user-role\":{\""+username+"\":\"admin\"}" +
"\n }" +
"\n}";
boolean blockUnknown = Boolean.valueOf(cli.getOptionValue("blockUnknown", "false"));
String securityJson = "{" +
"\n \"authentication\":{" +
"\n \"blockUnknown\": " + blockUnknown + "," +
"\n \"class\":\"solr.BasicAuthPlugin\"," +
"\n \"credentials\":{\"" + username + "\":\"" + Sha256AuthenticationProvider.getSaltedHashedValue(password) + "\"}" +
"\n }," +
"\n \"authorization\":{" +
"\n \"class\":\"solr.RuleBasedAuthorizationPlugin\"," +
"\n \"permissions\":[" +
"\n {\"name\":\"security-edit\", \"role\":\"admin\"}," +
"\n {\"name\":\"collection-admin-edit\", \"role\":\"admin\"}," +
"\n {\"name\":\"core-admin-edit\", \"role\":\"admin\"}" +
"\n ]," +
"\n \"user-role\":{\"" + username + "\":\"admin\"}" +
"\n }" +
"\n}";
if (!updateIncludeFileOnly) {
System.out.println("Uploading following security.json: " + securityJson);
try (SolrZkClient zkClient = new SolrZkClient(zkHost, 10000)) {
zkClient.setData("/security.json", securityJson.getBytes(StandardCharsets.UTF_8), true);
}
}
String solrIncludeFilename = cli.getOptionValue("solrIncludeFile");
File includeFile = new File(solrIncludeFilename);
if (includeFile.exists() == false || includeFile.canWrite() == false) {
System.out.println("Solr include file " + solrIncludeFilename + " doesn't exist or is not writeable.");
printAuthEnablingInstructions(username, password);
System.exit(0);
}
File basicAuthConfFile = new File(includeFile.getParent() + File.separator + "basicAuth.conf");
if (basicAuthConfFile.getParentFile().canWrite() == false) {
System.out.println("Cannot write to file: " + basicAuthConfFile.getAbsolutePath());
printAuthEnablingInstructions(username, password);
System.exit(0);
}
FileUtils.writeStringToFile(basicAuthConfFile,
"httpBasicAuthUser=" + username + "\nhttpBasicAuthPassword=" + password, StandardCharsets.UTF_8);
String solrIncludeFilename = cli.getOptionValue("solrIncludeFile");
File includeFile = new File(solrIncludeFilename);
if (includeFile.exists() == false || includeFile.canWrite() == false) {
System.out.println("Solr include file " + solrIncludeFilename + " doesn't exist or is not writeable.");
printAuthEnablingInstructions(username, password);
System.exit(0);
}
String authConfDir = cli.getOptionValue("authConfDir");
File basicAuthConfFile = new File(authConfDir + File.separator + "basicAuth.conf");
// update the solr.in.sh file to contain the necessary authentication lines
updateIncludeFileEnableAuth(includeFile, basicAuthConfFile.getAbsolutePath(), username, password);
return 0;
} else if (cli.hasOption("disable")) {
String zkHost = getZkHost(cli);
if (zkHost == null) {
stdout.print("ZK Host not found. Solr should be running in cloud mode");
if (basicAuthConfFile.getParentFile().canWrite() == false) {
System.out.println("Cannot write to file: " + basicAuthConfFile.getAbsolutePath());
printAuthEnablingInstructions(username, password);
System.exit(0);
}
FileUtils.writeStringToFile(basicAuthConfFile,
"httpBasicAuthUser=" + username + "\nhttpBasicAuthPassword=" + password, StandardCharsets.UTF_8);
// update the solr.in.sh file to contain the necessary authentication lines
updateIncludeFileEnableAuth(includeFile, basicAuthConfFile.getAbsolutePath());
return 0;
case "disable":
if (!updateIncludeFileOnly) {
zkHost = getZkHost(cli);
if (zkHost == null) {
stdout.print("ZK Host not found. Solr should be running in cloud mode");
exit(1);
}
System.out.println("Uploading following security.json: {}");
try (SolrZkClient zkClient = new SolrZkClient(zkHost, 10000)) {
zkClient.setData("/security.json", "{}".getBytes(StandardCharsets.UTF_8), true);
}
}
solrIncludeFilename = cli.getOptionValue("solrIncludeFile");
includeFile = new File(solrIncludeFilename);
if (!includeFile.exists() || !includeFile.canWrite()) {
System.out.println("Solr include file " + solrIncludeFilename + " doesn't exist or is not writeable.");
System.out.println("Security has been disabled. Please remove any SOLR_AUTH_TYPE or SOLR_AUTHENTICATION_OPTS configuration from solr.in.sh/solr.in.cmd.\n");
System.exit(0);
}
// update the solr.in.sh file to comment out the necessary authentication lines
updateIncludeFileDisableAuth(includeFile);
return 0;
default:
System.out.println("Valid auth commands are: enable, disable");
exit(1);
}
System.out.println("Uploading following security.json: {}");
try (SolrZkClient zkClient = new SolrZkClient(zkHost, 10000)) {
zkClient.setData("/security.json", "{}".getBytes(StandardCharsets.UTF_8), true);
}
String solrIncludeFilename = cli.getOptionValue("solrIncludeFile");
File includeFile = new File(solrIncludeFilename);
if (includeFile.exists() == false || includeFile.canWrite() == false) {
System.out.println("Solr include file " + solrIncludeFilename + " doesn't exist or is not writeable.");
System.out.println("Security has been disabled. Please remove any SOLR_AUTH_TYPE or SOLR_AUTHENTICATION_OPTS configuration from solr.in.sh/solr.in.cmd.\n");
System.exit(0);
}
// update the solr.in.sh file to comment out the necessary authentication lines
updateIncludeFileDisableAuth(includeFile);
return 0;
}
System.out.println("Options not understood (should be -enable or -disable).");
new HelpFormatter().printHelp("bin/solr auth [OPTIONS]", getToolOptions(this));
System.out.println("Options not understood.");
new HelpFormatter().printHelp("bin/solr auth <enable|disable> [OPTIONS]", getToolOptions(this));
return 1;
}
private void printAuthEnablingInstructions(String username, String password) {
if (SystemUtils.IS_OS_WINDOWS) {
System.out.println("\nAdd the following lines to the solr.in.cmd file so that the solr.cmd script can use subsequently.\n");
@ -3708,11 +3750,11 @@ public class SolrCLI {
} else {
System.out.println("\nAdd the following lines to the solr.in.sh file so that the ./solr script can use subsequently.\n");
System.out.println("SOLR_AUTH_TYPE=\"basic\"\n"
+ "SOLR_AUTHENTICATION_OPTS=\"-DbasicAuth=" + username + ":" + password + "\"\n");
+ "SOLR_AUTHENTICATION_OPTS=\"-Dbasicauth=" + username + ":" + password + "\"\n");
}
}
private void updateIncludeFileEnableAuth(File includeFile, String basicAuthConfFile, String username, String password) throws IOException {
private void updateIncludeFileEnableAuth(File includeFile, String basicAuthConfFile) throws IOException {
List<String> includeFileLines = FileUtils.readLines(includeFile, StandardCharsets.UTF_8);
for (int i=0; i<includeFileLines.size(); i++) {
String line = includeFileLines.get(i);
@ -3738,7 +3780,7 @@ public class SolrCLI {
System.out.println("Written out credentials file: " + basicAuthConfFile + ", updated Solr include file: " + includeFile.getAbsolutePath() + ".");
}
private void updateIncludeFileDisableAuth(File includeFile) throws IOException {
List<String> includeFileLines = FileUtils.readLines(includeFile, StandardCharsets.UTF_8);
boolean hasChanged = false;
@ -3762,7 +3804,7 @@ public class SolrCLI {
@Override
protected void runImpl(CommandLine cli) throws Exception {}
}
public static class UtilsTool extends ToolBase {
private Path serverPath;
private Path logsPath;

View File

@ -0,0 +1,78 @@
/*
* 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.util.configuration;
import java.lang.invoke.MethodHandles;
import java.util.Map;
import org.apache.solr.common.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Dedicated object to handle Solr configurations
*/
public class SSLConfigurations {
private final Map<String, String> envVars;
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static class SysProps {
public static final String SSL_KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";
public static final String SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
}
public static class EnvVars {
public static final String SOLR_SSL_CLIENT_KEY_STORE_PASSWORD = "SOLR_SSL_CLIENT_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_KEY_STORE_PASSWORD = "SOLR_SSL_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD = "SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD";
public static final String SOLR_SSL_TRUST_STORE_PASSWORD = "SOLR_SSL_TRUST_STORE_PASSWORD";
}
/**
* @param envVars Map of environment variables to use
*/
public SSLConfigurations(Map<String, String> envVars) {
this.envVars = envVars;
}
/** Initiates javax.net.ssl.* system properties from the proper sources. */
public void init() {
String clientKeystorePassword = envVars.get(EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD);
String keystorePassword = envVars.get(EnvVars.SOLR_SSL_KEY_STORE_PASSWORD);
String clientTruststorePassword = envVars.get(EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD);
String truststorePassword = envVars.get(EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD);
if (isEmpty(System.getProperty(SysProps.SSL_KEY_STORE_PASSWORD))
&& !(isEmpty(clientKeystorePassword) && isEmpty(keystorePassword))) {
log.debug("Setting {} based on env var", SysProps.SSL_KEY_STORE_PASSWORD);
System.setProperty(SysProps.SSL_KEY_STORE_PASSWORD, clientKeystorePassword != null ? clientKeystorePassword : keystorePassword);
}
if (isEmpty(System.getProperty(SysProps.SSL_TRUST_STORE_PASSWORD))
&& !(isEmpty(clientTruststorePassword) && isEmpty(truststorePassword))) {
log.debug("Setting {} based on env var", SysProps.SSL_TRUST_STORE_PASSWORD);
System.setProperty(SysProps.SSL_TRUST_STORE_PASSWORD, clientTruststorePassword != null ? clientTruststorePassword : truststorePassword);
}
}
private boolean isEmpty(String str) {
return StringUtils.isEmpty(str);
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.util.configuration;
import com.google.common.annotations.VisibleForTesting;
public class SSLConfigurationsFactory {
static private SSLConfigurations currentConfigurations;
/**
* Creates if necessary and returns singleton object of Configurations. Can be used for
* static accessor of application-wide instance.
* @return Configurations object
*/
static public SSLConfigurations current() {
if (currentConfigurations == null) {
synchronized (SSLConfigurationsFactory.class) {
if (currentConfigurations == null) {
currentConfigurations = getInstance();
}
}
}
return currentConfigurations;
}
private static SSLConfigurations getInstance() {
return new SSLConfigurations(System.getenv());
}
@VisibleForTesting
static public synchronized void setCurrent(SSLConfigurations configurations) {
currentConfigurations = configurations;
}
}

View File

@ -14,16 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.rest.schema;
import org.apache.solr.rest.SolrRestletTestBase;
import org.junit.Test;
/**
* Common Util APIs related to Solr configuration.
*/
package org.apache.solr.util.configuration;
public class TestSolrQueryParserDefaultOperatorResource extends SolrRestletTestBase {
@Test
public void testGetDefaultOperator() throws Exception {
assertQ("/schema/solrqueryparser/defaultoperator?indent=on&wt=xml",
"count(/response/str[@name='defaultOperator']) = 1",
"/response/str[@name='defaultOperator'][.='OR']");
}
}

View File

@ -11,8 +11,7 @@
"/schema/version",
"/schema/similarity",
"/schema/solrqueryparser",
"/schema/zkversion",
"/schema/solrqueryparser/defaultoperator"
"/schema/zkversion"
]
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" ?>
<!--
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.
-->
<schema name="bad-schema-default-operator" version="1.6">
<fieldType name="string" class="solr.StrField"/>
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="false"/>
<uniqueKey>id</uniqueKey>
<!-- BEGIN BAD STUFF: not allowed anymore -->
<solrQueryParser defaultOperator="OR"/>
<!-- END BAD STUFF -->
</schema>

View File

@ -1,30 +0,0 @@
/*
* 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.rest.schema;
import org.apache.solr.rest.SolrRestletTestBase;
import org.junit.Test;
public class TestSolrQueryParserResource extends SolrRestletTestBase {
@Test
public void testGetSolrQueryParser() throws Exception {
assertQ("/schema/solrqueryparser?indent=on&wt=xml",
"count(/response/lst[@name='solrQueryParser']) = 1",
"count(/response/lst[@name='solrQueryParser']/str[@name='defaultOperator']) = 1",
"/response/lst[@name='solrQueryParser']/str[@name='defaultOperator'][.='OR']");
}
}

View File

@ -127,5 +127,9 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
doTest("bad-schema-sim-default-does-not-exist.xml",
"ft-does-not-exist");
}
public void testDefaultOperatorBanned() throws Exception {
doTest("bad-schema-default-operator.xml",
"default operator in schema (solrQueryParser/@defaultOperator) not supported");
}
}

View File

@ -109,7 +109,7 @@ public class TestUseDocValuesAsStored extends AbstractBadConfigTestBase {
@After
private void afterTest() throws Exception {
clearIndex();
commit();
assertU(commit());
deleteCore();
System.clearProperty("managed.schema.mutable");
System.clearProperty("enable.update.log");

View File

@ -0,0 +1,121 @@
/*
* 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.util.configuration;
import java.util.HashMap;
import java.util.Map;
import org.apache.lucene.util.TestRuleRestoreSystemProperties;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class SSLConfigurationsTest {
private Map<String, String> envs;
private SSLConfigurations sut;
public static final String SAMPLE_PW1 = "pw123";
public static final String SAMPLE_PW2 = "pw456";
public static final String SAMPLE_PW3 = "pw789";
public static final String KEY_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD;
public static final String TRUST_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD;
@Rule
public TestRule syspropRestore = new TestRuleRestoreSystemProperties(
SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD
);
@Before
public void setUp() {
envs = new HashMap<>();
}
private SSLConfigurations createSut() {
sut = new SSLConfigurations(envs);
return sut;
}
@Test
public void testSslConfigKeystorePwFromKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW1));
}
@Test
public void testSslConfigKeystorePwFromClientKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigKeystorePwFromBothEnvVars() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigKeystorePwNotOverwrittenIfExists() {
System.setProperty(KEY_STORE_PASSWORD, SAMPLE_PW3);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
}
@Test
public void testSslConfigTruststorePwFromKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW1));
}
@Test
public void testSslConfigTruststorePwFromClientKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigTruststorePwFromBothEnvVars() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigTruststorePwNotOverwrittenIfExists() {
System.setProperty(TRUST_STORE_PASSWORD, SAMPLE_PW3);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
}
}

View File

@ -8,9 +8,9 @@
<!-- ============================================================= -->
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<Set name="KeyStorePath"><Property name="solr.jetty.keystore" default="./etc/solr-ssl.keystore.jks"/></Set>
<Set name="KeyStorePassword"><Property name="solr.jetty.keystore.password" default="secret"/></Set>
<Set name="KeyStorePassword"><Env name="SOLR_SSL_KEY_STORE_PASSWORD" default="secret"/></Set>
<Set name="TrustStorePath"><Property name="solr.jetty.truststore" default="./etc/solr-ssl.keystore.jks"/></Set>
<Set name="TrustStorePassword"><Property name="solr.jetty.truststore.password" default="secret"/></Set>
<Set name="TrustStorePassword"><Env name="SOLR_SSL_TRUST_STORE_PASSWORD" default="secret"/></Set>
<Set name="NeedClientAuth"><Property name="solr.jetty.ssl.needClientAuth" default="false"/></Set>
<Set name="WantClientAuth"><Property name="solr.jetty.ssl.wantClientAuth" default="false"/></Set>
<Set name="KeyStoreType"><Property name="solr.jetty.keystore.type" default="JKS"/></Set>

View File

@ -1,6 +0,0 @@
---
title: "Page Not Found"
search: exclude
---
Sorry, but the page you were trying to view does not exist. Try searching for it or looking at the URL to see if it looks correct.

View File

@ -36,18 +36,6 @@ exclude:
- .gitignore
- pdf/
# if you uncomment the next line, the Feedback link gets removed
feedback_disable: true
# used as a contact email for the Feedback link in the top navigation bar
# feedback_email: an_email@apache.org
# if you uncomment the next line, it changes the Feedback text
# feedback_text: "Need help?"
# if you uncomment the next line, it changes where the feedback link points to
# feedback_link: "http://helpy.io/"
# these are defaults used for the frontmatter for these file types
defaults:
-

View File

@ -1,15 +0,0 @@
---
layout: default
type: archive
---
<div class="post-header">
<h1 class="post-title-main">{{ page.title }}</h1>
</div>
<div class="post-content">
{{ content }}
</div>

View File

@ -1,16 +0,0 @@
<!-- Send feedback function -->
<script>
function SendLinkByMail(href) {
var subject= "{{site.site_title}} feedback";
var body = "I have some feedback about the {{page.title}} page: ";
body += window.location.href;
body += "";
var uri = "mailto:{{site.feedback_email}}?subject=";
uri += encodeURIComponent(subject);
uri += "&body=";
uri += encodeURIComponent(body);
window.location.href = uri;
}
</script>
<li><a href="{% if site.feedback_link %}{{site.feedback_link}}{% else %}javascript:(function()%7BSendLinkByMail()%3B%7D)()%3B{% endif %}" target="_blank">{% if site.feedback_link == null %}<i class="fa fa-envelope-o"></i>{% endif %} {% if site.feedback_text %}{{site.feedback_text}}{% else %}Feedback{% endif %}</a></li>

View File

@ -3,7 +3,7 @@
<div class="col-lg-12 footer">
&copy;{{ site.solr-attributes.build-year }} {{site.company_name}}. All rights reserved. <br />
{% if page.last_updated %}<p>Page last updated:</span> {{page.last_updated}}<br/>{% endif %} Site Version: {{ site.solr-attributes.solr-guide-version }} <br />Site last generated: {{ site.solr-attributes.build-date }} <br />
<p><img src="{{ "solr-sunOnly-small.png" }}" alt="Apache Solr"/></p>
<p><img src="{{ "images/solr-sunOnly-small.png" }}" alt="Apache Solr"/></p>
</div>
</div>
</footer>

View File

@ -1 +0,0 @@
<figure>{% if {{include.url}} %}<a class="no_icon" target="_blank" href="{{include.url}}">{% endif %}<img class="docimage" src="images/{{include.file}}" alt="{{include.alt}}" {% if {{include.max-width}} %}style="max-width: {{include.max-width}}px"{% endif %} />{% if {{include.url}} %}</a>{% endif %}{% if {{include.caption}} %}<figcaption>{{include.caption}}</figcaption></figure>{% endif %}

View File

@ -1 +0,0 @@
<img class="inline" src="images/{{include.file}}" alt="{{include.alt}}" />

View File

@ -1,44 +0,0 @@
{% comment %}Get links from each sidebar, as listed in the _config.yml file under sidebars{% endcomment %}
{% for sidebar in site.sidebars %}
{% for entry in site.data.sidebars[sidebar].entries %}
{% for folder in entry.folders %}
{% for folderitem in folder.folderitems %}
{% if folderitem.url contains "html#" %}
[{{folderitem.url | remove: "/" }}]: {{folderitem.url | remove: "/"}}
{% else %}
[{{folderitem.url | remove: "/" | remove: ".html"}}]: {{folderitem.url | remove: "/"}}
{% endif %}
{% for subfolders in folderitem.subfolders %}
{% for subfolderitem in subfolders.subfolderitems %}
[{{subfolderitem.url | remove: "/" | remove: ".html"}}]: {{subfolderitem.url | remove: "/"}}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% comment %} Get links from topnav {% endcomment %}
{% for entry in site.data.topnav.topnav %}
{% for item in entry.items %}
{% if item.external_url == null %}
[{{item.url | remove: "/" | remove: ".html"}}]: {{item.url | remove: "/"}}
{% endif %}
{% endfor %}
{% endfor %}
{% comment %}Get links from topnav dropdowns {% endcomment %}
{% for entry in site.data.topnav.topnav_dropdowns %}
{% for folder in entry.folders %}
{% for folderitem in folder.folderitems %}
{% if folderitem.external_url == null %}
[{{folderitem.url | remove: "/" | remove: ".html"}}]: {{folderitem.url | remove: "/"}}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}

View File

@ -33,9 +33,6 @@
<li><a href="https://lucene.apache.org/solr/community.html" target="_blank">Solr Community Links</a></li>
</ul>
</li>
{% if site.feedback_disable == null or site.feedback_disable == false %}
{% include feedback.html %}
{% endif %}
<!--comment out this block if you want to hide search-->
<li>
<!--start search-->

View File

@ -1,41 +0,0 @@
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
<p class="post-meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time> {% if page.author %}<span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">/ {{ page.author }}</span></span>{% endif %}{% if page.tags != null %}/
{% assign projectTags = site.data.tags.allowed-tags %}
{% for tag in page.tags %}
{% if projectTags contains tag %}
<a href="{{ "../tag_" | append: tag | append: ".html" }}">{{tag}}</a>{% unless forloop.last %}, {% endunless%}
{% endif %}
{% endfor %}
{% endif %}
</p>
</header>
<div class="post-content" itemprop="articleBody">
{% if page.summary %}
<div class="summary">{{page.summary}}</div>
{% endif %}
{{ content }}
</div>
</article>
{% if site.disqus %}
{% include disqus.html %}
{% endif %}
{{site.data.alerts.hr_shaded}}
{% include footer.html %}

View File

@ -77,7 +77,7 @@ body
}
body.DRAFT {
background-image: url("../draft-background.png");
background-image: url("../images/draft-background.png");
}
a

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -21,12 +21,12 @@ Schema defaults and `copyFields` cannot be used to populate the `uniqueKey` fiel
Further, the operation will fail if the `uniqueKey` field is used, but is multivalued (or inherits the multivalue-ness from the `fieldtype`). However, `uniqueKey` will continue to work, as long as the field is properly used.
[[OtherSchemaElements-DefaultSearchField_QueryOperator]]
== Default Search Field & Query Operator
[[OtherSchemaElements-DefaultSearchField]]
== Default Search Field
Although they have been deprecated for quite some time, Solr still has support for Schema based configuration of a `<defaultSearchField/>` (which is superseded by the <<the-standard-query-parser.adoc#the-standard-query-parser,`df parameter`>>) and `<solrQueryParser defaultOperator="OR"/>` (which is superseded by the <<the-standard-query-parser.adoc#the-standard-query-parser,`q.op` parameter>>.
Although it has been deprecated for quite some time, Solr still has support for Schema based configuration of a `<defaultSearchField/>` (which is superseded by the <<the-standard-query-parser.adoc#the-standard-query-parser,`df parameter`>>).
If you have these options specified in your Schema, you are strongly encouraged to replace them with request parameters (or <<request-parameters-api.adoc#request-parameters-api,request parameter defaults>>) as support for them may be removed from future Solr release.
If you have this option specified in your Schema, you are strongly encouraged to replace it with request parameters (or <<request-parameters-api.adoc#request-parameters-api,request parameter defaults>>) as support for it will be removed from future Solr release.
[[OtherSchemaElements-Similarity]]
== Similarity

View File

@ -92,7 +92,7 @@ title_page:
align: right
logo:
top: 10%
image: image:../../solr-sunOnly-small.png[pdfwidth=10%]
image: image:../../images/solr-sunOnly-small.png[pdfwidth=10%]
align: right
title:
top: 55%

View File

@ -47,7 +47,6 @@ bin/solr -e cloud -noprompt
* `/schema/version`: <<SchemaAPI-ShowtheSchemaVersion,retrieve>> the schema version
* `/schema/uniquekey`: <<SchemaAPI-ListUniqueKey,retrieve>> the defined uniqueKey
* `/schema/similarity`: <<SchemaAPI-ShowGlobalSimilarity,retrieve>> the global similarity definition
* `/schema/solrqueryparser/defaultoperator`: <<SchemaAPI-GettheDefaultQueryOperator,retrieve>> the default operator
[[SchemaAPI-ModifytheSchema]]
== Modify the Schema
@ -1165,63 +1164,6 @@ curl http://localhost:8983/solr/gettingstarted/schema/similarity?wt=json
----
[[SchemaAPI-GettheDefaultQueryOperator]]
=== Get the Default Query Operator
`GET /_collection_/schema/solrqueryparser/defaultoperator`
[[SchemaAPI-INPUT.9]]
==== INPUT
*Path Parameters*
// TODO: Change column width to %autowidth.spread when https://github.com/asciidoctor/asciidoctor-pdf/issues/599 is fixed
[cols="30,70",options="header"]
|===
|Key |Description
|collection |The collection (or core) name.
|===
*Query Parameters*
The query parameters can be added to the API request after a '?'.
// TODO: Change column width to %autowidth.spread when https://github.com/asciidoctor/asciidoctor-pdf/issues/599 is fixed
[cols="15,10,10,10,55",options="header"]
|===
|Key |Type |Required |Default |Description
|wt |string |No |json |Defines the format of the response. The options are *json* or *xml*. If not specified, JSON will be returned by default.
|===
[[SchemaAPI-OUTPUT.9]]
==== OUTPUT
*Output Content*
The output will include simply the default operator if none is defined by the user.
[[SchemaAPI-EXAMPLES.9]]
==== EXAMPLES
Get the default operator.
[source,bash]
----
curl http://localhost:8983/solr/gettingstarted/schema/solrqueryparser/defaultoperator?wt=json
----
[source,json]
----
{
"responseHeader":{
"status":0,
"QTime":2},
"defaultOperator":"OR"}
----
[[SchemaAPI-ManageResourceData]]
== Manage Resource Data

View File

@ -30,7 +30,7 @@ In addition to the common request parameter, highlighting parameters, and simple
|<<TheDisMaxQueryParser-TheqParameter,q>> |Defines the raw input strings for the query.
|<<TheDisMaxQueryParser-Theq.altParameter,q.alt>> |Calls the standard query parser and defines query input strings, when the q parameter is not used.
|<<TheDisMaxQueryParser-Theqf_QueryFields_Parameter,qf>> |Query Fields: specifies the fields in the index on which to perform the query. If absent, defaults to `df`.
|<<TheDisMaxQueryParser-Themm_MinimumShouldMatch_Parameter,mm>> |Minimum "Should" Match: specifies a minimum number of clauses that must match in a query. If no 'mm' parameter is specified in the query, or as a default in `solrconfig.xml`, the effective value of the `q.op` parameter (either in the query, as a default in `solrconfig.xml`, or from the `defaultOperator` option in the Schema) is used to influence the behavior. If `q.op` is effectively AND'ed, then mm=100%; if `q.op` is OR'ed, then mm=1. Users who want to force the legacy behavior should set a default value for the 'mm' parameter in their `solrconfig.xml` file. Users should add this as a configured default for their request handlers. This parameter tolerates miscellaneous white spaces in expressions (e.g., `" 3 < -25% 10 < -3\n", " \n-25%\n ", " \n3\n "`).
|<<TheDisMaxQueryParser-Themm_MinimumShouldMatch_Parameter,mm>> |Minimum "Should" Match: specifies a minimum number of clauses that must match in a query. If no 'mm' parameter is specified in the query, or as a default in `solrconfig.xml`, the effective value of the `q.op` parameter (either in the query or as a default in `solrconfig.xml`) is used to influence the behavior. If `q.op` is effectively AND'ed, then mm=100%; if `q.op` is OR'ed, then mm=1. Users who want to force the legacy behavior should set a default value for the 'mm' parameter in their `solrconfig.xml` file. Users should add this as a configured default for their request handlers. This parameter tolerates miscellaneous white spaces in expressions (e.g., `" 3 < -25% 10 < -3\n", " \n-25%\n ", " \n3\n "`).
|<<TheDisMaxQueryParser-Thepf_PhraseFields_Parameter,pf>> |Phrase Fields: boosts the score of documents in cases where all of the terms in the q parameter appear in close proximity.
|<<TheDisMaxQueryParser-Theps_PhraseSlop_Parameter,ps>> |Phrase Slop: specifies the number of positions two terms can be apart in order to match the specified phrase.
|<<TheDisMaxQueryParser-Theqs_QueryPhraseSlop_Parameter,qs>> |Query Phrase Slop: specifies the number of positions two terms can be apart in order to match the specified phrase. Used specifically with the `qf` parameter.

View File

@ -0,0 +1,84 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class CopyOfEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public CopyOfEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public List<Number> evaluate(Tuple tuple) throws IOException {
StreamEvaluator colEval1 = subEvaluators.get(0);
List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
double[] vals = new double[numbers1.size()];
for(int i=0; i<vals.length; i++) {
vals[i] = numbers1.get(i).doubleValue();
}
if(subEvaluators.size() == 2) {
StreamEvaluator lengthEval = subEvaluators.get(1);
Number lengthNum = (Number)lengthEval.evaluate(tuple);
int length = lengthNum.intValue();
vals = Arrays.copyOf(vals, length);
} else {
vals = Arrays.copyOf(vals, vals.length);
}
List<Number> copyOf = new ArrayList(vals.length);
for(int i=0; i<vals.length; i++) {
copyOf.add(vals[i]);
}
return copyOf;
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.List;
import org.apache.commons.math3.ml.distance.EuclideanDistance;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class DistanceEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public DistanceEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public Number evaluate(Tuple tuple) throws IOException {
StreamEvaluator colEval1 = subEvaluators.get(0);
StreamEvaluator colEval2 = subEvaluators.get(1);
List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
List<Number> numbers2 = (List<Number>)colEval2.evaluate(tuple);
double[] column1 = new double[numbers1.size()];
double[] column2 = new double[numbers2.size()];
for(int i=0; i<numbers1.size(); i++) {
column1[i] = numbers1.get(i).doubleValue();
}
for(int i=0; i<numbers2.size(); i++) {
column2[i] = numbers2.get(i).doubleValue();
}
EuclideanDistance distance = new EuclideanDistance();
return distance.compute(column1, column2);
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,129 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
import org.apache.commons.math3.random.EmpiricalDistribution;
import org.apache.commons.math3.stat.descriptive.StatisticalSummary;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class EmpiricalDistributionEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public EmpiricalDistributionEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public Tuple evaluate(Tuple tuple) throws IOException {
if(subEvaluators.size() != 1) {
throw new IOException("Empirical dist expects 1 column as a parameters");
}
StreamEvaluator colEval1 = subEvaluators.get(0);
List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
double[] column1 = new double[numbers1.size()];
for(int i=0; i<numbers1.size(); i++) {
column1[i] = numbers1.get(i).doubleValue();
}
Arrays.sort(column1);
EmpiricalDistribution empiricalDistribution = new EmpiricalDistribution();
empiricalDistribution.load(column1);
Map map = new HashMap();
StatisticalSummary statisticalSummary = empiricalDistribution.getSampleStats();
map.put("max", statisticalSummary.getMax());
map.put("mean", statisticalSummary.getMean());
map.put("min", statisticalSummary.getMin());
map.put("stdev", statisticalSummary.getStandardDeviation());
map.put("sum", statisticalSummary.getSum());
map.put("N", statisticalSummary.getN());
map.put("var", statisticalSummary.getVariance());
return new EmpiricalDistributionTuple(empiricalDistribution, column1, map);
}
public static class EmpiricalDistributionTuple extends Tuple {
private EmpiricalDistribution empiricalDistribution;
private double[] backingArray;
public EmpiricalDistributionTuple(EmpiricalDistribution empiricalDistribution, double[] backingArray, Map map) {
super(map);
this.empiricalDistribution = empiricalDistribution;
this.backingArray = backingArray;
}
public double percentile(double d) {
int slot = Arrays.binarySearch(backingArray, d);
if(slot == 0) {
return 0.0;
}
if(slot < 0) {
if(slot == -1) {
return 0.0D;
} else {
//Not a direct hit
slot = Math.abs(slot);
--slot;
if(slot == backingArray.length) {
return 1.0D;
} else {
return (this.empiricalDistribution.cumulativeProbability(backingArray[slot]));
}
}
} else {
return this.empiricalDistribution.cumulativeProbability(backingArray[slot]);
}
}
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.List;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class LengthEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public LengthEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public Number evaluate(Tuple tuple) throws IOException {
StreamEvaluator colEval1 = subEvaluators.get(0);
List<Number> numbers = (List<Number>)colEval1.evaluate(tuple);
return numbers.size();
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class PercentileEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public PercentileEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public Number evaluate(Tuple tuple) throws IOException {
if(subEvaluators.size() != 2) {
throw new IOException("Percentile expects 2 parameters: a regression result and a number");
}
StreamEvaluator r = subEvaluators.get(0);
StreamEvaluator d = subEvaluators.get(1);
EmpiricalDistributionEvaluator.EmpiricalDistributionTuple e = (EmpiricalDistributionEvaluator.EmpiricalDistributionTuple)r.evaluate(tuple);
Number n = (Number)d.evaluate(tuple);
return e.percentile(n.doubleValue());
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.stat.ranking.NaturalRanking;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class RankEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public RankEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public List<Number> evaluate(Tuple tuple) throws IOException {
StreamEvaluator colEval = subEvaluators.get(0);
List<Number> numbers = (List<Number>)colEval.evaluate(tuple);
double[] values = new double[numbers.size()];
for(int i=0; i<numbers.size(); i++) {
values[i] = numbers.get(i).doubleValue();
}
NaturalRanking rank = new NaturalRanking();
double[] ranked = rank.rank(values);
List<Number> rankedList = new ArrayList();
for(int i=0; i<numbers.size(); i++) {
rankedList.add(ranked[i]);
}
return rankedList;
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.client.solrj.io.stream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.util.MathArrays;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.eval.ComplexEvaluator;
import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
import org.apache.solr.client.solrj.io.stream.expr.Explanation;
import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
public class ScaleEvaluator extends ComplexEvaluator implements Expressible {
private static final long serialVersionUID = 1;
public ScaleEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
super(expression, factory);
}
public List<Number> evaluate(Tuple tuple) throws IOException {
StreamEvaluator numEval = subEvaluators.get(0);
StreamEvaluator colEval1 = subEvaluators.get(1);
Number num = (Number)numEval.evaluate(tuple);
List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
double[] column1 = new double[numbers1.size()];
for(int i=0; i<numbers1.size(); i++) {
column1[i] = numbers1.get(i).doubleValue();
}
double[] scaled = MathArrays.scale(num.doubleValue(), column1);
List<Number> scaledList = new ArrayList(scaled.length);
for(double d : scaled) {
scaledList.add(d);
}
return scaledList;
}
@Override
public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
return expression;
}
@Override
public Explanation toExplanation(StreamFactory factory) throws IOException {
return new Explanation(nodeId.toString())
.withExpressionType(ExpressionType.EVALUATOR)
.withFunctionName(factory.getFunctionName(getClass()))
.withImplementingClass(getClass().getName())
.withExpression(toExpression(factory).toString());
}
}

View File

@ -354,25 +354,6 @@ public class SchemaRequest extends AbstractSchemaRequest<SchemaResponse> {
}
}
/**
* Retrieves the default operator if it is defined in the schema.
*/
public static class DefaultQueryOperator extends AbstractSchemaRequest<SchemaResponse.DefaultQueryOperatorResponse> {
public DefaultQueryOperator() {
this(null);
}
public DefaultQueryOperator(SolrParams q) {
super(METHOD.GET, "/schema/solrqueryparser/defaultoperator", q);
}
@Override
protected SchemaResponse.DefaultQueryOperatorResponse createResponse(SolrClient client) {
return new SchemaResponse.DefaultQueryOperatorResponse();
}
}
/**
* Adds a new field definition to the schema.
* If the field already exists, the method {@link #process(SolrClient, String)} will fail.

View File

@ -31,8 +31,6 @@ public class SchemaRepresentation {
private String defaultSearchField;
private String defaultOperator;
private Map<String, Object> similarity;
private List<Map<String, Object>> fields;
@ -76,14 +74,6 @@ public class SchemaRepresentation {
this.defaultSearchField = defaultSearchField;
}
public String getDefaultOperator() {
return defaultOperator;
}
public void setDefaultOperator(String defaultOperator) {
this.defaultOperator = defaultOperator;
}
public Map<String, Object> getSimilarity() {
return similarity;
}

View File

@ -138,7 +138,6 @@ public class SchemaResponse extends SolrResponseBase {
schemaRepresentation.setVersion(getSchemaVersion(schemaObj));
schemaRepresentation.setUniqueKey(getSchemaUniqueKey(schemaObj));
schemaRepresentation.setDefaultSearchField(getDefaultSearchField(schemaObj));
schemaRepresentation.setDefaultOperator(getDefaultOperator(schemaObj));
schemaRepresentation.setSimilarity(getSimilarity(schemaObj));
schemaRepresentation.setFields(getFields(schemaObj));
schemaRepresentation.setDynamicFields(getDynamicFields(schemaObj));
@ -170,14 +169,6 @@ public class SchemaResponse extends SolrResponseBase {
return similarity;
}
@SuppressWarnings("unchecked")
private static String getDefaultOperator(Map schemaNamedList) {
String defaultOperator = null;
NamedList<Object> solrQueryParserProperties = (NamedList<Object>) schemaNamedList.get("solrQueryParser");
if (solrQueryParserProperties != null) defaultOperator = (String) solrQueryParserProperties.get("defaultOperator");
return defaultOperator;
}
@SuppressWarnings("unchecked")
private static List<Map<String, Object>> getFields(Map schemaNamedList) {
List<Map<String, Object>> fieldsAttributes = new LinkedList<>();
@ -416,25 +407,6 @@ public class SchemaResponse extends SolrResponseBase {
}
public static class DefaultQueryOperatorResponse extends SolrResponseBase {
private String defaultOperator;
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
public void setResponse(NamedList<Object> response) {
super.setResponse(response);
defaultOperator = (String) response.get("defaultOperator");
}
public String getDefaultOperator() {
return defaultOperator;
}
}
public static class CopyFieldsResponse extends SolrResponseBase {
List<Map<String, Object>> copyFields;

View File

@ -5299,6 +5299,55 @@ public class StreamExpressionTest extends SolrCloudTestCase {
assertTrue(tuples.get(0).getDouble("cov").equals(-625.0D));
}
@Test
public void testDistance() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
int i=0;
while(i<50) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2016", "5", "1"), "price_f", "400.00");
}
while(i<100) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2015", "5", "1"), "price_f", "300.0");
}
while(i<150) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2014", "5", "1"), "price_f", "500.0");
}
while(i<250) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2013", "5", "1"), "price_f", "100.00");
}
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr = "timeseries("+COLLECTIONORALIAS+", q=\"*:*\", start=\"2013-01-01T01:00:00.000Z\", " +
"end=\"2016-12-01T01:00:00.000Z\", " +
"gap=\"+1YEAR\", " +
"field=\"test_dt\", " +
"count(*), sum(price_f), max(price_f), min(price_f))";
String cexpr = "let(a="+expr+", b=select("+expr+",mult(-1, count(*)) as nvalue), c=col(a, count(*)), d=col(b, nvalue), tuple(colc=c, cold=d, cov=cov(c,d), dist=distance(c,d)))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
assertTrue(tuples.get(0).getDouble("cov").equals(-625.0D));
assertTrue(tuples.get(0).getDouble("dist").equals(264.5751311064591D));
}
@Test
public void testReverse() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
@ -5350,6 +5399,235 @@ public class StreamExpressionTest extends SolrCloudTestCase {
}
@Test
public void testCopyOf() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
int i=0;
while(i<50) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2016", "5", "1"), "price_f", "400.00");
}
while(i<100) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2015", "5", "1"), "price_f", "300.0");
}
while(i<150) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2014", "5", "1"), "price_f", "500.0");
}
while(i<250) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2013", "5", "1"), "price_f", "100.00");
}
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr = "timeseries("+COLLECTIONORALIAS+", q=\"*:*\", start=\"2013-01-01T01:00:00.000Z\", " +
"end=\"2016-12-01T01:00:00.000Z\", " +
"gap=\"+1YEAR\", " +
"field=\"test_dt\", " +
"count(*), sum(price_f), max(price_f), min(price_f))";
String cexpr = "let(a="+expr+", c=col(a, max(price_f)), tuple(copy1=copyOf(c, 10), copy2=copyOf(c), copy3=copyOf(c, 2) ))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
List<Number> copy1 = (List<Number>)tuples.get(0).get("copy1");
assertTrue(copy1.size() == 10);
assertTrue(copy1.get(0).doubleValue() == 100D);
assertTrue(copy1.get(1).doubleValue() == 500D);
assertTrue(copy1.get(2).doubleValue() == 300D);
assertTrue(copy1.get(3).doubleValue() == 400D);
assertTrue(copy1.get(4).doubleValue() == 0D);
assertTrue(copy1.get(5).doubleValue() == 0D);
assertTrue(copy1.get(6).doubleValue() == 0D);
assertTrue(copy1.get(7).doubleValue() == 0D);
assertTrue(copy1.get(8).doubleValue() == 0D);
assertTrue(copy1.get(9).doubleValue() == 0D);
List<Number> copy2 = (List<Number>)tuples.get(0).get("copy2");
assertTrue(copy2.size() == 4);
assertTrue(copy2.get(0).doubleValue() == 100D);
assertTrue(copy2.get(1).doubleValue() == 500D);
assertTrue(copy2.get(2).doubleValue() == 300D);
assertTrue(copy2.get(3).doubleValue() == 400D);
List<Number> copy3 = (List<Number>)tuples.get(0).get("copy3");
assertTrue(copy3.size() == 2);
assertTrue(copy3.get(0).doubleValue() == 100D);
assertTrue(copy3.get(1).doubleValue() == 500D);
}
@Test
public void testPercentiles() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
int i=0;
while(i<100) {
i=i+2;
updateRequest.add(id, "id_"+(i), "price_f", Integer.toString(i));
}
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr = "search("+COLLECTIONORALIAS+", q=\"*:*\", fl=\"price_f\", sort=\"price_f asc\", rows=\"200\")";
String cexpr = "let(a="+expr+", c=col(a, price_f), e=empiricalDistribution(c), " +
"tuple(p1=percentile(e, 88), " +
"p2=percentile(e, 2), " +
"p3=percentile(e, 99), " +
"p4=percentile(e, 77), " +
"p5=percentile(e, 98)))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
double percentile1 = tuples.get(0).getDouble("p1");
double percentile2 = tuples.get(0).getDouble("p2");
double percentile3 = tuples.get(0).getDouble("p3");
double percentile4 = tuples.get(0).getDouble("p4");
double percentile5 = tuples.get(0).getDouble("p5");
assertEquals(.88D, percentile1, 0.001);
assertEquals(.0D, percentile2, 0.001);
assertEquals(1.0D, percentile3, 0.001);
assertEquals(.78D, percentile4, 0.001);
assertEquals(.98D, percentile5, 0.001);
}
@Test
public void testRankTransform() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
int i=0;
while(i<50) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2016", "5", "1"), "price_f", "400.00");
}
while(i<100) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2015", "5", "1"), "price_f", "300.0");
}
while(i<150) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2014", "5", "1"), "price_f", "500.0");
}
while(i<250) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2013", "5", "1"), "price_f", "100.00");
}
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr = "timeseries("+COLLECTIONORALIAS+", q=\"*:*\", start=\"2013-01-01T01:00:00.000Z\", " +
"end=\"2016-12-01T01:00:00.000Z\", " +
"gap=\"+1YEAR\", " +
"field=\"test_dt\", " +
"count(*), sum(price_f), max(price_f), min(price_f))";
String cexpr = "let(a="+expr+", c=col(a, max(price_f)), tuple(reverse=rev(c), ranked=rank(c)))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
List<Number> reverse = (List<Number>)tuples.get(0).get("reverse");
assertTrue(reverse.size() == 4);
assertTrue(reverse.get(0).doubleValue() == 400D);
assertTrue(reverse.get(1).doubleValue() == 300D);
assertTrue(reverse.get(2).doubleValue() == 500D);
assertTrue(reverse.get(3).doubleValue() == 100D);
List<Number> ranked = (List<Number>)tuples.get(0).get("ranked");
assertTrue(ranked.size() == 4);
assertTrue(ranked.get(0).doubleValue() == 1D);
assertTrue(ranked.get(1).doubleValue() == 4D);
assertTrue(ranked.get(2).doubleValue() == 2D);
assertTrue(ranked.get(3).doubleValue() == 3D);
}
@Test
public void testScale() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
int i=0;
while(i<50) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2016", "5", "1"), "price_f", "400.00");
}
while(i<100) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2015", "5", "1"), "price_f", "300.0");
}
while(i<150) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2014", "5", "1"), "price_f", "500.0");
}
while(i<250) {
updateRequest.add(id, "id_"+(++i),"test_dt", getDateString("2013", "5", "1"), "price_f", "100.00");
}
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr = "timeseries("+COLLECTIONORALIAS+", q=\"*:*\", start=\"2013-01-01T01:00:00.000Z\", " +
"end=\"2016-12-01T01:00:00.000Z\", " +
"gap=\"+1YEAR\", " +
"field=\"test_dt\", " +
"count(*), sum(price_f), max(price_f), min(price_f))";
String cexpr = "let(a="+expr+", c=col(a, max(price_f)), tuple(reverse=rev(c), scaled=scale(2, c)))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
List<Number> reverse = (List<Number>)tuples.get(0).get("reverse");
assertTrue(reverse.size() == 4);
assertTrue(reverse.get(0).doubleValue() == 400D);
assertTrue(reverse.get(1).doubleValue() == 300D);
assertTrue(reverse.get(2).doubleValue() == 500D);
assertTrue(reverse.get(3).doubleValue() == 100D);
List<Number> ranked = (List<Number>)tuples.get(0).get("scaled");
assertTrue(ranked.size() == 4);
assertTrue(ranked.get(0).doubleValue() == 200D);
assertTrue(ranked.get(1).doubleValue() == 1000D);
assertTrue(ranked.get(2).doubleValue() == 600D);
assertTrue(ranked.get(3).doubleValue() == 800D);
}
@Test
public void testConvolution() throws Exception {
@ -5453,6 +5731,58 @@ public class StreamExpressionTest extends SolrCloudTestCase {
assertTrue(prediction == 600.0D);
}
@Test
public void testLength() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.add(id, "1", "price_f", "100.0", "col_s", "a", "order_i", "1");
updateRequest.add(id, "2", "price_f", "200.0", "col_s", "a", "order_i", "2");
updateRequest.add(id, "3", "price_f", "300.0", "col_s", "a", "order_i", "3");
updateRequest.add(id, "4", "price_f", "100.0", "col_s", "a", "order_i", "4");
updateRequest.add(id, "5", "price_f", "200.0", "col_s", "a", "order_i", "5");
updateRequest.add(id, "6", "price_f", "400.0", "col_s", "a", "order_i", "6");
updateRequest.add(id, "7", "price_f", "600.0", "col_s", "a", "order_i", "7");
updateRequest.add(id, "8", "price_f", "200.0", "col_s", "b", "order_i", "1");
updateRequest.add(id, "9", "price_f", "400.0", "col_s", "b", "order_i", "2");
updateRequest.add(id, "10", "price_f", "600.0", "col_s", "b", "order_i", "3");
updateRequest.add(id, "11", "price_f", "200.0", "col_s", "b", "order_i", "4");
updateRequest.add(id, "12", "price_f", "400.0", "col_s", "b", "order_i", "5");
updateRequest.add(id, "13", "price_f", "800.0", "col_s", "b", "order_i", "6");
updateRequest.add(id, "14", "price_f", "1200.0", "col_s", "b", "order_i", "7");
updateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
String expr1 = "search("+COLLECTIONORALIAS+", q=\"col_s:a\", fl=\"price_f, order_i\", sort=\"order_i asc\")";
String expr2 = "search("+COLLECTIONORALIAS+", q=\"col_s:b\", fl=\"price_f, order_i\", sort=\"order_i asc\")";
String cexpr = "let(a="+expr1+", b="+expr2+", c=col(a, price_f), d=col(b, price_f), e=regress(c, d), tuple(regress=e, p=predict(e, 300), l=length(d)))";
ModifiableSolrParams paramsLoc = new ModifiableSolrParams();
paramsLoc.set("expr", cexpr);
paramsLoc.set("qt", "/stream");
String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS;
TupleStream solrStream = new SolrStream(url, paramsLoc);
StreamContext context = new StreamContext();
solrStream.setStreamContext(context);
List<Tuple> tuples = getTuples(solrStream);
assertTrue(tuples.size() == 1);
Tuple tuple = tuples.get(0);
Map regression = (Map)tuple.get("regress");
double slope = (double)regression.get("slope");
double intercept= (double) regression.get("intercept");
double length = tuple.getDouble("l");
assertTrue(slope == 2.0D);
assertTrue(intercept == 0.0D);
double prediction = tuple.getDouble("p");
assertTrue(prediction == 600.0D);
assertTrue(length == 7);
}
@Test
public void testNormalize() throws Exception {
UpdateRequest updateRequest = new UpdateRequest();

View File

@ -242,16 +242,6 @@ public class SchemaTest extends RestTestBase {
globalSimilarityResponse.getSimilarity().get("class"));
}
@Test
public void testGetDefaultQueryOperatorAccuracy() throws Exception {
SchemaRequest.DefaultQueryOperator defaultQueryOperatorRequest =
new SchemaRequest.DefaultQueryOperator();
SchemaResponse.DefaultQueryOperatorResponse defaultQueryOperatorResponse =
defaultQueryOperatorRequest.process(getSolrClient());
assertValidSchemaResponse(defaultQueryOperatorResponse);
assertEquals("OR", defaultQueryOperatorResponse.getDefaultOperator());
}
@Test
public void testAddFieldAccuracy() throws Exception {
SchemaRequest.Fields fieldsSchemaRequest = new SchemaRequest.Fields();