fix eol-style

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1305339 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Muir 2012-03-26 12:58:58 +00:00
parent f5770479e3
commit a29a14698e
24 changed files with 2523 additions and 2523 deletions

View File

@ -1,10 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="ICU library"> <library name="ICU library">
<CLASSES> <CLASSES>
<root url="file://$PROJECT_DIR$/modules/analysis/icu/lib" /> <root url="file://$PROJECT_DIR$/modules/analysis/icu/lib" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES /> <SOURCES />
<jarDirectory url="file://$PROJECT_DIR$/modules/analysis/icu/lib" recursive="false" /> <jarDirectory url="file://$PROJECT_DIR$/modules/analysis/icu/lib" recursive="false" />
</library> </library>
</component> </component>

View File

@ -1,56 +1,56 @@
<project name="custom-tasks"> <project name="custom-tasks">
<description> <description>
This file is designed for importing into a main build file, and not intended This file is designed for importing into a main build file, and not intended
for standalone use. for standalone use.
</description> </description>
<macrodef name="license-check-macro"> <macrodef name="license-check-macro">
<attribute name="dir" /> <attribute name="dir" />
<element name="additional-excludes" optional="true" /> <element name="additional-excludes" optional="true" />
<element name="additional-filters" optional="true" /> <element name="additional-filters" optional="true" />
<sequential> <sequential>
<!-- LICENSE and NOTICE verification macro. --> <!-- LICENSE and NOTICE verification macro. -->
<dirname file="${ant.file.custom-tasks}" property="custom-tasks.dir"/> <dirname file="${ant.file.custom-tasks}" property="custom-tasks.dir"/>
<taskdef resource="lucene-solr.antlib.xml"> <taskdef resource="lucene-solr.antlib.xml">
<classpath> <classpath>
<pathelement location="${custom-tasks.dir}/../build/tools/classes/java" /> <pathelement location="${custom-tasks.dir}/../build/tools/classes/java" />
</classpath> </classpath>
</taskdef> </taskdef>
<echo>License check under: @{dir}</echo> <echo>License check under: @{dir}</echo>
<licenses> <licenses>
<fileset dir="@{dir}"> <fileset dir="@{dir}">
<include name="**/*.jar" /> <include name="**/*.jar" />
<!-- Speed up scanning a bit. --> <!-- Speed up scanning a bit. -->
<exclude name="**/.git/**" /> <exclude name="**/.git/**" />
<exclude name="**/.svn/**" /> <exclude name="**/.svn/**" />
<exclude name="**/bin/**" /> <exclude name="**/bin/**" />
<exclude name="**/build/**" /> <exclude name="**/build/**" />
<exclude name="**/dist/**" /> <exclude name="**/dist/**" />
<exclude name="**/src/**" /> <exclude name="**/src/**" />
<additional-excludes /> <additional-excludes />
</fileset> </fileset>
<licenseMapper> <licenseMapper>
<filtermapper id="license-mapper-defaults"> <filtermapper id="license-mapper-defaults">
<!-- Normalize input paths. --> <!-- Normalize input paths. -->
<replacestring from="\" to="/" /> <replacestring from="\" to="/" />
<replaceregex pattern="\.jar$" replace="" flags="gi" /> <replaceregex pattern="\.jar$" replace="" flags="gi" />
<!-- Some typical snapshot/minimalized JAR suffixes. --> <!-- Some typical snapshot/minimalized JAR suffixes. -->
<replaceregex pattern="-min$" replace="" flags="gi" /> <replaceregex pattern="-min$" replace="" flags="gi" />
<replaceregex pattern="SNAPSHOT$" replace="" flags="gi" /> <replaceregex pattern="SNAPSHOT$" replace="" flags="gi" />
<!-- Non-typical version patterns. --> <!-- Non-typical version patterns. -->
<additional-filters /> <additional-filters />
<replaceregex pattern="/xercesImpl([^/]+)$" replace="/xercesImpl" flags="gi" /> <replaceregex pattern="/xercesImpl([^/]+)$" replace="/xercesImpl" flags="gi" />
<!-- Typical version patterns. --> <!-- Typical version patterns. -->
<replaceregex pattern="\-(r)?([0-9\-\_\.])+(b(eta)?([0-9\-\.])*)?$" replace="" flags="gi" /> <replaceregex pattern="\-(r)?([0-9\-\_\.])+(b(eta)?([0-9\-\.])*)?$" replace="" flags="gi" />
</filtermapper> </filtermapper>
</licenseMapper> </licenseMapper>
</licenses> </licenses>
</sequential> </sequential>
</macrodef> </macrodef>
</project> </project>

View File

@ -1,110 +1,110 @@
package org.apache.lucene.analysis.icu; package org.apache.lucene.analysis.icu;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.text.DateFormat; import java.text.DateFormat;
import java.util.*; import java.util.*;
import com.ibm.icu.text.UnicodeSet; import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.text.UnicodeSetIterator; import com.ibm.icu.text.UnicodeSetIterator;
import com.ibm.icu.util.VersionInfo; import com.ibm.icu.util.VersionInfo;
/** creates a macro to augment jflex's unicode support for > BMP */ /** creates a macro to augment jflex's unicode support for > BMP */
public class GenerateHTMLStripCharFilterSupplementaryMacros { public class GenerateHTMLStripCharFilterSupplementaryMacros {
private static final UnicodeSet BMP = new UnicodeSet("[\u0000-\uFFFF]"); private static final UnicodeSet BMP = new UnicodeSet("[\u0000-\uFFFF]");
private static final String NL = System.getProperty("line.separator"); private static final String NL = System.getProperty("line.separator");
private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance
(DateFormat.FULL, DateFormat.FULL, Locale.US); (DateFormat.FULL, DateFormat.FULL, Locale.US);
static { static {
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
} }
private static final String APACHE_LICENSE private static final String APACHE_LICENSE
= "/*" + NL = "/*" + NL
+ " * Copyright 2010 The Apache Software Foundation." + NL + " * Copyright 2010 The Apache Software Foundation." + NL
+ " *" + NL + " *" + NL
+ " * Licensed under the Apache License, Version 2.0 (the \"License\");" + NL + " * Licensed under the Apache License, Version 2.0 (the \"License\");" + NL
+ " * you may not use this file except in compliance with the License." + NL + " * you may not use this file except in compliance with the License." + NL
+ " * You may obtain a copy of the License at" + NL + " * You may obtain a copy of the License at" + NL
+ " *" + NL + " *" + NL
+ " * http://www.apache.org/licenses/LICENSE-2.0" + NL + " * http://www.apache.org/licenses/LICENSE-2.0" + NL
+ " *" + NL + " *" + NL
+ " * Unless required by applicable law or agreed to in writing, software" + NL + " * Unless required by applicable law or agreed to in writing, software" + NL
+ " * distributed under the License is distributed on an \"AS IS\" BASIS," + NL + " * distributed under the License is distributed on an \"AS IS\" BASIS," + NL
+ " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." + NL + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." + NL
+ " * See the License for the specific language governing permissions and" + NL + " * See the License for the specific language governing permissions and" + NL
+ " * limitations under the License." + NL + " * limitations under the License." + NL
+ " */" + NL + NL; + " */" + NL + NL;
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
outputHeader(); outputHeader();
outputMacro("ID_Start_Supp", "[:ID_Start:]"); outputMacro("ID_Start_Supp", "[:ID_Start:]");
outputMacro("ID_Continue_Supp", "[:ID_Continue:]"); outputMacro("ID_Continue_Supp", "[:ID_Continue:]");
} }
static void outputHeader() { static void outputHeader() {
System.out.print(APACHE_LICENSE); System.out.print(APACHE_LICENSE);
System.out.print("// Generated using ICU4J " + VersionInfo.ICU_VERSION.toString() + " on "); System.out.print("// Generated using ICU4J " + VersionInfo.ICU_VERSION.toString() + " on ");
System.out.println(DATE_FORMAT.format(new Date())); System.out.println(DATE_FORMAT.format(new Date()));
System.out.println("// by " + GenerateHTMLStripCharFilterSupplementaryMacros.class.getName()); System.out.println("// by " + GenerateHTMLStripCharFilterSupplementaryMacros.class.getName());
System.out.print(NL + NL); System.out.print(NL + NL);
} }
// we have to carefully output the possibilities as compact utf-16 // we have to carefully output the possibilities as compact utf-16
// range expressions, or jflex will OOM! // range expressions, or jflex will OOM!
static void outputMacro(String name, String pattern) { static void outputMacro(String name, String pattern) {
UnicodeSet set = new UnicodeSet(pattern); UnicodeSet set = new UnicodeSet(pattern);
set.removeAll(BMP); set.removeAll(BMP);
System.out.println(name + " = ("); System.out.println(name + " = (");
// if the set is empty, we have to do this or jflex will barf // if the set is empty, we have to do this or jflex will barf
if (set.isEmpty()) { if (set.isEmpty()) {
System.out.println("\t []"); System.out.println("\t []");
} }
HashMap<Character,UnicodeSet> utf16ByLead = new HashMap<Character,UnicodeSet>(); HashMap<Character,UnicodeSet> utf16ByLead = new HashMap<Character,UnicodeSet>();
for (UnicodeSetIterator it = new UnicodeSetIterator(set); it.next();) { for (UnicodeSetIterator it = new UnicodeSetIterator(set); it.next();) {
char utf16[] = Character.toChars(it.codepoint); char utf16[] = Character.toChars(it.codepoint);
UnicodeSet trails = utf16ByLead.get(utf16[0]); UnicodeSet trails = utf16ByLead.get(utf16[0]);
if (trails == null) { if (trails == null) {
trails = new UnicodeSet(); trails = new UnicodeSet();
utf16ByLead.put(utf16[0], trails); utf16ByLead.put(utf16[0], trails);
} }
trails.add(utf16[1]); trails.add(utf16[1]);
} }
Map<String,UnicodeSet> utf16ByTrail = new HashMap<String,UnicodeSet>(); Map<String,UnicodeSet> utf16ByTrail = new HashMap<String,UnicodeSet>();
for (Map.Entry<Character,UnicodeSet> entry : utf16ByLead.entrySet()) { for (Map.Entry<Character,UnicodeSet> entry : utf16ByLead.entrySet()) {
String trail = entry.getValue().getRegexEquivalent(); String trail = entry.getValue().getRegexEquivalent();
UnicodeSet leads = utf16ByTrail.get(trail); UnicodeSet leads = utf16ByTrail.get(trail);
if (leads == null) { if (leads == null) {
leads = new UnicodeSet(); leads = new UnicodeSet();
utf16ByTrail.put(trail, leads); utf16ByTrail.put(trail, leads);
} }
leads.add(entry.getKey()); leads.add(entry.getKey());
} }
boolean isFirst = true; boolean isFirst = true;
for (Map.Entry<String,UnicodeSet> entry : utf16ByTrail.entrySet()) { for (Map.Entry<String,UnicodeSet> entry : utf16ByTrail.entrySet()) {
System.out.print( isFirst ? "\t " : "\t| "); System.out.print( isFirst ? "\t " : "\t| ");
isFirst = false; isFirst = false;
System.out.println(entry.getValue().getRegexEquivalent() + entry.getKey()); System.out.println(entry.getValue().getRegexEquivalent() + entry.getKey());
} }
System.out.println(")"); System.out.println(")");
} }
} }

View File

@ -1,33 +1,33 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project name="spatial" default="default"> <project name="spatial" default="default">
<description> <description>
Lucene Spatial Lucene Spatial
</description> </description>
<property name="build.dir" location="build/" /> <property name="build.dir" location="build/" />
<property name="dist.dir" location="dist/" /> <property name="dist.dir" location="dist/" />
<property name="maven.dist.dir" location="../dist/maven" /> <property name="maven.dist.dir" location="../dist/maven" />
<path id="additional.dependencies"> <path id="additional.dependencies">
<fileset dir="lib" includes="*.jar"/> <fileset dir="lib" includes="*.jar"/>
</path> </path>
<pathconvert property="project.classpath" <pathconvert property="project.classpath"
targetos="unix" targetos="unix"
refid="additional.dependencies" refid="additional.dependencies"
/> />
<import file="../../lucene/contrib/contrib-build.xml"/> <import file="../../lucene/contrib/contrib-build.xml"/>
<path id="classpath"> <path id="classpath">
<path refid="base.classpath"/> <path refid="base.classpath"/>
<pathelement path="${queries.jar}" /> <pathelement path="${queries.jar}" />
</path> </path>
<path id="test.classpath"> <path id="test.classpath">
<path refid="test.base.classpath" /> <path refid="test.base.classpath" />
<pathelement path="src/test-files" /> <pathelement path="src/test-files" />
</path> </path>
<target name="compile-core" depends="jar-queries,common.compile-core" /> <target name="compile-core" depends="jar-queries,common.compile-core" />
</project> </project>

View File

@ -1,22 +1,22 @@
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/** /**
* Prefix Tree Strategy * Prefix Tree Strategy
*/ */
package org.apache.lucene.spatial.prefix; package org.apache.lucene.spatial.prefix;

View File

@ -1,23 +1,23 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 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 not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<html> <html>
<head> <head>
<title>Apache Lucene Spatial Strategies</title> <title>Apache Lucene Spatial Strategies</title>
</head> </head>
<body> <body>
</body> </body>
</html> </html>

View File

@ -1,241 +1,241 @@
package org.apache.solr.handler.clustering.carrot2; package org.apache.solr.handler.clustering.carrot2;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.util.HashMap; import java.util.HashMap;
import org.apache.lucene.analysis.ar.ArabicNormalizer; import org.apache.lucene.analysis.ar.ArabicNormalizer;
import org.apache.lucene.analysis.ar.ArabicStemmer; import org.apache.lucene.analysis.ar.ArabicStemmer;
import org.carrot2.core.LanguageCode; import org.carrot2.core.LanguageCode;
import org.carrot2.text.linguistic.IStemmer; import org.carrot2.text.linguistic.IStemmer;
import org.carrot2.text.linguistic.IStemmerFactory; import org.carrot2.text.linguistic.IStemmerFactory;
import org.carrot2.util.ReflectionUtils; import org.carrot2.util.ReflectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.tartarus.snowball.SnowballProgram; import org.tartarus.snowball.SnowballProgram;
import org.tartarus.snowball.ext.DanishStemmer; import org.tartarus.snowball.ext.DanishStemmer;
import org.tartarus.snowball.ext.DutchStemmer; import org.tartarus.snowball.ext.DutchStemmer;
import org.tartarus.snowball.ext.EnglishStemmer; import org.tartarus.snowball.ext.EnglishStemmer;
import org.tartarus.snowball.ext.FinnishStemmer; import org.tartarus.snowball.ext.FinnishStemmer;
import org.tartarus.snowball.ext.FrenchStemmer; import org.tartarus.snowball.ext.FrenchStemmer;
import org.tartarus.snowball.ext.GermanStemmer; import org.tartarus.snowball.ext.GermanStemmer;
import org.tartarus.snowball.ext.HungarianStemmer; import org.tartarus.snowball.ext.HungarianStemmer;
import org.tartarus.snowball.ext.ItalianStemmer; import org.tartarus.snowball.ext.ItalianStemmer;
import org.tartarus.snowball.ext.NorwegianStemmer; import org.tartarus.snowball.ext.NorwegianStemmer;
import org.tartarus.snowball.ext.PortugueseStemmer; import org.tartarus.snowball.ext.PortugueseStemmer;
import org.tartarus.snowball.ext.RomanianStemmer; import org.tartarus.snowball.ext.RomanianStemmer;
import org.tartarus.snowball.ext.RussianStemmer; import org.tartarus.snowball.ext.RussianStemmer;
import org.tartarus.snowball.ext.SpanishStemmer; import org.tartarus.snowball.ext.SpanishStemmer;
import org.tartarus.snowball.ext.SwedishStemmer; import org.tartarus.snowball.ext.SwedishStemmer;
import org.tartarus.snowball.ext.TurkishStemmer; import org.tartarus.snowball.ext.TurkishStemmer;
/** /**
* An implementation of Carrot2's {@link IStemmerFactory} based on Lucene's * An implementation of Carrot2's {@link IStemmerFactory} based on Lucene's
* APIs. Should the relevant Lucene APIs need to change, the changes can be made * APIs. Should the relevant Lucene APIs need to change, the changes can be made
* in this class. * in this class.
*/ */
public class LuceneCarrot2StemmerFactory implements IStemmerFactory { public class LuceneCarrot2StemmerFactory implements IStemmerFactory {
final static Logger logger = org.slf4j.LoggerFactory final static Logger logger = org.slf4j.LoggerFactory
.getLogger(LuceneCarrot2StemmerFactory.class); .getLogger(LuceneCarrot2StemmerFactory.class);
@Override @Override
public IStemmer getStemmer(LanguageCode language) { public IStemmer getStemmer(LanguageCode language) {
switch (language) { switch (language) {
case ARABIC: case ARABIC:
return ArabicStemmerFactory.createStemmer(); return ArabicStemmerFactory.createStemmer();
case CHINESE_SIMPLIFIED: case CHINESE_SIMPLIFIED:
return IdentityStemmer.INSTANCE; return IdentityStemmer.INSTANCE;
default: default:
/* /*
* For other languages, try to use snowball's stemming. * For other languages, try to use snowball's stemming.
*/ */
return SnowballStemmerFactory.createStemmer(language); return SnowballStemmerFactory.createStemmer(language);
} }
} }
/** /**
* Factory of {@link IStemmer} implementations from the <code>snowball</code> * Factory of {@link IStemmer} implementations from the <code>snowball</code>
* project. * project.
*/ */
private final static class SnowballStemmerFactory { private final static class SnowballStemmerFactory {
/** /**
* Static hard mapping from language codes to stemmer classes in Snowball. * Static hard mapping from language codes to stemmer classes in Snowball.
* This mapping is not dynamic because we want to keep the possibility to * This mapping is not dynamic because we want to keep the possibility to
* obfuscate these classes. * obfuscate these classes.
*/ */
private static HashMap<LanguageCode, Class<? extends SnowballProgram>> snowballStemmerClasses; private static HashMap<LanguageCode, Class<? extends SnowballProgram>> snowballStemmerClasses;
static { static {
snowballStemmerClasses = new HashMap<LanguageCode, Class<? extends SnowballProgram>>(); snowballStemmerClasses = new HashMap<LanguageCode, Class<? extends SnowballProgram>>();
snowballStemmerClasses.put(LanguageCode.DANISH, DanishStemmer.class); snowballStemmerClasses.put(LanguageCode.DANISH, DanishStemmer.class);
snowballStemmerClasses.put(LanguageCode.DUTCH, DutchStemmer.class); snowballStemmerClasses.put(LanguageCode.DUTCH, DutchStemmer.class);
snowballStemmerClasses.put(LanguageCode.ENGLISH, EnglishStemmer.class); snowballStemmerClasses.put(LanguageCode.ENGLISH, EnglishStemmer.class);
snowballStemmerClasses.put(LanguageCode.FINNISH, FinnishStemmer.class); snowballStemmerClasses.put(LanguageCode.FINNISH, FinnishStemmer.class);
snowballStemmerClasses.put(LanguageCode.FRENCH, FrenchStemmer.class); snowballStemmerClasses.put(LanguageCode.FRENCH, FrenchStemmer.class);
snowballStemmerClasses.put(LanguageCode.GERMAN, GermanStemmer.class); snowballStemmerClasses.put(LanguageCode.GERMAN, GermanStemmer.class);
snowballStemmerClasses snowballStemmerClasses
.put(LanguageCode.HUNGARIAN, HungarianStemmer.class); .put(LanguageCode.HUNGARIAN, HungarianStemmer.class);
snowballStemmerClasses.put(LanguageCode.ITALIAN, ItalianStemmer.class); snowballStemmerClasses.put(LanguageCode.ITALIAN, ItalianStemmer.class);
snowballStemmerClasses snowballStemmerClasses
.put(LanguageCode.NORWEGIAN, NorwegianStemmer.class); .put(LanguageCode.NORWEGIAN, NorwegianStemmer.class);
snowballStemmerClasses.put(LanguageCode.PORTUGUESE, snowballStemmerClasses.put(LanguageCode.PORTUGUESE,
PortugueseStemmer.class); PortugueseStemmer.class);
snowballStemmerClasses.put(LanguageCode.ROMANIAN, RomanianStemmer.class); snowballStemmerClasses.put(LanguageCode.ROMANIAN, RomanianStemmer.class);
snowballStemmerClasses.put(LanguageCode.RUSSIAN, RussianStemmer.class); snowballStemmerClasses.put(LanguageCode.RUSSIAN, RussianStemmer.class);
snowballStemmerClasses.put(LanguageCode.SPANISH, SpanishStemmer.class); snowballStemmerClasses.put(LanguageCode.SPANISH, SpanishStemmer.class);
snowballStemmerClasses.put(LanguageCode.SWEDISH, SwedishStemmer.class); snowballStemmerClasses.put(LanguageCode.SWEDISH, SwedishStemmer.class);
snowballStemmerClasses.put(LanguageCode.TURKISH, TurkishStemmer.class); snowballStemmerClasses.put(LanguageCode.TURKISH, TurkishStemmer.class);
} }
/** /**
* An adapter converting Snowball programs into {@link IStemmer} interface. * An adapter converting Snowball programs into {@link IStemmer} interface.
*/ */
private static class SnowballStemmerAdapter implements IStemmer { private static class SnowballStemmerAdapter implements IStemmer {
private final SnowballProgram snowballStemmer; private final SnowballProgram snowballStemmer;
public SnowballStemmerAdapter(SnowballProgram snowballStemmer) { public SnowballStemmerAdapter(SnowballProgram snowballStemmer) {
this.snowballStemmer = snowballStemmer; this.snowballStemmer = snowballStemmer;
} }
public CharSequence stem(CharSequence word) { public CharSequence stem(CharSequence word) {
snowballStemmer.setCurrent(word.toString()); snowballStemmer.setCurrent(word.toString());
if (snowballStemmer.stem()) { if (snowballStemmer.stem()) {
return snowballStemmer.getCurrent(); return snowballStemmer.getCurrent();
} else { } else {
return null; return null;
} }
} }
} }
/** /**
* Create and return an {@link IStemmer} adapter for a * Create and return an {@link IStemmer} adapter for a
* {@link SnowballProgram} for a given language code. An identity stemmer is * {@link SnowballProgram} for a given language code. An identity stemmer is
* returned for unknown languages. * returned for unknown languages.
*/ */
public static IStemmer createStemmer(LanguageCode language) { public static IStemmer createStemmer(LanguageCode language) {
final Class<? extends SnowballProgram> stemmerClazz = snowballStemmerClasses final Class<? extends SnowballProgram> stemmerClazz = snowballStemmerClasses
.get(language); .get(language);
if (stemmerClazz == null) { if (stemmerClazz == null) {
logger.warn("No Snowball stemmer class for: " + language.name() logger.warn("No Snowball stemmer class for: " + language.name()
+ ". Quality of clustering may be degraded."); + ". Quality of clustering may be degraded.");
return IdentityStemmer.INSTANCE; return IdentityStemmer.INSTANCE;
} }
try { try {
return new SnowballStemmerAdapter(stemmerClazz.newInstance()); return new SnowballStemmerAdapter(stemmerClazz.newInstance());
} catch (Exception e) { } catch (Exception e) {
logger.warn("Could not instantiate snowball stemmer" logger.warn("Could not instantiate snowball stemmer"
+ " for language: " + language.name() + " for language: " + language.name()
+ ". Quality of clustering may be degraded.", e); + ". Quality of clustering may be degraded.", e);
return IdentityStemmer.INSTANCE; return IdentityStemmer.INSTANCE;
} }
} }
} }
/** /**
* Factory of {@link IStemmer} implementations for the * Factory of {@link IStemmer} implementations for the
* {@link LanguageCode#ARABIC} language. Requires <code>lucene-contrib</code> * {@link LanguageCode#ARABIC} language. Requires <code>lucene-contrib</code>
* to be present in classpath, otherwise an empty (identity) stemmer is * to be present in classpath, otherwise an empty (identity) stemmer is
* returned. * returned.
*/ */
private static class ArabicStemmerFactory { private static class ArabicStemmerFactory {
static { static {
try { try {
ReflectionUtils.classForName(ArabicStemmer.class.getName(), false); ReflectionUtils.classForName(ArabicStemmer.class.getName(), false);
ReflectionUtils.classForName(ArabicNormalizer.class.getName(), false); ReflectionUtils.classForName(ArabicNormalizer.class.getName(), false);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
logger logger
.warn( .warn(
"Could not instantiate Lucene stemmer for Arabic, clustering quality " "Could not instantiate Lucene stemmer for Arabic, clustering quality "
+ "of Arabic content may be degraded. For best quality clusters, " + "of Arabic content may be degraded. For best quality clusters, "
+ "make sure Lucene's Arabic analyzer JAR is in the classpath", + "make sure Lucene's Arabic analyzer JAR is in the classpath",
e); e);
} }
} }
/** /**
* Adapter to lucene-contrib Arabic analyzers. * Adapter to lucene-contrib Arabic analyzers.
*/ */
private static class LuceneStemmerAdapter implements IStemmer { private static class LuceneStemmerAdapter implements IStemmer {
private final org.apache.lucene.analysis.ar.ArabicStemmer delegate; private final org.apache.lucene.analysis.ar.ArabicStemmer delegate;
private final org.apache.lucene.analysis.ar.ArabicNormalizer normalizer; private final org.apache.lucene.analysis.ar.ArabicNormalizer normalizer;
private char[] buffer = new char[0]; private char[] buffer = new char[0];
private LuceneStemmerAdapter() throws Exception { private LuceneStemmerAdapter() throws Exception {
delegate = new org.apache.lucene.analysis.ar.ArabicStemmer(); delegate = new org.apache.lucene.analysis.ar.ArabicStemmer();
normalizer = new org.apache.lucene.analysis.ar.ArabicNormalizer(); normalizer = new org.apache.lucene.analysis.ar.ArabicNormalizer();
} }
public CharSequence stem(CharSequence word) { public CharSequence stem(CharSequence word) {
if (word.length() > buffer.length) { if (word.length() > buffer.length) {
buffer = new char[word.length()]; buffer = new char[word.length()];
} }
for (int i = 0; i < word.length(); i++) { for (int i = 0; i < word.length(); i++) {
buffer[i] = word.charAt(i); buffer[i] = word.charAt(i);
} }
int newLen = normalizer.normalize(buffer, word.length()); int newLen = normalizer.normalize(buffer, word.length());
newLen = delegate.stem(buffer, newLen); newLen = delegate.stem(buffer, newLen);
if (newLen != word.length() || !equals(buffer, newLen, word)) { if (newLen != word.length() || !equals(buffer, newLen, word)) {
return CharBuffer.wrap(buffer, 0, newLen); return CharBuffer.wrap(buffer, 0, newLen);
} }
// Same-same. // Same-same.
return null; return null;
} }
private boolean equals(char[] buffer, int len, CharSequence word) { private boolean equals(char[] buffer, int len, CharSequence word) {
assert len == word.length(); assert len == word.length();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (buffer[i] != word.charAt(i)) if (buffer[i] != word.charAt(i))
return false; return false;
} }
return true; return true;
} }
} }
public static IStemmer createStemmer() { public static IStemmer createStemmer() {
try { try {
return new LuceneStemmerAdapter(); return new LuceneStemmerAdapter();
} catch (Throwable e) { } catch (Throwable e) {
return IdentityStemmer.INSTANCE; return IdentityStemmer.INSTANCE;
} }
} }
} }
/** /**
* An implementation of {@link IStemmer} that always returns <code>null</code> * An implementation of {@link IStemmer} that always returns <code>null</code>
* which means no stemming. * which means no stemming.
*/ */
private static class IdentityStemmer implements IStemmer { private static class IdentityStemmer implements IStemmer {
private final static IdentityStemmer INSTANCE = new IdentityStemmer(); private final static IdentityStemmer INSTANCE = new IdentityStemmer();
@Override @Override
public CharSequence stem(CharSequence word) { public CharSequence stem(CharSequence word) {
return null; return null;
} }
} }
} }

View File

@ -1,156 +1,156 @@
package org.apache.solr.handler.clustering.carrot2; package org.apache.solr.handler.clustering.carrot2;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.carrot2.core.LanguageCode; import org.carrot2.core.LanguageCode;
import org.carrot2.text.analysis.ExtendedWhitespaceTokenizer; import org.carrot2.text.analysis.ExtendedWhitespaceTokenizer;
import org.carrot2.text.analysis.ITokenizer; import org.carrot2.text.analysis.ITokenizer;
import org.carrot2.text.linguistic.ITokenizerFactory; import org.carrot2.text.linguistic.ITokenizerFactory;
import org.carrot2.text.util.MutableCharArray; import org.carrot2.text.util.MutableCharArray;
import org.carrot2.util.ExceptionUtils; import org.carrot2.util.ExceptionUtils;
import org.carrot2.util.ReflectionUtils; import org.carrot2.util.ReflectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
/** /**
* An implementation of Carrot2's {@link ITokenizerFactory} based on Lucene's * An implementation of Carrot2's {@link ITokenizerFactory} based on Lucene's
* Smart Chinese tokenizer. If Smart Chinese tokenizer is not available in * Smart Chinese tokenizer. If Smart Chinese tokenizer is not available in
* classpath at runtime, the default Carrot2's tokenizer is used. Should the * classpath at runtime, the default Carrot2's tokenizer is used. Should the
* Lucene APIs need to change, the changes can be made in this class. * Lucene APIs need to change, the changes can be made in this class.
*/ */
public class LuceneCarrot2TokenizerFactory implements ITokenizerFactory { public class LuceneCarrot2TokenizerFactory implements ITokenizerFactory {
final static Logger logger = org.slf4j.LoggerFactory final static Logger logger = org.slf4j.LoggerFactory
.getLogger(LuceneCarrot2TokenizerFactory.class); .getLogger(LuceneCarrot2TokenizerFactory.class);
@Override @Override
public ITokenizer getTokenizer(LanguageCode language) { public ITokenizer getTokenizer(LanguageCode language) {
switch (language) { switch (language) {
case CHINESE_SIMPLIFIED: case CHINESE_SIMPLIFIED:
return ChineseTokenizerFactory.createTokenizer(); return ChineseTokenizerFactory.createTokenizer();
/* /*
* We use our own analyzer for Arabic. Lucene's version has special * We use our own analyzer for Arabic. Lucene's version has special
* support for Nonspacing-Mark characters (see * support for Nonspacing-Mark characters (see
* http://www.fileformat.info/info/unicode/category/Mn/index.htm), but we * http://www.fileformat.info/info/unicode/category/Mn/index.htm), but we
* have them included as letters in the parser. * have them included as letters in the parser.
*/ */
case ARABIC: case ARABIC:
// Intentional fall-through. // Intentional fall-through.
default: default:
return new ExtendedWhitespaceTokenizer(); return new ExtendedWhitespaceTokenizer();
} }
} }
/** /**
* Creates tokenizers that adapt Lucene's Smart Chinese Tokenizer to Carrot2's * Creates tokenizers that adapt Lucene's Smart Chinese Tokenizer to Carrot2's
* {@link ITokenizer}. If Smart Chinese is not available in the classpath, the * {@link ITokenizer}. If Smart Chinese is not available in the classpath, the
* factory will fall back to the default white space tokenizer. * factory will fall back to the default white space tokenizer.
*/ */
private static final class ChineseTokenizerFactory { private static final class ChineseTokenizerFactory {
static { static {
try { try {
ReflectionUtils.classForName( ReflectionUtils.classForName(
"org.apache.lucene.analysis.cn.smart.WordTokenFilter", false); "org.apache.lucene.analysis.cn.smart.WordTokenFilter", false);
ReflectionUtils.classForName( ReflectionUtils.classForName(
"org.apache.lucene.analysis.cn.smart.SentenceTokenizer", false); "org.apache.lucene.analysis.cn.smart.SentenceTokenizer", false);
} catch (Throwable e) { } catch (Throwable e) {
logger logger
.warn("Could not instantiate Smart Chinese Analyzer, clustering quality " .warn("Could not instantiate Smart Chinese Analyzer, clustering quality "
+ "of Chinese content may be degraded. For best quality clusters, " + "of Chinese content may be degraded. For best quality clusters, "
+ "make sure Lucene's Smart Chinese Analyzer JAR is in the classpath"); + "make sure Lucene's Smart Chinese Analyzer JAR is in the classpath");
} }
} }
static ITokenizer createTokenizer() { static ITokenizer createTokenizer() {
try { try {
return new ChineseTokenizer(); return new ChineseTokenizer();
} catch (Throwable e) { } catch (Throwable e) {
return new ExtendedWhitespaceTokenizer(); return new ExtendedWhitespaceTokenizer();
} }
} }
private final static class ChineseTokenizer implements ITokenizer { private final static class ChineseTokenizer implements ITokenizer {
private final static Pattern numeric = Pattern private final static Pattern numeric = Pattern
.compile("[\\-+'$]?\\d+([:\\-/,.]?\\d+)*[%$]?"); .compile("[\\-+'$]?\\d+([:\\-/,.]?\\d+)*[%$]?");
private Tokenizer sentenceTokenizer; private Tokenizer sentenceTokenizer;
private TokenStream wordTokenFilter; private TokenStream wordTokenFilter;
private CharTermAttribute term = null; private CharTermAttribute term = null;
private final MutableCharArray tempCharSequence; private final MutableCharArray tempCharSequence;
private final Class<?> tokenFilterClass; private final Class<?> tokenFilterClass;
private ChineseTokenizer() throws Exception { private ChineseTokenizer() throws Exception {
this.tempCharSequence = new MutableCharArray(new char[0]); this.tempCharSequence = new MutableCharArray(new char[0]);
// As Smart Chinese is not available during compile time, // As Smart Chinese is not available during compile time,
// we need to resort to reflection. // we need to resort to reflection.
final Class<?> tokenizerClass = ReflectionUtils.classForName( final Class<?> tokenizerClass = ReflectionUtils.classForName(
"org.apache.lucene.analysis.cn.smart.SentenceTokenizer", false); "org.apache.lucene.analysis.cn.smart.SentenceTokenizer", false);
this.sentenceTokenizer = (Tokenizer) tokenizerClass.getConstructor( this.sentenceTokenizer = (Tokenizer) tokenizerClass.getConstructor(
Reader.class).newInstance((Reader) null); Reader.class).newInstance((Reader) null);
this.tokenFilterClass = ReflectionUtils.classForName( this.tokenFilterClass = ReflectionUtils.classForName(
"org.apache.lucene.analysis.cn.smart.WordTokenFilter", false); "org.apache.lucene.analysis.cn.smart.WordTokenFilter", false);
} }
public short nextToken() throws IOException { public short nextToken() throws IOException {
final boolean hasNextToken = wordTokenFilter.incrementToken(); final boolean hasNextToken = wordTokenFilter.incrementToken();
if (hasNextToken) { if (hasNextToken) {
short flags = 0; short flags = 0;
final char[] image = term.buffer(); final char[] image = term.buffer();
final int length = term.length(); final int length = term.length();
tempCharSequence.reset(image, 0, length); tempCharSequence.reset(image, 0, length);
if (length == 1 && image[0] == ',') { if (length == 1 && image[0] == ',') {
// ChineseTokenizer seems to convert all punctuation to ',' // ChineseTokenizer seems to convert all punctuation to ','
// characters // characters
flags = ITokenizer.TT_PUNCTUATION; flags = ITokenizer.TT_PUNCTUATION;
} else if (numeric.matcher(tempCharSequence).matches()) { } else if (numeric.matcher(tempCharSequence).matches()) {
flags = ITokenizer.TT_NUMERIC; flags = ITokenizer.TT_NUMERIC;
} else { } else {
flags = ITokenizer.TT_TERM; flags = ITokenizer.TT_TERM;
} }
return flags; return flags;
} }
return ITokenizer.TT_EOF; return ITokenizer.TT_EOF;
} }
public void setTermBuffer(MutableCharArray array) { public void setTermBuffer(MutableCharArray array) {
array.reset(term.buffer(), 0, term.length()); array.reset(term.buffer(), 0, term.length());
} }
public void reset(Reader input) throws IOException { public void reset(Reader input) throws IOException {
try { try {
sentenceTokenizer.reset(input); sentenceTokenizer.reset(input);
wordTokenFilter = (TokenStream) tokenFilterClass.getConstructor( wordTokenFilter = (TokenStream) tokenFilterClass.getConstructor(
TokenStream.class).newInstance(sentenceTokenizer); TokenStream.class).newInstance(sentenceTokenizer);
term = wordTokenFilter.addAttribute(CharTermAttribute.class); term = wordTokenFilter.addAttribute(CharTermAttribute.class);
} catch (Exception e) { } catch (Exception e) {
throw ExceptionUtils.wrapAsRuntimeException(e); throw ExceptionUtils.wrapAsRuntimeException(e);
} }
} }
} }
} }
} }

View File

@ -1,140 +1,140 @@
package org.apache.solr.handler.clustering.carrot2; package org.apache.solr.handler.clustering.carrot2;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.util.CharArraySet; import org.apache.lucene.analysis.util.CharArraySet;
import org.apache.solr.analysis.CommonGramsFilterFactory; import org.apache.solr.analysis.CommonGramsFilterFactory;
import org.apache.solr.analysis.StopFilterFactory; import org.apache.solr.analysis.StopFilterFactory;
import org.apache.solr.analysis.TokenFilterFactory; import org.apache.solr.analysis.TokenFilterFactory;
import org.apache.solr.analysis.TokenizerChain; import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.IndexSchema;
import org.carrot2.core.LanguageCode; import org.carrot2.core.LanguageCode;
import org.carrot2.core.attribute.Init; import org.carrot2.core.attribute.Init;
import org.carrot2.core.attribute.Processing; import org.carrot2.core.attribute.Processing;
import org.carrot2.text.linguistic.DefaultLexicalDataFactory; import org.carrot2.text.linguistic.DefaultLexicalDataFactory;
import org.carrot2.text.linguistic.ILexicalData; import org.carrot2.text.linguistic.ILexicalData;
import org.carrot2.text.linguistic.ILexicalDataFactory; import org.carrot2.text.linguistic.ILexicalDataFactory;
import org.carrot2.text.util.MutableCharArray; import org.carrot2.text.util.MutableCharArray;
import org.carrot2.util.attribute.Attribute; import org.carrot2.util.attribute.Attribute;
import org.carrot2.util.attribute.Bindable; import org.carrot2.util.attribute.Bindable;
import org.carrot2.util.attribute.Input; import org.carrot2.util.attribute.Input;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
* An implementation of Carrot2's {@link ILexicalDataFactory} that adds stop * An implementation of Carrot2's {@link ILexicalDataFactory} that adds stop
* words from a field's StopFilter to the default stop words used in Carrot2, * words from a field's StopFilter to the default stop words used in Carrot2,
* for all languages Carrot2 supports. Completely replacing Carrot2 stop words * for all languages Carrot2 supports. Completely replacing Carrot2 stop words
* with Solr's wouldn't make much sense because clustering needs more aggressive * with Solr's wouldn't make much sense because clustering needs more aggressive
* stop words removal. In other words, if something is a stop word during * stop words removal. In other words, if something is a stop word during
* indexing, then it should also be a stop word during clustering, but not the * indexing, then it should also be a stop word during clustering, but not the
* other way round. * other way round.
*/ */
@Bindable @Bindable
public class SolrStopwordsCarrot2LexicalDataFactory implements public class SolrStopwordsCarrot2LexicalDataFactory implements
ILexicalDataFactory { ILexicalDataFactory {
final static Logger logger = org.slf4j.LoggerFactory final static Logger logger = org.slf4j.LoggerFactory
.getLogger(SolrStopwordsCarrot2LexicalDataFactory.class); .getLogger(SolrStopwordsCarrot2LexicalDataFactory.class);
@Init @Init
@Input @Input
@Attribute(key = "solrIndexSchema") @Attribute(key = "solrIndexSchema")
private IndexSchema schema; private IndexSchema schema;
@Processing @Processing
@Input @Input
@Attribute(key = "solrFieldNames") @Attribute(key = "solrFieldNames")
private Set<String> fieldNames; private Set<String> fieldNames;
/** /**
* A lazily-built cache of stop words per field. * A lazily-built cache of stop words per field.
*/ */
private Multimap<String, CharArraySet> solrStopWords = HashMultimap.create(); private Multimap<String, CharArraySet> solrStopWords = HashMultimap.create();
/** /**
* Carrot2's default lexical resources to use in addition to Solr's stop * Carrot2's default lexical resources to use in addition to Solr's stop
* words. * words.
*/ */
private DefaultLexicalDataFactory carrot2LexicalDataFactory = new DefaultLexicalDataFactory(); private DefaultLexicalDataFactory carrot2LexicalDataFactory = new DefaultLexicalDataFactory();
/** /**
* Obtains stop words for a field from the associated * Obtains stop words for a field from the associated
* {@link StopFilterFactory}, if any. * {@link StopFilterFactory}, if any.
*/ */
private Collection<CharArraySet> getSolrStopWordsForField(String fieldName) { private Collection<CharArraySet> getSolrStopWordsForField(String fieldName) {
// No need to synchronize here, Carrot2 ensures that instances // No need to synchronize here, Carrot2 ensures that instances
// of this class are not used by multiple threads at a time. // of this class are not used by multiple threads at a time.
if (!solrStopWords.containsKey(fieldName)) { if (!solrStopWords.containsKey(fieldName)) {
final Analyzer fieldAnalyzer = schema.getFieldType(fieldName) final Analyzer fieldAnalyzer = schema.getFieldType(fieldName)
.getAnalyzer(); .getAnalyzer();
if (fieldAnalyzer instanceof TokenizerChain) { if (fieldAnalyzer instanceof TokenizerChain) {
final TokenFilterFactory[] filterFactories = ((TokenizerChain) fieldAnalyzer) final TokenFilterFactory[] filterFactories = ((TokenizerChain) fieldAnalyzer)
.getTokenFilterFactories(); .getTokenFilterFactories();
for (TokenFilterFactory factory : filterFactories) { for (TokenFilterFactory factory : filterFactories) {
if (factory instanceof StopFilterFactory) { if (factory instanceof StopFilterFactory) {
// StopFilterFactory holds the stop words in a CharArraySet // StopFilterFactory holds the stop words in a CharArraySet
solrStopWords.put(fieldName, solrStopWords.put(fieldName,
((StopFilterFactory) factory).getStopWords()); ((StopFilterFactory) factory).getStopWords());
} }
if (factory instanceof CommonGramsFilterFactory) { if (factory instanceof CommonGramsFilterFactory) {
solrStopWords.put(fieldName, solrStopWords.put(fieldName,
((CommonGramsFilterFactory) factory) ((CommonGramsFilterFactory) factory)
.getCommonWords()); .getCommonWords());
} }
} }
} }
} }
return solrStopWords.get(fieldName); return solrStopWords.get(fieldName);
} }
@Override @Override
public ILexicalData getLexicalData(LanguageCode languageCode) { public ILexicalData getLexicalData(LanguageCode languageCode) {
final ILexicalData carrot2LexicalData = carrot2LexicalDataFactory final ILexicalData carrot2LexicalData = carrot2LexicalDataFactory
.getLexicalData(languageCode); .getLexicalData(languageCode);
return new ILexicalData() { return new ILexicalData() {
@Override @Override
public boolean isStopLabel(CharSequence word) { public boolean isStopLabel(CharSequence word) {
// Nothing in Solr maps to the concept of a stop label, // Nothing in Solr maps to the concept of a stop label,
// so return Carrot2's default here. // so return Carrot2's default here.
return carrot2LexicalData.isStopLabel(word); return carrot2LexicalData.isStopLabel(word);
} }
@Override @Override
public boolean isCommonWord(MutableCharArray word) { public boolean isCommonWord(MutableCharArray word) {
// Loop over the fields involved in clustering first // Loop over the fields involved in clustering first
for (String fieldName : fieldNames) { for (String fieldName : fieldNames) {
for (CharArraySet stopWords : getSolrStopWordsForField(fieldName)) { for (CharArraySet stopWords : getSolrStopWordsForField(fieldName)) {
if (stopWords.contains(word)) { if (stopWords.contains(word)) {
return true; return true;
} }
} }
} }
// Check default Carrot2 stop words too // Check default Carrot2 stop words too
return carrot2LexicalData.isCommonWord(word); return carrot2LexicalData.isCommonWord(word);
} }
}; };
} }
} }

View File

@ -1,78 +1,78 @@
package org.apache.solr.handler.clustering.carrot2; package org.apache.solr.handler.clustering.carrot2;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.carrot2.core.Cluster; import org.carrot2.core.Cluster;
import org.carrot2.core.Document; import org.carrot2.core.Document;
import org.carrot2.core.IClusteringAlgorithm; import org.carrot2.core.IClusteringAlgorithm;
import org.carrot2.core.ProcessingComponentBase; import org.carrot2.core.ProcessingComponentBase;
import org.carrot2.core.ProcessingException; import org.carrot2.core.ProcessingException;
import org.carrot2.core.attribute.AttributeNames; import org.carrot2.core.attribute.AttributeNames;
import org.carrot2.core.attribute.Processing; import org.carrot2.core.attribute.Processing;
import org.carrot2.util.attribute.Attribute; import org.carrot2.util.attribute.Attribute;
import org.carrot2.util.attribute.Bindable; import org.carrot2.util.attribute.Bindable;
import org.carrot2.util.attribute.Input; import org.carrot2.util.attribute.Input;
import org.carrot2.util.attribute.Output; import org.carrot2.util.attribute.Output;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
/** /**
* A mock Carrot2 clustering algorithm that outputs input documents as clusters. * A mock Carrot2 clustering algorithm that outputs input documents as clusters.
* Useful only in tests. * Useful only in tests.
*/ */
@Bindable(prefix = "EchoClusteringAlgorithm") @Bindable(prefix = "EchoClusteringAlgorithm")
public class EchoClusteringAlgorithm extends ProcessingComponentBase implements public class EchoClusteringAlgorithm extends ProcessingComponentBase implements
IClusteringAlgorithm { IClusteringAlgorithm {
@Input @Input
@Processing @Processing
@Attribute(key = AttributeNames.DOCUMENTS) @Attribute(key = AttributeNames.DOCUMENTS)
private List<Document> documents; private List<Document> documents;
@Output @Output
@Processing @Processing
@Attribute(key = AttributeNames.CLUSTERS) @Attribute(key = AttributeNames.CLUSTERS)
private List<Cluster> clusters; private List<Cluster> clusters;
@Input @Input
@Processing @Processing
@Attribute(key = "custom-fields") @Attribute(key = "custom-fields")
private String customFields = ""; private String customFields = "";
@Override @Override
public void process() throws ProcessingException { public void process() throws ProcessingException {
clusters = Lists.newArrayListWithCapacity(documents.size()); clusters = Lists.newArrayListWithCapacity(documents.size());
for (Document document : documents) { for (Document document : documents) {
final Cluster cluster = new Cluster(); final Cluster cluster = new Cluster();
cluster.addPhrases(document.getTitle(), document.getSummary()); cluster.addPhrases(document.getTitle(), document.getSummary());
if (document.getLanguage() != null) { if (document.getLanguage() != null) {
cluster.addPhrases(document.getLanguage().name()); cluster.addPhrases(document.getLanguage().name());
} }
for (String field : customFields.split(",")) { for (String field : customFields.split(",")) {
Object value = document.getField(field); Object value = document.getField(field);
if (value != null) { if (value != null) {
cluster.addPhrases(value.toString()); cluster.addPhrases(value.toString());
} }
} }
cluster.addDocuments(document); cluster.addDocuments(document);
clusters.add(cluster); clusters.add(cluster);
} }
} }
} }

View File

@ -1,80 +1,80 @@
package org.apache.solr.handler.clustering.carrot2; package org.apache.solr.handler.clustering.carrot2;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.util.List; import java.util.List;
import org.carrot2.core.Cluster; import org.carrot2.core.Cluster;
import org.carrot2.core.IClusteringAlgorithm; import org.carrot2.core.IClusteringAlgorithm;
import org.carrot2.core.LanguageCode; import org.carrot2.core.LanguageCode;
import org.carrot2.core.ProcessingComponentBase; import org.carrot2.core.ProcessingComponentBase;
import org.carrot2.core.ProcessingException; import org.carrot2.core.ProcessingException;
import org.carrot2.core.attribute.AttributeNames; import org.carrot2.core.attribute.AttributeNames;
import org.carrot2.core.attribute.Processing; import org.carrot2.core.attribute.Processing;
import org.carrot2.text.linguistic.ILexicalData; import org.carrot2.text.linguistic.ILexicalData;
import org.carrot2.text.preprocessing.pipeline.BasicPreprocessingPipeline; import org.carrot2.text.preprocessing.pipeline.BasicPreprocessingPipeline;
import org.carrot2.text.util.MutableCharArray; import org.carrot2.text.util.MutableCharArray;
import org.carrot2.util.attribute.Attribute; import org.carrot2.util.attribute.Attribute;
import org.carrot2.util.attribute.Bindable; import org.carrot2.util.attribute.Bindable;
import org.carrot2.util.attribute.Input; import org.carrot2.util.attribute.Input;
import org.carrot2.util.attribute.Output; import org.carrot2.util.attribute.Output;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
/** /**
* A mock implementation of Carrot2 clustering algorithm for testing whether the * A mock implementation of Carrot2 clustering algorithm for testing whether the
* customized lexical resource lookup works correctly. This algorithm ignores * customized lexical resource lookup works correctly. This algorithm ignores
* the input documents and instead for each word from {@link #wordsToCheck}, it * the input documents and instead for each word from {@link #wordsToCheck}, it
* outputs a cluster labeled with the word only if the word is neither a stop * outputs a cluster labeled with the word only if the word is neither a stop
* word nor a stop label. * word nor a stop label.
*/ */
@Bindable(prefix = "LexicalResourcesCheckClusteringAlgorithm") @Bindable(prefix = "LexicalResourcesCheckClusteringAlgorithm")
public class LexicalResourcesCheckClusteringAlgorithm extends public class LexicalResourcesCheckClusteringAlgorithm extends
ProcessingComponentBase implements IClusteringAlgorithm { ProcessingComponentBase implements IClusteringAlgorithm {
@Output @Output
@Processing @Processing
@Attribute(key = AttributeNames.CLUSTERS) @Attribute(key = AttributeNames.CLUSTERS)
private List<Cluster> clusters; private List<Cluster> clusters;
@Input @Input
@Processing @Processing
@Attribute @Attribute
private String wordsToCheck; private String wordsToCheck;
private BasicPreprocessingPipeline preprocessing = new BasicPreprocessingPipeline(); private BasicPreprocessingPipeline preprocessing = new BasicPreprocessingPipeline();
@Override @Override
public void process() throws ProcessingException { public void process() throws ProcessingException {
clusters = Lists.newArrayList(); clusters = Lists.newArrayList();
if (wordsToCheck == null) { if (wordsToCheck == null) {
return; return;
} }
// Test with Maltese so that the English clustering performed in other tests // Test with Maltese so that the English clustering performed in other tests
// is not affected by the test stopwords and stoplabels. // is not affected by the test stopwords and stoplabels.
ILexicalData lexicalData = preprocessing.lexicalDataFactory ILexicalData lexicalData = preprocessing.lexicalDataFactory
.getLexicalData(LanguageCode.MALTESE); .getLexicalData(LanguageCode.MALTESE);
for (String word : wordsToCheck.split(",")) { for (String word : wordsToCheck.split(",")) {
if (!lexicalData.isCommonWord(new MutableCharArray(word)) if (!lexicalData.isCommonWord(new MutableCharArray(word))
&& !lexicalData.isStopLabel(word)) { && !lexicalData.isStopLabel(word)) {
clusters.add(new Cluster(word)); clusters.add(new Cluster(word));
} }
} }
} }
} }

View File

@ -1,5 +1,5 @@
<html> <html>
<body> <body>
Apache Solr Search Server: Solr Language Identifier contrib Apache Solr Search Server: Solr Language Identifier contrib
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
<html> <html>
<body> <body>
Apache Solr Search Server: Velocity Response Writer contrib Apache Solr Search Server: Velocity Response Writer contrib
</body> </body>
</html> </html>

View File

@ -1,184 +1,184 @@
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.solr.client.solrj.impl.LBHttpSolrServer; import org.apache.solr.client.solrj.impl.LBHttpSolrServer;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.PluginInfo; import org.apache.solr.core.PluginInfo;
import org.apache.solr.util.DefaultSolrThreadFactory; import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.plugin.PluginInfoInitialized; import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.Random; import java.util.Random;
import java.util.concurrent.*; import java.util.concurrent.*;
public class HttpShardHandlerFactory extends ShardHandlerFactory implements PluginInfoInitialized { public class HttpShardHandlerFactory extends ShardHandlerFactory implements PluginInfoInitialized {
protected static Logger log = LoggerFactory.getLogger(HttpShardHandlerFactory.class); protected static Logger log = LoggerFactory.getLogger(HttpShardHandlerFactory.class);
// We want an executor that doesn't take up any resources if // We want an executor that doesn't take up any resources if
// it's not used, so it could be created statically for // it's not used, so it could be created statically for
// the distributed search component if desired. // the distributed search component if desired.
// //
// Consider CallerRuns policy and a lower max threads to throttle // Consider CallerRuns policy and a lower max threads to throttle
// requests at some point (or should we simply return failure?) // requests at some point (or should we simply return failure?)
ThreadPoolExecutor commExecutor = new ThreadPoolExecutor( ThreadPoolExecutor commExecutor = new ThreadPoolExecutor(
0, 0,
Integer.MAX_VALUE, Integer.MAX_VALUE,
5, TimeUnit.SECONDS, // terminate idle threads after 5 sec 5, TimeUnit.SECONDS, // terminate idle threads after 5 sec
new SynchronousQueue<Runnable>(), // directly hand off tasks new SynchronousQueue<Runnable>(), // directly hand off tasks
new DefaultSolrThreadFactory("httpShardExecutor") new DefaultSolrThreadFactory("httpShardExecutor")
); );
HttpClient client; HttpClient client;
Random r = new Random(); Random r = new Random();
LBHttpSolrServer loadbalancer; LBHttpSolrServer loadbalancer;
int soTimeout = 0; //current default values int soTimeout = 0; //current default values
int connectionTimeout = 0; //current default values int connectionTimeout = 0; //current default values
int maxConnectionsPerHost = 20; int maxConnectionsPerHost = 20;
int corePoolSize = 0; int corePoolSize = 0;
int maximumPoolSize = 10; int maximumPoolSize = 10;
int keepAliveTime = 5; int keepAliveTime = 5;
int queueSize = 1; int queueSize = 1;
boolean accessPolicy = true; boolean accessPolicy = true;
public String scheme = "http://"; //current default values public String scheme = "http://"; //current default values
private MultiThreadedHttpConnectionManager mgr; private MultiThreadedHttpConnectionManager mgr;
// socket timeout measured in ms, closes a socket if read // socket timeout measured in ms, closes a socket if read
// takes longer than x ms to complete. throws // takes longer than x ms to complete. throws
// java.net.SocketTimeoutException: Read timed out exception // java.net.SocketTimeoutException: Read timed out exception
static final String INIT_SO_TIMEOUT = "socketTimeout"; static final String INIT_SO_TIMEOUT = "socketTimeout";
// connection timeout measures in ms, closes a socket if connection // connection timeout measures in ms, closes a socket if connection
// cannot be established within x ms. with a // cannot be established within x ms. with a
// java.net.SocketTimeoutException: Connection timed out // java.net.SocketTimeoutException: Connection timed out
static final String INIT_CONNECTION_TIMEOUT = "connTimeout"; static final String INIT_CONNECTION_TIMEOUT = "connTimeout";
// URL scheme to be used in distributed search. // URL scheme to be used in distributed search.
static final String INIT_URL_SCHEME = "urlScheme"; static final String INIT_URL_SCHEME = "urlScheme";
// Maximum connections allowed per host // Maximum connections allowed per host
static final String INIT_MAX_CONNECTION_PER_HOST = "maxConnectionsPerHost"; static final String INIT_MAX_CONNECTION_PER_HOST = "maxConnectionsPerHost";
// The core size of the threadpool servicing requests // The core size of the threadpool servicing requests
static final String INIT_CORE_POOL_SIZE = "corePoolSize"; static final String INIT_CORE_POOL_SIZE = "corePoolSize";
// The maximum size of the threadpool servicing requests // The maximum size of the threadpool servicing requests
static final String INIT_MAX_POOL_SIZE = "maximumPoolSize"; static final String INIT_MAX_POOL_SIZE = "maximumPoolSize";
// The amount of time idle threads persist for in the queue, before being killed // The amount of time idle threads persist for in the queue, before being killed
static final String MAX_THREAD_IDLE_TIME = "maxThreadIdleTime"; static final String MAX_THREAD_IDLE_TIME = "maxThreadIdleTime";
// If the threadpool uses a backing queue, what is its maximum size (-1) to use direct handoff // If the threadpool uses a backing queue, what is its maximum size (-1) to use direct handoff
static final String INIT_SIZE_OF_QUEUE = "sizeOfQueue"; static final String INIT_SIZE_OF_QUEUE = "sizeOfQueue";
// Configure if the threadpool favours fairness over throughput // Configure if the threadpool favours fairness over throughput
static final String INIT_FAIRNESS_POLICY = "fairnessPolicy"; static final String INIT_FAIRNESS_POLICY = "fairnessPolicy";
public ShardHandler getShardHandler() { public ShardHandler getShardHandler() {
return getShardHandler(null); return getShardHandler(null);
} }
public ShardHandler getShardHandler(HttpClient httpClient) { public ShardHandler getShardHandler(HttpClient httpClient) {
return new HttpShardHandler(this, httpClient); return new HttpShardHandler(this, httpClient);
} }
public void init(PluginInfo info) { public void init(PluginInfo info) {
NamedList args = info.initArgs; NamedList args = info.initArgs;
this.soTimeout = getParameter(args, INIT_SO_TIMEOUT, 0); this.soTimeout = getParameter(args, INIT_SO_TIMEOUT, 0);
this.scheme = getParameter(args, INIT_URL_SCHEME, "http://"); this.scheme = getParameter(args, INIT_URL_SCHEME, "http://");
this.scheme = (this.scheme.endsWith("://")) ? this.scheme : this.scheme + "://"; this.scheme = (this.scheme.endsWith("://")) ? this.scheme : this.scheme + "://";
this.connectionTimeout = getParameter(args, INIT_CONNECTION_TIMEOUT, 0); this.connectionTimeout = getParameter(args, INIT_CONNECTION_TIMEOUT, 0);
this.maxConnectionsPerHost = getParameter(args, INIT_MAX_CONNECTION_PER_HOST, 20); this.maxConnectionsPerHost = getParameter(args, INIT_MAX_CONNECTION_PER_HOST, 20);
this.corePoolSize = getParameter(args, INIT_CORE_POOL_SIZE, 0); this.corePoolSize = getParameter(args, INIT_CORE_POOL_SIZE, 0);
this.maximumPoolSize = getParameter(args, INIT_MAX_POOL_SIZE, Integer.MAX_VALUE); this.maximumPoolSize = getParameter(args, INIT_MAX_POOL_SIZE, Integer.MAX_VALUE);
this.keepAliveTime = getParameter(args, MAX_THREAD_IDLE_TIME, 5); this.keepAliveTime = getParameter(args, MAX_THREAD_IDLE_TIME, 5);
this.queueSize = getParameter(args, INIT_SIZE_OF_QUEUE, -1); this.queueSize = getParameter(args, INIT_SIZE_OF_QUEUE, -1);
this.accessPolicy = getParameter(args, INIT_FAIRNESS_POLICY, false); this.accessPolicy = getParameter(args, INIT_FAIRNESS_POLICY, false);
BlockingQueue<Runnable> blockingQueue = (this.queueSize == -1) ? BlockingQueue<Runnable> blockingQueue = (this.queueSize == -1) ?
new SynchronousQueue<Runnable>(this.accessPolicy) : new SynchronousQueue<Runnable>(this.accessPolicy) :
new ArrayBlockingQueue<Runnable>(this.queueSize, this.accessPolicy); new ArrayBlockingQueue<Runnable>(this.queueSize, this.accessPolicy);
this.commExecutor = new ThreadPoolExecutor( this.commExecutor = new ThreadPoolExecutor(
this.corePoolSize, this.corePoolSize,
this.maximumPoolSize, this.maximumPoolSize,
this.keepAliveTime, TimeUnit.SECONDS, this.keepAliveTime, TimeUnit.SECONDS,
blockingQueue, blockingQueue,
new DefaultSolrThreadFactory("httpShardExecutor") new DefaultSolrThreadFactory("httpShardExecutor")
); );
mgr = new MultiThreadedHttpConnectionManager(); mgr = new MultiThreadedHttpConnectionManager();
mgr.getParams().setDefaultMaxConnectionsPerHost(this.maxConnectionsPerHost); mgr.getParams().setDefaultMaxConnectionsPerHost(this.maxConnectionsPerHost);
mgr.getParams().setMaxTotalConnections(10000); mgr.getParams().setMaxTotalConnections(10000);
mgr.getParams().setConnectionTimeout(this.connectionTimeout); mgr.getParams().setConnectionTimeout(this.connectionTimeout);
mgr.getParams().setSoTimeout(this.soTimeout); mgr.getParams().setSoTimeout(this.soTimeout);
// mgr.getParams().setStaleCheckingEnabled(false); // mgr.getParams().setStaleCheckingEnabled(false);
client = new HttpClient(mgr); client = new HttpClient(mgr);
// prevent retries (note: this didn't work when set on mgr.. needed to be set on client) // prevent retries (note: this didn't work when set on mgr.. needed to be set on client)
DefaultHttpMethodRetryHandler retryhandler = new DefaultHttpMethodRetryHandler(0, false); DefaultHttpMethodRetryHandler retryhandler = new DefaultHttpMethodRetryHandler(0, false);
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler); client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler);
try { try {
loadbalancer = new LBHttpSolrServer(client); loadbalancer = new LBHttpSolrServer(client);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
// should be impossible since we're not passing any URLs here // should be impossible since we're not passing any URLs here
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
} }
} }
private <T> T getParameter(NamedList initArgs, String configKey, T defaultValue) { private <T> T getParameter(NamedList initArgs, String configKey, T defaultValue) {
T toReturn = defaultValue; T toReturn = defaultValue;
if (initArgs != null) { if (initArgs != null) {
T temp = (T) initArgs.get(configKey); T temp = (T) initArgs.get(configKey);
toReturn = (temp != null) ? temp : defaultValue; toReturn = (temp != null) ? temp : defaultValue;
} }
log.info("Setting {} to: {}", configKey, soTimeout); log.info("Setting {} to: {}", configKey, soTimeout);
return toReturn; return toReturn;
} }
@Override @Override
public void close() { public void close() {
try { try {
mgr.shutdown(); mgr.shutdown();
} catch (Throwable e) { } catch (Throwable e) {
SolrException.log(log, e); SolrException.log(log, e);
} }
try { try {
loadbalancer.shutdown(); loadbalancer.shutdown();
} catch (Throwable e) { } catch (Throwable e) {
SolrException.log(log, e); SolrException.log(log, e);
} }
try { try {
commExecutor.shutdownNow(); commExecutor.shutdownNow();
} catch (Throwable e) { } catch (Throwable e) {
SolrException.log(log, e); SolrException.log(log, e);
} }
} }
} }

View File

@ -1,28 +1,28 @@
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
public abstract class ShardHandler { public abstract class ShardHandler {
public abstract void checkDistributed(ResponseBuilder rb); public abstract void checkDistributed(ResponseBuilder rb);
public abstract void submit(ShardRequest sreq, String shard, ModifiableSolrParams params) ; public abstract void submit(ShardRequest sreq, String shard, ModifiableSolrParams params) ;
public abstract ShardResponse takeCompletedIncludingErrors(); public abstract ShardResponse takeCompletedIncludingErrors();
public abstract ShardResponse takeCompletedOrError(); public abstract ShardResponse takeCompletedOrError();
public abstract void cancelAll(); public abstract void cancelAll();
} }

View File

@ -1,25 +1,25 @@
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
public abstract class ShardHandlerFactory { public abstract class ShardHandlerFactory {
public abstract ShardHandler getShardHandler(); public abstract ShardHandler getShardHandler();
public abstract void close(); public abstract void close();
} }

View File

@ -1,96 +1,96 @@
package org.apache.solr.search; package org.apache.solr.search;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.Collector; import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Scorer;
import org.apache.lucene.util.OpenBitSet; import org.apache.lucene.util.OpenBitSet;
import java.io.IOException; import java.io.IOException;
/** /**
* *
*/ */
public class DocSetCollector extends Collector { public class DocSetCollector extends Collector {
int pos=0; int pos=0;
OpenBitSet bits; OpenBitSet bits;
final int maxDoc; final int maxDoc;
final int smallSetSize; final int smallSetSize;
int base; int base;
// in case there aren't that many hits, we may not want a very sparse // in case there aren't that many hits, we may not want a very sparse
// bit array. Optimistically collect the first few docs in an array // bit array. Optimistically collect the first few docs in an array
// in case there are only a few. // in case there are only a few.
final int[] scratch; final int[] scratch;
public DocSetCollector(int smallSetSize, int maxDoc) { public DocSetCollector(int smallSetSize, int maxDoc) {
this.smallSetSize = smallSetSize; this.smallSetSize = smallSetSize;
this.maxDoc = maxDoc; this.maxDoc = maxDoc;
this.scratch = new int[smallSetSize]; this.scratch = new int[smallSetSize];
} }
@Override @Override
public void collect(int doc) throws IOException { public void collect(int doc) throws IOException {
doc += base; doc += base;
// optimistically collect the first docs in an array // optimistically collect the first docs in an array
// in case the total number will be small enough to represent // in case the total number will be small enough to represent
// as a small set like SortedIntDocSet instead... // as a small set like SortedIntDocSet instead...
// Storing in this array will be quicker to convert // Storing in this array will be quicker to convert
// than scanning through a potentially huge bit vector. // than scanning through a potentially huge bit vector.
// FUTURE: when search methods all start returning docs in order, maybe // FUTURE: when search methods all start returning docs in order, maybe
// we could have a ListDocSet() and use the collected array directly. // we could have a ListDocSet() and use the collected array directly.
if (pos < scratch.length) { if (pos < scratch.length) {
scratch[pos]=doc; scratch[pos]=doc;
} else { } else {
// this conditional could be removed if BitSet was preallocated, but that // this conditional could be removed if BitSet was preallocated, but that
// would take up more memory, and add more GC time... // would take up more memory, and add more GC time...
if (bits==null) bits = new OpenBitSet(maxDoc); if (bits==null) bits = new OpenBitSet(maxDoc);
bits.fastSet(doc); bits.fastSet(doc);
} }
pos++; pos++;
} }
public DocSet getDocSet() { public DocSet getDocSet() {
if (pos<=scratch.length) { if (pos<=scratch.length) {
// assumes docs were collected in sorted order! // assumes docs were collected in sorted order!
return new SortedIntDocSet(scratch, pos); return new SortedIntDocSet(scratch, pos);
} else { } else {
// set the bits for ids that were collected in the array // set the bits for ids that were collected in the array
for (int i=0; i<scratch.length; i++) bits.fastSet(scratch[i]); for (int i=0; i<scratch.length; i++) bits.fastSet(scratch[i]);
return new BitDocSet(bits,pos); return new BitDocSet(bits,pos);
} }
} }
@Override @Override
public void setScorer(Scorer scorer) throws IOException { public void setScorer(Scorer scorer) throws IOException {
} }
@Override @Override
public void setNextReader(AtomicReaderContext context) throws IOException { public void setNextReader(AtomicReaderContext context) throws IOException {
this.base = context.docBase; this.base = context.docBase;
} }
@Override @Override
public boolean acceptsDocsOutOfOrder() { public boolean acceptsDocsOutOfOrder() {
return false; return false;
} }
} }

View File

@ -1,85 +1,85 @@
package org.apache.solr.search; package org.apache.solr.search;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.Collector; import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Scorer;
import org.apache.lucene.util.OpenBitSet; import org.apache.lucene.util.OpenBitSet;
import java.io.IOException; import java.io.IOException;
/** /**
* *
*/ */
public class DocSetDelegateCollector extends DocSetCollector { public class DocSetDelegateCollector extends DocSetCollector {
final Collector collector; final Collector collector;
public DocSetDelegateCollector(int smallSetSize, int maxDoc, Collector collector) { public DocSetDelegateCollector(int smallSetSize, int maxDoc, Collector collector) {
super(smallSetSize, maxDoc); super(smallSetSize, maxDoc);
this.collector = collector; this.collector = collector;
} }
@Override @Override
public void collect(int doc) throws IOException { public void collect(int doc) throws IOException {
collector.collect(doc); collector.collect(doc);
doc += base; doc += base;
// optimistically collect the first docs in an array // optimistically collect the first docs in an array
// in case the total number will be small enough to represent // in case the total number will be small enough to represent
// as a small set like SortedIntDocSet instead... // as a small set like SortedIntDocSet instead...
// Storing in this array will be quicker to convert // Storing in this array will be quicker to convert
// than scanning through a potentially huge bit vector. // than scanning through a potentially huge bit vector.
// FUTURE: when search methods all start returning docs in order, maybe // FUTURE: when search methods all start returning docs in order, maybe
// we could have a ListDocSet() and use the collected array directly. // we could have a ListDocSet() and use the collected array directly.
if (pos < scratch.length) { if (pos < scratch.length) {
scratch[pos]=doc; scratch[pos]=doc;
} else { } else {
// this conditional could be removed if BitSet was preallocated, but that // this conditional could be removed if BitSet was preallocated, but that
// would take up more memory, and add more GC time... // would take up more memory, and add more GC time...
if (bits==null) bits = new OpenBitSet(maxDoc); if (bits==null) bits = new OpenBitSet(maxDoc);
bits.fastSet(doc); bits.fastSet(doc);
} }
pos++; pos++;
} }
@Override @Override
public DocSet getDocSet() { public DocSet getDocSet() {
if (pos<=scratch.length) { if (pos<=scratch.length) {
// assumes docs were collected in sorted order! // assumes docs were collected in sorted order!
return new SortedIntDocSet(scratch, pos); return new SortedIntDocSet(scratch, pos);
} else { } else {
// set the bits for ids that were collected in the array // set the bits for ids that were collected in the array
for (int i=0; i<scratch.length; i++) bits.fastSet(scratch[i]); for (int i=0; i<scratch.length; i++) bits.fastSet(scratch[i]);
return new BitDocSet(bits,pos); return new BitDocSet(bits,pos);
} }
} }
@Override @Override
public void setScorer(Scorer scorer) throws IOException { public void setScorer(Scorer scorer) throws IOException {
collector.setScorer(scorer); collector.setScorer(scorer);
} }
@Override @Override
public void setNextReader(AtomicReaderContext context) throws IOException { public void setNextReader(AtomicReaderContext context) throws IOException {
collector.setNextReader(context); collector.setNextReader(context);
this.base = context.docBase; this.base = context.docBase;
} }
} }

View File

@ -1,70 +1,70 @@
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.solr.search; package org.apache.solr.search;
import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queries.function.FunctionValues; import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.ValueSourceScorer; import org.apache.lucene.queries.function.ValueSourceScorer;
import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.IndexSearcher;
import org.apache.solr.search.function.ValueSourceRangeFilter; import org.apache.solr.search.function.ValueSourceRangeFilter;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
// This class works as either a normal constant score query, or as a PostFilter using a collector // This class works as either a normal constant score query, or as a PostFilter using a collector
public class FunctionRangeQuery extends SolrConstantScoreQuery implements PostFilter { public class FunctionRangeQuery extends SolrConstantScoreQuery implements PostFilter {
final ValueSourceRangeFilter rangeFilt; final ValueSourceRangeFilter rangeFilt;
public FunctionRangeQuery(ValueSourceRangeFilter filter) { public FunctionRangeQuery(ValueSourceRangeFilter filter) {
super(filter); super(filter);
this.rangeFilt = filter; this.rangeFilt = filter;
} }
@Override @Override
public DelegatingCollector getFilterCollector(IndexSearcher searcher) { public DelegatingCollector getFilterCollector(IndexSearcher searcher) {
Map fcontext = ValueSource.newContext(searcher); Map fcontext = ValueSource.newContext(searcher);
return new FunctionRangeCollector(fcontext); return new FunctionRangeCollector(fcontext);
} }
class FunctionRangeCollector extends DelegatingCollector { class FunctionRangeCollector extends DelegatingCollector {
final Map fcontext; final Map fcontext;
ValueSourceScorer scorer; ValueSourceScorer scorer;
int maxdoc; int maxdoc;
public FunctionRangeCollector(Map fcontext) { public FunctionRangeCollector(Map fcontext) {
this.fcontext = fcontext; this.fcontext = fcontext;
} }
@Override @Override
public void collect(int doc) throws IOException { public void collect(int doc) throws IOException {
if (doc<maxdoc && scorer.matches(doc)) { if (doc<maxdoc && scorer.matches(doc)) {
delegate.collect(doc); delegate.collect(doc);
} }
} }
@Override @Override
public void setNextReader(AtomicReaderContext context) throws IOException { public void setNextReader(AtomicReaderContext context) throws IOException {
maxdoc = context.reader().maxDoc(); maxdoc = context.reader().maxDoc();
FunctionValues dv = rangeFilt.getValueSource().getValues(fcontext, context); FunctionValues dv = rangeFilt.getValueSource().getValues(fcontext, context);
scorer = dv.getRangeScorer(context.reader(), rangeFilt.getLowerVal(), rangeFilt.getUpperVal(), rangeFilt.isIncludeLower(), rangeFilt.isIncludeUpper()); scorer = dv.getRangeScorer(context.reader(), rangeFilt.getLowerVal(), rangeFilt.getUpperVal(), rangeFilt.isIncludeLower(), rangeFilt.isIncludeUpper());
super.setNextReader(context); super.setNextReader(context);
} }
} }
} }

View File

@ -1,76 +1,76 @@
package org.apache.solr.search.grouping.collector; package org.apache.solr.search.grouping.collector;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.Collector; import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Scorer;
import org.apache.solr.search.DocSet; import org.apache.solr.search.DocSet;
import java.io.IOException; import java.io.IOException;
/** /**
* A collector that filters incoming doc ids that are not in the filter. * A collector that filters incoming doc ids that are not in the filter.
* *
* @lucene.experimental * @lucene.experimental
*/ */
public class FilterCollector extends Collector { public class FilterCollector extends Collector {
private final DocSet filter; private final DocSet filter;
private final Collector delegate; private final Collector delegate;
private int docBase; private int docBase;
private int matches; private int matches;
public FilterCollector(DocSet filter, Collector delegate) throws IOException { public FilterCollector(DocSet filter, Collector delegate) throws IOException {
this.filter = filter; this.filter = filter;
this.delegate = delegate; this.delegate = delegate;
} }
public void setScorer(Scorer scorer) throws IOException { public void setScorer(Scorer scorer) throws IOException {
delegate.setScorer(scorer); delegate.setScorer(scorer);
} }
public void collect(int doc) throws IOException { public void collect(int doc) throws IOException {
matches++; matches++;
if (filter.exists(doc + docBase)) { if (filter.exists(doc + docBase)) {
delegate.collect(doc); delegate.collect(doc);
} }
} }
public void setNextReader(AtomicReaderContext context) throws IOException { public void setNextReader(AtomicReaderContext context) throws IOException {
this.docBase = context.docBase; this.docBase = context.docBase;
delegate.setNextReader(context); delegate.setNextReader(context);
} }
public boolean acceptsDocsOutOfOrder() { public boolean acceptsDocsOutOfOrder() {
return delegate.acceptsDocsOutOfOrder(); return delegate.acceptsDocsOutOfOrder();
} }
public int getMatches() { public int getMatches() {
return matches; return matches;
} }
/** /**
* Returns the delegate collector * Returns the delegate collector
* *
* @return the delegate collector * @return the delegate collector
*/ */
public Collector getDelegate() { public Collector getDelegate() {
return delegate; return delegate;
} }
} }

View File

@ -1,82 +1,82 @@
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.solr.servlet; package org.apache.solr.servlet;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringEscapeUtils;
import org.apache.solr.core.CoreContainer; import org.apache.solr.core.CoreContainer;
/** /**
* A simple servlet to load the Solr Admin UI * A simple servlet to load the Solr Admin UI
* *
* @since solr 4.0 * @since solr 4.0
*/ */
public final class LoadAdminUiServlet extends HttpServlet { public final class LoadAdminUiServlet extends HttpServlet {
@Override @Override
public void doGet(HttpServletRequest request, public void doGet(HttpServletRequest request,
HttpServletResponse response) HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setContentType("text/html"); response.setContentType("text/html");
PrintWriter out = response.getWriter(); PrintWriter out = response.getWriter();
InputStream in = getServletContext().getResourceAsStream("/admin.html"); InputStream in = getServletContext().getResourceAsStream("/admin.html");
if(in != null) { if(in != null) {
try { try {
// This attribute is set by the SolrDispatchFilter // This attribute is set by the SolrDispatchFilter
CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer"); CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
String html = IOUtils.toString(in, "UTF-8"); String html = IOUtils.toString(in, "UTF-8");
String[] search = new String[] { String[] search = new String[] {
"${contextPath}", "${contextPath}",
"${adminPath}" "${adminPath}"
}; };
String[] replace = new String[] { String[] replace = new String[] {
StringEscapeUtils.escapeJavaScript(request.getContextPath()), StringEscapeUtils.escapeJavaScript(request.getContextPath()),
StringEscapeUtils.escapeJavaScript(cores.getAdminPath()) StringEscapeUtils.escapeJavaScript(cores.getAdminPath())
}; };
out.println( StringUtils.replaceEach(html, search, replace) ); out.println( StringUtils.replaceEach(html, search, replace) );
} finally { } finally {
IOUtils.closeQuietly(in); IOUtils.closeQuietly(in);
} }
} else { } else {
out.println("solr"); out.println("solr");
} }
} }
@Override @Override
public void doPost(HttpServletRequest request, public void doPost(HttpServletRequest request,
HttpServletResponse response) HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
doGet(request, response); doGet(request, response);
} }
} }

View File

@ -1,409 +1,409 @@
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.solr.servlet; package org.apache.solr.servlet;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.apache.noggit.CharArr; import org.apache.noggit.CharArr;
import org.apache.noggit.JSONWriter; import org.apache.noggit.JSONWriter;
import org.apache.solr.cloud.ZkController; import org.apache.solr.cloud.ZkController;
import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.core.CoreContainer; import org.apache.solr.core.CoreContainer;
import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
/** /**
* Zookeeper Info * Zookeeper Info
* *
* @since solr 4.0 * @since solr 4.0
*/ */
public final class ZookeeperInfoServlet extends HttpServlet { public final class ZookeeperInfoServlet extends HttpServlet {
static final Logger log = LoggerFactory.getLogger(ZookeeperInfoServlet.class); static final Logger log = LoggerFactory.getLogger(ZookeeperInfoServlet.class);
@Override @Override
public void init() throws ServletException { public void init() throws ServletException {
} }
@Override @Override
public void doGet(HttpServletRequest request, public void doGet(HttpServletRequest request,
HttpServletResponse response) HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setContentType("application/json"); response.setContentType("application/json");
// This attribute is set by the SolrDispatchFilter // This attribute is set by the SolrDispatchFilter
CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer"); CoreContainer cores = (CoreContainer) request.getAttribute("org.apache.solr.CoreContainer");
String path = request.getParameter("path"); String path = request.getParameter("path");
String addr = request.getParameter("addr"); String addr = request.getParameter("addr");
if (addr != null && addr.length() == 0) { if (addr != null && addr.length() == 0) {
addr = null; addr = null;
} }
String detailS = request.getParameter("detail"); String detailS = request.getParameter("detail");
boolean detail = detailS != null && detailS.equals("true"); boolean detail = detailS != null && detailS.equals("true");
String dumpS = request.getParameter("dump"); String dumpS = request.getParameter("dump");
boolean dump = dumpS != null && dumpS.equals("true"); boolean dump = dumpS != null && dumpS.equals("true");
PrintWriter out = response.getWriter(); PrintWriter out = response.getWriter();
ZKPrinter printer = new ZKPrinter(response, out, cores.getZkController(), addr); ZKPrinter printer = new ZKPrinter(response, out, cores.getZkController(), addr);
printer.detail = detail; printer.detail = detail;
printer.dump = dump; printer.dump = dump;
try { try {
printer.print(path); printer.print(path);
} finally { } finally {
printer.close(); printer.close();
} }
} }
@Override @Override
public void doPost(HttpServletRequest request, public void doPost(HttpServletRequest request,
HttpServletResponse response) HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
doGet(request, response); doGet(request, response);
} }
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// //
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static class ZKPrinter { static class ZKPrinter {
static boolean FULLPATH_DEFAULT = false; static boolean FULLPATH_DEFAULT = false;
boolean indent = true; boolean indent = true;
boolean fullpath = FULLPATH_DEFAULT; boolean fullpath = FULLPATH_DEFAULT;
boolean detail = false; boolean detail = false;
boolean dump = false; boolean dump = false;
String addr; // the address passed to us String addr; // the address passed to us
String keeperAddr; // the address we're connected to String keeperAddr; // the address we're connected to
boolean doClose; // close the client after done if we opened it boolean doClose; // close the client after done if we opened it
final HttpServletResponse response; final HttpServletResponse response;
final PrintWriter out; final PrintWriter out;
SolrZkClient zkClient; SolrZkClient zkClient;
int level; int level;
int maxData = 95; int maxData = 95;
public ZKPrinter(HttpServletResponse response, PrintWriter out, ZkController controller, String addr) throws IOException { public ZKPrinter(HttpServletResponse response, PrintWriter out, ZkController controller, String addr) throws IOException {
this.response = response; this.response = response;
this.out = out; this.out = out;
this.addr = addr; this.addr = addr;
if (addr == null) { if (addr == null) {
if (controller != null) { if (controller != null) {
// this core is zk enabled // this core is zk enabled
keeperAddr = controller.getZkServerAddress(); keeperAddr = controller.getZkServerAddress();
zkClient = controller.getZkClient(); zkClient = controller.getZkClient();
if (zkClient != null && zkClient.isConnected()) { if (zkClient != null && zkClient.isConnected()) {
return; return;
} else { } else {
// try a different client with this address // try a different client with this address
addr = keeperAddr; addr = keeperAddr;
} }
} }
} }
keeperAddr = addr; keeperAddr = addr;
if (addr == null) { if (addr == null) {
writeError(404, "Zookeeper is not configured for this Solr Core. Please try connecting to an alternate zookeeper address."); writeError(404, "Zookeeper is not configured for this Solr Core. Please try connecting to an alternate zookeeper address.");
return; return;
} }
try { try {
zkClient = new SolrZkClient(addr, 10000); zkClient = new SolrZkClient(addr, 10000);
doClose = true; doClose = true;
} catch (TimeoutException e) { } catch (TimeoutException e) {
writeError(503, "Could not connect to zookeeper at '" + addr + "'\""); writeError(503, "Could not connect to zookeeper at '" + addr + "'\"");
zkClient = null; zkClient = null;
return; return;
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Restore the interrupted status // Restore the interrupted status
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
writeError(503, "Could not connect to zookeeper at '" + addr + "'\""); writeError(503, "Could not connect to zookeeper at '" + addr + "'\"");
zkClient = null; zkClient = null;
return; return;
} }
} }
public void close() { public void close() {
try { try {
if (doClose) { if (doClose) {
zkClient.close(); zkClient.close();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore exception on close // ignore exception on close
} }
} }
// main entry point // main entry point
void print(String path) throws IOException { void print(String path) throws IOException {
if (zkClient == null) { if (zkClient == null) {
return; return;
} }
// normalize path // normalize path
if (path == null) { if (path == null) {
path = "/"; path = "/";
} else { } else {
path.trim(); path.trim();
if (path.length() == 0) { if (path.length() == 0) {
path = "/"; path = "/";
} }
} }
if (path.endsWith("/") && path.length() > 1) { if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1); path = path.substring(0, path.length() - 1);
} }
int idx = path.lastIndexOf('/'); int idx = path.lastIndexOf('/');
String parent = idx >= 0 ? path.substring(0, idx) : path; String parent = idx >= 0 ? path.substring(0, idx) : path;
if (parent.length() == 0) { if (parent.length() == 0) {
parent = "/"; parent = "/";
} }
CharArr chars = new CharArr(); CharArr chars = new CharArr();
JSONWriter json = new JSONWriter(chars, 2); JSONWriter json = new JSONWriter(chars, 2);
json.startObject(); json.startObject();
if (detail) { if (detail) {
if (!printZnode(json, path)) { if (!printZnode(json, path)) {
return; return;
} }
json.writeValueSeparator(); json.writeValueSeparator();
} }
json.writeString("tree"); json.writeString("tree");
json.writeNameSeparator(); json.writeNameSeparator();
json.startArray(); json.startArray();
if (!printTree(json, path)) { if (!printTree(json, path)) {
return; // there was an error return; // there was an error
} }
json.endArray(); json.endArray();
json.endObject(); json.endObject();
out.println(chars.toString()); out.println(chars.toString());
} }
void writeError(int code, String msg) { void writeError(int code, String msg) {
response.setStatus(code); response.setStatus(code);
CharArr chars = new CharArr(); CharArr chars = new CharArr();
JSONWriter w = new JSONWriter(chars, 2); JSONWriter w = new JSONWriter(chars, 2);
w.startObject(); w.startObject();
w.indent(); w.indent();
w.writeString("status"); w.writeString("status");
w.writeNameSeparator(); w.writeNameSeparator();
w.write(code); w.write(code);
w.writeValueSeparator(); w.writeValueSeparator();
w.indent(); w.indent();
w.writeString("error"); w.writeString("error");
w.writeNameSeparator(); w.writeNameSeparator();
w.writeString(msg); w.writeString(msg);
w.endObject(); w.endObject();
out.println(chars.toString()); out.println(chars.toString());
} }
boolean printTree(JSONWriter json, String path) throws IOException { boolean printTree(JSONWriter json, String path) throws IOException {
String label = path; String label = path;
if (!fullpath) { if (!fullpath) {
int idx = path.lastIndexOf('/'); int idx = path.lastIndexOf('/');
label = idx > 0 ? path.substring(idx + 1) : path; label = idx > 0 ? path.substring(idx + 1) : path;
} }
json.startObject(); json.startObject();
//writeKeyValue(json, "data", label, true ); //writeKeyValue(json, "data", label, true );
json.writeString("data"); json.writeString("data");
json.writeNameSeparator(); json.writeNameSeparator();
json.startObject(); json.startObject();
writeKeyValue(json, "title", label, true); writeKeyValue(json, "title", label, true);
json.writeValueSeparator(); json.writeValueSeparator();
json.writeString("attr"); json.writeString("attr");
json.writeNameSeparator(); json.writeNameSeparator();
json.startObject(); json.startObject();
writeKeyValue(json, "href", "zookeeper?detail=true&path=" + URLEncoder.encode(path, "UTF-8"), true); writeKeyValue(json, "href", "zookeeper?detail=true&path=" + URLEncoder.encode(path, "UTF-8"), true);
json.endObject(); json.endObject();
json.endObject(); json.endObject();
Stat stat = new Stat(); Stat stat = new Stat();
try { try {
// Trickily, the call to zkClient.getData fills in the stat variable // Trickily, the call to zkClient.getData fills in the stat variable
byte[] data = zkClient.getData(path, null, stat, true); byte[] data = zkClient.getData(path, null, stat, true);
if (stat.getEphemeralOwner() != 0) { if (stat.getEphemeralOwner() != 0) {
writeKeyValue(json, "ephemeral", true, false); writeKeyValue(json, "ephemeral", true, false);
writeKeyValue(json, "version", stat.getVersion(), false); writeKeyValue(json, "version", stat.getVersion(), false);
} }
if (dump) { if (dump) {
json.writeValueSeparator(); json.writeValueSeparator();
printZnode(json, path); printZnode(json, path);
} }
/* /*
if (stat.getNumChildren() != 0) if (stat.getNumChildren() != 0)
{ {
writeKeyValue(json, "children_count", stat.getNumChildren(), false ); writeKeyValue(json, "children_count", stat.getNumChildren(), false );
out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\""); out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\"");
} }
*/ */
//if (stat.getDataLength() != 0) //if (stat.getDataLength() != 0)
if (data != null) { if (data != null) {
String str = new BytesRef(data).utf8ToString(); String str = new BytesRef(data).utf8ToString();
//?? writeKeyValue(json, "content", str, false ); //?? writeKeyValue(json, "content", str, false );
// Does nothing now, but on the assumption this will be used later we'll leave it in. If it comes out // Does nothing now, but on the assumption this will be used later we'll leave it in. If it comes out
// the catches below need to be restructured. // the catches below need to be restructured.
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// path doesn't exist (must have been removed) // path doesn't exist (must have been removed)
writeKeyValue(json, "warning", "(path gone)", false); writeKeyValue(json, "warning", "(path gone)", false);
} catch (KeeperException e) { } catch (KeeperException e) {
writeKeyValue(json, "warning", e.toString(), false); writeKeyValue(json, "warning", e.toString(), false);
log.warn("Keeper Exception", e); log.warn("Keeper Exception", e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
writeKeyValue(json, "warning", e.toString(), false); writeKeyValue(json, "warning", e.toString(), false);
log.warn("InterruptedException", e); log.warn("InterruptedException", e);
} }
if (stat.getNumChildren() > 0) { if (stat.getNumChildren() > 0) {
json.writeValueSeparator(); json.writeValueSeparator();
if (indent) { if (indent) {
json.indent(); json.indent();
} }
json.writeString("children"); json.writeString("children");
json.writeNameSeparator(); json.writeNameSeparator();
json.startArray(); json.startArray();
try { try {
List<String> children = zkClient.getChildren(path, null, true); List<String> children = zkClient.getChildren(path, null, true);
java.util.Collections.sort(children); java.util.Collections.sort(children);
boolean first = true; boolean first = true;
for (String child : children) { for (String child : children) {
if (!first) { if (!first) {
json.writeValueSeparator(); json.writeValueSeparator();
} }
String childPath = path + (path.endsWith("/") ? "" : "/") + child; String childPath = path + (path.endsWith("/") ? "" : "/") + child;
if (!printTree(json, childPath)) { if (!printTree(json, childPath)) {
return false; return false;
} }
first = false; first = false;
} }
} catch (KeeperException e) { } catch (KeeperException e) {
writeError(500, e.toString()); writeError(500, e.toString());
return false; return false;
} catch (InterruptedException e) { } catch (InterruptedException e) {
writeError(500, e.toString()); writeError(500, e.toString());
return false; return false;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// path doesn't exist (must have been removed) // path doesn't exist (must have been removed)
json.writeString("(children gone)"); json.writeString("(children gone)");
} }
json.endArray(); json.endArray();
} }
json.endObject(); json.endObject();
return true; return true;
} }
String time(long ms) { String time(long ms) {
return (new Date(ms)).toString() + " (" + ms + ")"; return (new Date(ms)).toString() + " (" + ms + ")";
} }
public void writeKeyValue(JSONWriter json, String k, Object v, boolean isFirst) { public void writeKeyValue(JSONWriter json, String k, Object v, boolean isFirst) {
if (!isFirst) { if (!isFirst) {
json.writeValueSeparator(); json.writeValueSeparator();
} }
if (indent) { if (indent) {
json.indent(); json.indent();
} }
json.writeString(k); json.writeString(k);
json.writeNameSeparator(); json.writeNameSeparator();
json.write(v); json.write(v);
} }
boolean printZnode(JSONWriter json, String path) throws IOException { boolean printZnode(JSONWriter json, String path) throws IOException {
try { try {
Stat stat = new Stat(); Stat stat = new Stat();
// Trickily, the call to zkClient.getData fills in the stat variable // Trickily, the call to zkClient.getData fills in the stat variable
byte[] data = zkClient.getData(path, null, stat, true); byte[] data = zkClient.getData(path, null, stat, true);
json.writeString("znode"); json.writeString("znode");
json.writeNameSeparator(); json.writeNameSeparator();
json.startObject(); json.startObject();
writeKeyValue(json, "path", path, true); writeKeyValue(json, "path", path, true);
json.writeValueSeparator(); json.writeValueSeparator();
json.writeString("prop"); json.writeString("prop");
json.writeNameSeparator(); json.writeNameSeparator();
json.startObject(); json.startObject();
writeKeyValue(json, "version", stat.getVersion(), true); writeKeyValue(json, "version", stat.getVersion(), true);
writeKeyValue(json, "aversion", stat.getAversion(), false); writeKeyValue(json, "aversion", stat.getAversion(), false);
writeKeyValue(json, "children_count", stat.getNumChildren(), false); writeKeyValue(json, "children_count", stat.getNumChildren(), false);
writeKeyValue(json, "ctime", time(stat.getCtime()), false); writeKeyValue(json, "ctime", time(stat.getCtime()), false);
writeKeyValue(json, "cversion", stat.getCversion(), false); writeKeyValue(json, "cversion", stat.getCversion(), false);
writeKeyValue(json, "czxid", stat.getCzxid(), false); writeKeyValue(json, "czxid", stat.getCzxid(), false);
writeKeyValue(json, "dataLength", stat.getDataLength(), false); writeKeyValue(json, "dataLength", stat.getDataLength(), false);
writeKeyValue(json, "ephemeralOwner", stat.getEphemeralOwner(), false); writeKeyValue(json, "ephemeralOwner", stat.getEphemeralOwner(), false);
writeKeyValue(json, "mtime", time(stat.getMtime()), false); writeKeyValue(json, "mtime", time(stat.getMtime()), false);
writeKeyValue(json, "mzxid", stat.getMzxid(), false); writeKeyValue(json, "mzxid", stat.getMzxid(), false);
writeKeyValue(json, "pzxid", stat.getPzxid(), false); writeKeyValue(json, "pzxid", stat.getPzxid(), false);
json.endObject(); json.endObject();
if (data != null) { if (data != null) {
writeKeyValue(json, "data", new BytesRef(data).utf8ToString(), false); writeKeyValue(json, "data", new BytesRef(data).utf8ToString(), false);
} }
json.endObject(); json.endObject();
} catch (KeeperException e) { } catch (KeeperException e) {
writeError(500, e.toString()); writeError(500, e.toString());
return false; return false;
} catch (InterruptedException e) { } catch (InterruptedException e) {
writeError(500, e.toString()); writeError(500, e.toString());
return false; return false;
} }
return true; return true;
} }
} }
} }

View File

@ -1,456 +1,456 @@
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.solr.search; package org.apache.solr.search;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
public class TestPseudoReturnFields extends SolrTestCaseJ4 { public class TestPseudoReturnFields extends SolrTestCaseJ4 {
// :TODO: datatypes produced by the functions used may change // :TODO: datatypes produced by the functions used may change
/** /**
* values of the fl param that mean all real fields * values of the fl param that mean all real fields
*/ */
private static String[] ALL_REAL_FIELDS = new String[] { "", "*" }; private static String[] ALL_REAL_FIELDS = new String[] { "", "*" };
/** /**
* values of the fl param that mean all real fields and score * values of the fl param that mean all real fields and score
*/ */
private static String[] SCORE_AND_REAL_FIELDS = new String[] { private static String[] SCORE_AND_REAL_FIELDS = new String[] {
"score,*", "*,score" "score,*", "*,score"
}; };
@BeforeClass @BeforeClass
public static void beforeTests() throws Exception { public static void beforeTests() throws Exception {
initCore("solrconfig.xml","schema12.xml"); initCore("solrconfig.xml","schema12.xml");
assertU(adoc("id", "42", "val_i", "1", "ssto", "X", "subject", "aaa")); assertU(adoc("id", "42", "val_i", "1", "ssto", "X", "subject", "aaa"));
assertU(adoc("id", "43", "val_i", "9", "ssto", "X", "subject", "bbb")); assertU(adoc("id", "43", "val_i", "9", "ssto", "X", "subject", "bbb"));
assertU(adoc("id", "44", "val_i", "4", "ssto", "X", "subject", "aaa")); assertU(adoc("id", "44", "val_i", "4", "ssto", "X", "subject", "aaa"));
assertU(adoc("id", "45", "val_i", "6", "ssto", "X", "subject", "aaa")); assertU(adoc("id", "45", "val_i", "6", "ssto", "X", "subject", "aaa"));
assertU(adoc("id", "46", "val_i", "3", "ssto", "X", "subject", "ggg")); assertU(adoc("id", "46", "val_i", "3", "ssto", "X", "subject", "ggg"));
assertU(commit()); assertU(commit());
} }
@Test @Test
public void testAllRealFields() throws Exception { public void testAllRealFields() throws Exception {
for (String fl : ALL_REAL_FIELDS) { for (String fl : ALL_REAL_FIELDS) {
assertQ("fl="+fl+" ... all real fields", assertQ("fl="+fl+" ... all real fields",
req("q","*:*", "rows", "1", "fl",fl) req("q","*:*", "rows", "1", "fl",fl)
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='ssto']" ,"//result/doc/str[@name='ssto']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc[count(*)=4]" ,"//result/doc[count(*)=4]"
); );
} }
} }
@Test @Test
public void testScoreAndAllRealFields() throws Exception { public void testScoreAndAllRealFields() throws Exception {
for (String fl : SCORE_AND_REAL_FIELDS) { for (String fl : SCORE_AND_REAL_FIELDS) {
assertQ("fl="+fl+" ... score and real fields", assertQ("fl="+fl+" ... score and real fields",
req("q","*:*", "rows", "1", "fl",fl) req("q","*:*", "rows", "1", "fl",fl)
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='ssto']" ,"//result/doc/str[@name='ssto']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc[count(*)=5]" ,"//result/doc[count(*)=5]"
); );
} }
} }
@Test @Test
public void testScoreAndExplicitRealFields() throws Exception { public void testScoreAndExplicitRealFields() throws Exception {
assertQ("fl=score,val_i", assertQ("fl=score,val_i",
req("q","*:*", "rows", "1", "fl","score,val_i") req("q","*:*", "rows", "1", "fl","score,val_i")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=score&fl=val_i", assertQ("fl=score&fl=val_i",
req("q","*:*", "rows", "1", "fl","score","fl","val_i") req("q","*:*", "rows", "1", "fl","score","fl","val_i")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=val_i", assertQ("fl=val_i",
req("q","*:*", "rows", "1", "fl","val_i") req("q","*:*", "rows", "1", "fl","val_i")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc[count(*)=1]" ,"//result/doc[count(*)=1]"
); );
} }
@Test @Test
public void testFunctions() throws Exception { public void testFunctions() throws Exception {
assertQ("fl=log(val_i)", assertQ("fl=log(val_i)",
req("q","*:*", "rows", "1", "fl","log(val_i)") req("q","*:*", "rows", "1", "fl","log(val_i)")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc[count(*)=1]" ,"//result/doc[count(*)=1]"
); );
assertQ("fl=log(val_i),abs(val_i)", assertQ("fl=log(val_i),abs(val_i)",
req("q","*:*", "rows", "1", "fl","log(val_i),abs(val_i)") req("q","*:*", "rows", "1", "fl","log(val_i),abs(val_i)")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/float[@name='abs(val_i)']" ,"//result/doc/float[@name='abs(val_i)']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=log(val_i)&fl=abs(val_i)", assertQ("fl=log(val_i)&fl=abs(val_i)",
req("q","*:*", "rows", "1", "fl","log(val_i)","fl","abs(val_i)") req("q","*:*", "rows", "1", "fl","log(val_i)","fl","abs(val_i)")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/float[@name='abs(val_i)']" ,"//result/doc/float[@name='abs(val_i)']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
} }
@Test @Test
public void testFunctionsAndExplicit() throws Exception { public void testFunctionsAndExplicit() throws Exception {
assertQ("fl=log(val_i),val_i", assertQ("fl=log(val_i),val_i",
req("q","*:*", "rows", "1", "fl","log(val_i),val_i") req("q","*:*", "rows", "1", "fl","log(val_i),val_i")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=log(val_i)&fl=val_i", assertQ("fl=log(val_i)&fl=val_i",
req("q","*:*", "rows", "1", "fl","log(val_i)","fl","val_i") req("q","*:*", "rows", "1", "fl","log(val_i)","fl","val_i")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
} }
@Test @Test
public void testFunctionsAndScore() throws Exception { public void testFunctionsAndScore() throws Exception {
assertQ("fl=log(val_i),score", assertQ("fl=log(val_i),score",
req("q","*:*", "rows", "1", "fl","log(val_i),score") req("q","*:*", "rows", "1", "fl","log(val_i),score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=log(val_i)&fl=score", assertQ("fl=log(val_i)&fl=score",
req("q","*:*", "rows", "1", "fl","log(val_i)","fl","score") req("q","*:*", "rows", "1", "fl","log(val_i)","fl","score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=score,log(val_i),abs(val_i)", assertQ("fl=score,log(val_i),abs(val_i)",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","score,log(val_i),abs(val_i)") "fl","score,log(val_i),abs(val_i)")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/float[@name='abs(val_i)']" ,"//result/doc/float[@name='abs(val_i)']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
assertQ("fl=score&fl=log(val_i)&fl=abs(val_i)", assertQ("fl=score&fl=log(val_i)&fl=abs(val_i)",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","score","fl","log(val_i)","fl","abs(val_i)") "fl","score","fl","log(val_i)","fl","abs(val_i)")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/double[@name='log(val_i)']" ,"//result/doc/double[@name='log(val_i)']"
,"//result/doc/float[@name='abs(val_i)']" ,"//result/doc/float[@name='abs(val_i)']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
} }
@Test @Test
public void testGlobs() throws Exception { public void testGlobs() throws Exception {
assertQ("fl=val_*", assertQ("fl=val_*",
req("q","*:*", "rows", "1", "fl","val_*") req("q","*:*", "rows", "1", "fl","val_*")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc[count(*)=1]" ,"//result/doc[count(*)=1]"
); );
assertQ("fl=val_*,subj*", assertQ("fl=val_*,subj*",
req("q","*:*", "rows", "1", "fl","val_*,subj*") req("q","*:*", "rows", "1", "fl","val_*,subj*")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=val_*&fl=subj*", assertQ("fl=val_*&fl=subj*",
req("q","*:*", "rows", "1", "fl","val_*","fl","subj*") req("q","*:*", "rows", "1", "fl","val_*","fl","subj*")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
} }
@Test @Test
public void testGlobsAndExplicit() throws Exception { public void testGlobsAndExplicit() throws Exception {
assertQ("fl=val_*,id", assertQ("fl=val_*,id",
req("q","*:*", "rows", "1", "fl","val_*,id") req("q","*:*", "rows", "1", "fl","val_*,id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=val_*,subj*,id", assertQ("fl=val_*,subj*,id",
req("q","*:*", "rows", "1", "fl","val_*,subj*,id") req("q","*:*", "rows", "1", "fl","val_*,subj*,id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
assertQ("fl=val_*&fl=subj*&fl=id", assertQ("fl=val_*&fl=subj*&fl=id",
req("q","*:*", "rows", "1", "fl","val_*","fl","subj*","fl","id") req("q","*:*", "rows", "1", "fl","val_*","fl","subj*","fl","id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
} }
@Test @Test
public void testGlobsAndScore() throws Exception { public void testGlobsAndScore() throws Exception {
assertQ("fl=val_*,score", assertQ("fl=val_*,score",
req("q","*:*", "rows", "1", "fl","val_*,score", "indent", "true") req("q","*:*", "rows", "1", "fl","val_*,score", "indent", "true")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=val_*,subj*,score", assertQ("fl=val_*,subj*,score",
req("q","*:*", "rows", "1", "fl","val_*,subj*,score") req("q","*:*", "rows", "1", "fl","val_*,subj*,score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
assertQ("fl=val_*&fl=subj*&fl=score", assertQ("fl=val_*&fl=subj*&fl=score",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","val_*","fl","subj*","fl","score") "fl","val_*","fl","subj*","fl","score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
} }
@Test @Test
public void testAugmenters() throws Exception { public void testAugmenters() throws Exception {
assertQ("fl=[docid]", assertQ("fl=[docid]",
req("q","*:*", "rows", "1", "fl","[docid]") req("q","*:*", "rows", "1", "fl","[docid]")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc[count(*)=1]" ,"//result/doc[count(*)=1]"
); );
assertQ("fl=[docid],[explain]", assertQ("fl=[docid],[explain]",
req("q","*:*", "rows", "1", "fl","[docid],[explain]") req("q","*:*", "rows", "1", "fl","[docid],[explain]")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=[docid]&fl=[explain]", assertQ("fl=[docid]&fl=[explain]",
req("q","*:*", "rows", "1", "fl","[docid]","fl","[explain]") req("q","*:*", "rows", "1", "fl","[docid]","fl","[explain]")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
} }
@Test @Test
public void testAugmentersAndExplicit() throws Exception { public void testAugmentersAndExplicit() throws Exception {
assertQ("fl=[docid],id", assertQ("fl=[docid],id",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid],id") "fl","[docid],id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=[docid],[explain],id", assertQ("fl=[docid],[explain],id",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid],[explain],id") "fl","[docid],[explain],id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
assertQ("fl=[docid]&fl=[explain]&fl=id", assertQ("fl=[docid]&fl=[explain]&fl=id",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid]","fl","[explain]","fl","id") "fl","[docid]","fl","[explain]","fl","id")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
} }
@Test @Test
public void testAugmentersAndScore() throws Exception { public void testAugmentersAndScore() throws Exception {
assertQ("fl=[docid],score", assertQ("fl=[docid],score",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid],score") "fl","[docid],score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc[count(*)=2]" ,"//result/doc[count(*)=2]"
); );
assertQ("fl=[docid],[explain],score", assertQ("fl=[docid],[explain],score",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid],[explain],score") "fl","[docid],[explain],score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
assertQ("fl=[docid]&fl=[explain]&fl=score", assertQ("fl=[docid]&fl=[explain]&fl=score",
req("q","*:*", "rows", "1", req("q","*:*", "rows", "1",
"fl","[docid]","fl","[explain]","fl","score") "fl","[docid]","fl","[explain]","fl","score")
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=3]" ,"//result/doc[count(*)=3]"
); );
} }
@Test @Test
public void testAugmentersGlobsExplicitAndScoreOhMy() throws Exception { public void testAugmentersGlobsExplicitAndScoreOhMy() throws Exception {
// NOTE: 'ssto' is the missing one // NOTE: 'ssto' is the missing one
final List<String> fl = Arrays.asList final List<String> fl = Arrays.asList
("id","[docid]","[explain]","score","val_*","subj*"); ("id","[docid]","[explain]","score","val_*","subj*");
final int iters = atLeast(random, 10); final int iters = atLeast(random, 10);
for (int i = 0; i< iters; i++) { for (int i = 0; i< iters; i++) {
Collections.shuffle(fl, random); Collections.shuffle(fl, random);
final String singleFl = StringUtils.join(fl.toArray(),','); final String singleFl = StringUtils.join(fl.toArray(),',');
assertQ("fl=" + singleFl, assertQ("fl=" + singleFl,
req("q","*:*", "rows", "1","fl",singleFl) req("q","*:*", "rows", "1","fl",singleFl)
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=6]" ,"//result/doc[count(*)=6]"
); );
final List<String> params = new ArrayList<String>((fl.size()*2) + 4); final List<String> params = new ArrayList<String>((fl.size()*2) + 4);
final StringBuilder info = new StringBuilder(); final StringBuilder info = new StringBuilder();
params.addAll(Arrays.asList("q","*:*", "rows", "1")); params.addAll(Arrays.asList("q","*:*", "rows", "1"));
for (String item : fl) { for (String item : fl) {
params.add("fl"); params.add("fl");
params.add(item); params.add(item);
info.append("&fl=").append(item); info.append("&fl=").append(item);
} }
assertQ(info.toString(), assertQ(info.toString(),
req((String[])params.toArray(new String[0])) req((String[])params.toArray(new String[0]))
,"//result[@numFound='5']" ,"//result[@numFound='5']"
,"//result/doc/str[@name='id']" ,"//result/doc/str[@name='id']"
,"//result/doc/float[@name='score']" ,"//result/doc/float[@name='score']"
,"//result/doc/str[@name='subject']" ,"//result/doc/str[@name='subject']"
,"//result/doc/int[@name='val_i']" ,"//result/doc/int[@name='val_i']"
,"//result/doc/int[@name='[docid]']" ,"//result/doc/int[@name='[docid]']"
,"//result/doc/str[@name='[explain]']" ,"//result/doc/str[@name='[explain]']"
,"//result/doc[count(*)=6]" ,"//result/doc[count(*)=6]"
); );
} }
} }
} }

View File

@ -1,56 +1,56 @@
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.solr.util; package org.apache.solr.util;
import java.io.StringReader; import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath; import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactory;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
public abstract class DOMUtilTestBase extends LuceneTestCase { public abstract class DOMUtilTestBase extends LuceneTestCase {
private DocumentBuilder builder; private DocumentBuilder builder;
private static final XPathFactory xpathFactory = XPathFactory.newInstance(); private static final XPathFactory xpathFactory = XPathFactory.newInstance();
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} }
public Node getNode( String xml, String path ) throws Exception { public Node getNode( String xml, String path ) throws Exception {
return getNode( getDocument(xml), path ); return getNode( getDocument(xml), path );
} }
public Node getNode( Document doc, String path ) throws Exception { public Node getNode( Document doc, String path ) throws Exception {
XPath xpath = xpathFactory.newXPath(); XPath xpath = xpathFactory.newXPath();
return (Node)xpath.evaluate(path, doc, XPathConstants.NODE); return (Node)xpath.evaluate(path, doc, XPathConstants.NODE);
} }
public Document getDocument( String xml ) throws Exception { public Document getDocument( String xml ) throws Exception {
return builder.parse(new InputSource(new StringReader(xml))); return builder.parse(new InputSource(new StringReader(xml)));
} }
} }