LUCENE-2981: review/remove unused/unsupported contribs

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1126280 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Muir 2011-05-23 00:10:44 +00:00
parent 49fe358760
commit d1219a5769
85 changed files with 5 additions and 7631 deletions

View File

@ -77,14 +77,6 @@
<mkdir dir=".settings"/>
<copy file="dev-tools/eclipse/resources.prefs"
tofile=".settings/org.eclipse.core.resources.prefs" overwrite="true"/>
<echo>Running Lucene contrib db/bdb-je task 'get-je-jar' ...</echo>
<subant target="get-je-jar">
<fileset dir="lucene/contrib/db/bdb-je" includes="build.xml" />
</subant>
<echo>Running Lucene contrib db/bdb task 'get-db-jar' ...</echo>
<subant target="get-db-jar">
<fileset dir="lucene/contrib/db/bdb" includes="build.xml" />
</subant>
<echo>
SUCCESS: You must right-click your project and choose Refresh
Please note, your project must use a Java 6 JRE
@ -95,14 +87,6 @@
<copy todir=".">
<fileset dir="dev-tools/idea"/>
</copy>
<echo>Running Lucene contrib db/bdb-je task 'get-je-jar' ...</echo>
<subant target="get-je-jar">
<fileset dir="lucene/contrib/db/bdb-je" includes="build.xml" />
</subant>
<echo>Running Lucene contrib db/bdb task 'get-db-jar' ...</echo>
<subant target="get-db-jar">
<fileset dir="lucene/contrib/db/bdb" includes="build.xml" />
</subant>
<echo>
To complete IntelliJ IDEA setup, you must manually configure
Project Structure | Project | Project SDK.

View File

@ -3,21 +3,12 @@
<classpathentry kind="src" path="lucene/src/java"/>
<classpathentry kind="src" path="lucene/src/test-framework"/>
<classpathentry kind="src" path="lucene/src/test"/>
<classpathentry kind="src" path="lucene/contrib/ant/src/java"/>
<classpathentry kind="src" path="lucene/contrib/ant/src/resources"/>
<classpathentry kind="src" path="lucene/contrib/ant/src/test"/>
<classpathentry kind="src" path="lucene/contrib/db/bdb/src/java"/>
<classpathentry kind="src" path="lucene/contrib/db/bdb/src/test"/>
<classpathentry kind="src" path="lucene/contrib/db/bdb-je/src/java"/>
<classpathentry kind="src" path="lucene/contrib/db/bdb-je/src/test"/>
<classpathentry kind="src" path="lucene/contrib/demo/src/java"/>
<classpathentry kind="src" path="lucene/contrib/demo/src/test"/>
<classpathentry kind="src" path="lucene/contrib/highlighter/src/java"/>
<classpathentry kind="src" path="lucene/contrib/highlighter/src/test"/>
<classpathentry kind="src" path="lucene/contrib/instantiated/src/java"/>
<classpathentry kind="src" path="lucene/contrib/instantiated/src/test"/>
<classpathentry kind="src" path="lucene/contrib/lucli/src/java"/>
<classpathentry kind="src" path="lucene/contrib/lucli/src/test"/>
<classpathentry kind="src" path="lucene/contrib/memory/src/java"/>
<classpathentry kind="src" path="lucene/contrib/memory/src/test"/>
<classpathentry kind="src" path="lucene/contrib/misc/src/java"/>
@ -31,8 +22,6 @@
<classpathentry kind="src" path="lucene/contrib/spatial/src/test"/>
<classpathentry kind="src" path="lucene/contrib/spellchecker/src/java"/>
<classpathentry kind="src" path="lucene/contrib/spellchecker/src/test"/>
<classpathentry kind="src" path="lucene/contrib/swing/src/java"/>
<classpathentry kind="src" path="lucene/contrib/swing/src/test"/>
<classpathentry kind="src" path="lucene/contrib/wordnet/src/java"/>
<classpathentry kind="src" path="lucene/contrib/wordnet/src/test"/>
<classpathentry kind="src" path="lucene/contrib/xml-query-parser/src/java"/>
@ -84,10 +73,6 @@
<classpathentry kind="lib" path="lucene/lib/ant-1.7.1.jar"/>
<classpathentry kind="lib" path="lucene/lib/ant-junit-1.7.1.jar"/>
<classpathentry kind="lib" path="lucene/lib/junit-4.7.jar"/>
<classpathentry kind="lib" path="lucene/contrib/ant/lib/jtidy-r938.jar"/>
<classpathentry kind="lib" path="lucene/contrib/db/bdb/lib/db-4.7.25.jar"/>
<classpathentry kind="lib" path="lucene/contrib/db/bdb-je/lib/je-3.3.93.jar"/>
<classpathentry kind="lib" path="lucene/contrib/lucli/lib/jline.jar"/>
<classpathentry kind="lib" path="lucene/contrib/queries/lib/jakarta-regexp-1.4.jar"/>
<classpathentry kind="lib" path="modules/analysis/icu/lib/icu4j-4_6.jar"/>
<classpathentry kind="lib" path="modules/analysis/phonetic/lib/commons-codec-1.4.jar"/>

View File

@ -220,19 +220,14 @@
<!-- make sure the group list below is updated. -->
<!-- Also remember to keep site.xml in sync. -->
<packageset dir="contrib/ant/src/java"/>
<packageset dir="contrib/db/bdb-je/src/java"/>
<packageset dir="contrib/db/bdb/src/java"/>
<packageset dir="contrib/demo/src/java"/>
<packageset dir="contrib/highlighter/src/java"/>
<packageset dir="contrib/instantiated/src/java"/>
<packageset dir="contrib/lucli/src/java"/>
<packageset dir="contrib/memory/src/java"/>
<packageset dir="contrib/misc/src/java"/>
<packageset dir="contrib/queries/src/java"/>
<packageset dir="contrib/spatial/src/java"/>
<packageset dir="contrib/spellchecker/src/java"/>
<packageset dir="contrib/swing/src/java"/>
<packageset dir="contrib/wordnet/src/java"/>
<packageset dir="contrib/xml-query-parser/src/java"/>
<packageset dir="contrib/queryparser/src/java"/>
@ -244,20 +239,16 @@
<group title="Core" packages="org.apache.*:org.apache.lucene.analysis:org.apache.lucene.analysis.standard*:org.apache.lucene.analysis.tokenattributes*"/>
<group title="contrib: Ant" packages="org.apache.lucene.ant*"/>
<group title="contrib: Demo" packages="org.apache.lucene.demo*"/>
<group title="contrib: ICU" packages="org.apache.lucene.collation*"/>
<group title="contrib: DB" packages="org.apache.lucene.store.db*:org.apache.lucene.store.je*:com.sleepycat*"/>
<group title="contrib: Highlighter" packages="org.apache.lucene.search.highlight*:org.apache.lucene.search.vectorhighlight*"/>
<group title="contrib: Instantiated" packages="org.apache.lucene.store.instantiated*"/>
<group title="contrib: Lucli" packages="lucli*"/>
<group title="contrib: Memory" packages="org.apache.lucene.index.memory*"/>
<group title="contrib: Misc " packages="org.apache.lucene.misc*"/>
<group title="contrib: Queries" packages="org.apache.lucene.search.similar*:org.apache.lucene.search.regex*:org.apache.regexp*"/>
<group title="contrib: Query Parser" packages="org.apache.lucene.queryParser.*"/>
<group title="contrib: Spatial" packages="org.apache.lucene.spatial*"/>
<group title="contrib: SpellChecker" packages="org.apache.lucene.search.spell*"/>
<group title="contrib: Swing" packages="org.apache.lucene.swing*"/>
<group title="contrib: WordNet" packages="org.apache.lucene.wordnet*"/>
<group title="contrib: XML Query Parser" packages="org.apache.lucene.xmlparser*"/>

View File

@ -849,15 +849,6 @@
<arg value="-c" />
<arg value="${basedir}/lib" />
<arg value="-c" />
<arg value="${basedir}/contrib/ant/lib" />
<!-- BDB libs are downloaded, don't check them -->
<!--<arg value="-c" />
<arg value="${toplevel.dir}/lucene/contrib/db/bdb/lib" />
<arg value="-c" />
<arg value="${toplevel.dir}/lucene/contrib/db/bdb-je/lib" />-->
<arg value="-c" />
<arg value="${basedir}/contrib/lucli/lib" />
<arg value="-c" />
<arg value="${basedir}/contrib/queries/lib" />
</java>
</target>

View File

@ -50,6 +50,10 @@ Bug Fixes
======================= Lucene 3.x (not yet released) =======================
Changes in backwards compatibility policy
* LUCENE-2981: Removed the following contribs: ant, db, lucli, swing. (Robert Muir)
Changes in runtime behavior
* LUCENE-3086: ItalianAnalyzer now uses ElisionFilter with a set of Italian

View File

@ -1,56 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="ant" default="default">
<description>
Lucene Ant integration
</description>
<path id="additional.dependencies">
<!-- TODO: make ${tidy.jar} property -->
<fileset dir="lib" includes="jtidy-*.jar"/>
</path>
<pathconvert property="project.classpath"
targetos="unix"
refid="additional.dependencies"
/>
<property name="javac.includeAntRuntime" value="true"/>
<import file="../contrib-build.xml"/>
<module-uptodate name="analysis/common" jarfile="${common.dir}/../modules/analysis/build/common/lucene-analyzers-common-${version}.jar"
property="analyzers-common.uptodate" classpath.property="analyzers-common.jar"/>
<path id="classpath">
<pathelement path="${analyzers-common.jar}"/>
<path refid="base.classpath"/>
</path>
<target name="compile-core" depends="compile-analyzers-common, common.compile-core" />
<target name="compile-analyzers-common" unless="analyzers-common.uptodate">
<subant target="default">
<fileset dir="${common.dir}/../modules/analysis/common" includes="build.xml"/>
</subant>
</target>
</project>

View File

@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!--
To use this example from a source checkout:
ant -f example.xml -lib ../../build/contrib/ant/ -lib ../../build/ -lib lib
-->
<project name="ant-example" default="index">
<description>
Lucene Ant index example
</description>
<property name="index.base.dir" location="build"/>
<property name="files.dir" location="src/test"/>
<target name="index">
<mkdir dir="${index.base.dir}"/>
<index index="${index.base.dir}/index"
xmlns="antlib:org.apache.lucene.ant">
<fileset dir="${files.dir}"/>
</index>
</target>
</project>

View File

@ -1,53 +0,0 @@
/**
* Java HTML Tidy - JTidy
* HTML parser and pretty printer
*
* Copyright (c) 1998-2000 World Wide Web Consortium (Massachusetts
* Institute of Technology, Institut National de Recherche en
* Informatique et en Automatique, Keio University). All Rights
* Reserved.
*
* Contributing Author(s):
*
* Dave Raggett <dsr@w3.org>
* Andy Quick <ac.quick@sympatico.ca> (translation to Java)
* Gary L Peskin <garyp@firstech.com> (Java development)
* Sami Lempinen <sami@lempinen.net> (release management)
* Fabrizio Giustina <fgiust at users.sourceforge.net>
*
* The contributing author(s) would like to thank all those who
* helped with testing, bug fixes, and patience. This wouldn't
* have been possible without all of you.
*
* COPYRIGHT NOTICE:
*
* This software and documentation is provided "as is," and
* the copyright holders and contributing author(s) make no
* representations or warranties, express or implied, including
* but not limited to, warranties of merchantability or fitness
* for any particular purpose or that the use of the software or
* documentation will not infringe any third party patents,
* copyrights, trademarks or other rights.
*
* The copyright holders and contributing author(s) will not be
* liable for any direct, indirect, special or consequential damages
* arising out of any use of the software or documentation, even if
* advised of the possibility of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute
* this source code, or portions hereof, documentation and executables,
* for any purpose, without fee, subject to the following restrictions:
*
* 1. The origin of this source code must not be misrepresented.
* 2. Altered versions must be plainly marked as such and must
* not be misrepresented as being the original source.
* 3. This Copyright notice may not be removed or altered from any
* source or altered source distribution.
*
* The copyright holders and contributing author(s) specifically
* permit, without fee, and encourage the use of this source code
* as a component for supporting the Hypertext Markup Language in
* commercial products. If you use this source code in a product,
* acknowledgment is not required but would be appreciated.
*
*/

View File

@ -1,2 +0,0 @@
AnyObjectId[efde902f3e9b180ee7bed0e849b4be8d6c15aaff] was removed in git history.
Apache SVN contains full history.

View File

@ -1,24 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Properties;
public interface ConfigurableDocumentHandler extends DocumentHandler {
void configure(Properties props);
}

View File

@ -1,40 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.document.Document;
import java.io.File;
/**
* Allows a class to act as a Lucene document handler
*
*@since October 27, 2001
*/
public interface DocumentHandler {
/**
* Gets the document attribute of the DocumentHandler object
*
*@param file Description of Parameter
*@return The document value
*/
Document getDocument(File file)
throws DocumentHandlerException;
}

View File

@ -1,83 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.PrintStream;
import java.io.PrintWriter;
public class DocumentHandlerException extends Exception {
private Throwable cause;
/**
* Default constructor.
*/
public DocumentHandlerException() {
super();
}
/**
* Constructs with message.
*/
public DocumentHandlerException(String message) {
super(message);
}
/**
* Constructs with chained exception.
*/
public DocumentHandlerException(Throwable cause) {
super(cause.toString());
this.cause = cause;
}
/**
* Retrieves nested exception.
*/
public Throwable getException() {
return cause;
}
@Override
public void printStackTrace() {
printStackTrace(System.err);
}
@Override
public void printStackTrace(PrintStream ps) {
synchronized (ps) {
super.printStackTrace(ps);
if (cause != null) {
ps.println("--- Nested Exception ---");
cause.printStackTrace(ps);
}
}
}
@Override
public void printStackTrace(PrintWriter pw) {
synchronized (pw) {
super.printStackTrace(pw);
if (cause != null) {
pw.println("--- Nested Exception ---");
cause.printStackTrace(pw);
}
}
}
}

View File

@ -1,65 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.document.Document;
import java.io.File;
/**
* A DocumentHandler implementation to delegate responsibility to
* based on a files extension. Currently only .html and .txt
* files are handled, other extensions ignored.
*
*@since October 28, 2001
*TODO: Implement dynamic document type lookup
*/
public class FileExtensionDocumentHandler
implements DocumentHandler {
/**
* Gets the document attribute of the
* FileExtensionDocumentHandler object
*
*@param file Description of
* Parameter
*@return The document value
*@exception DocumentHandlerException Description of
* Exception
*/
public Document getDocument(File file)
throws DocumentHandlerException {
Document doc = null;
String name = file.getName();
try {
if (name.endsWith(".txt")) {
doc = TextDocument.Document(file);
}
if (name.endsWith(".html")) {
doc = HtmlDocument.Document(file);
}
} catch (java.io.IOException e) {
throw new DocumentHandlerException(e);
}
return doc;
}
}

View File

@ -1,294 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.document.Field;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.tidy.Tidy;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
/**
* The <code>HtmlDocument</code> class creates a Lucene {@link
* org.apache.lucene.document.Document} from an HTML document. <P>
*
* It does this by using JTidy package. It can take input input
* from {@link java.io.File} or {@link java.io.InputStream}.
*
*/
public class HtmlDocument {
private Element rawDoc;
//-------------------------------------------------------------
// Constructors
//-------------------------------------------------------------
/**
* Constructs an <code>HtmlDocument</code> from a {@link
* java.io.File}.
*
*@param file the <code>File</code> containing the
* HTML to parse
*@exception IOException if an I/O exception occurs
*/
public HtmlDocument(File file) throws IOException {
Tidy tidy = new Tidy();
tidy.setQuiet(true);
tidy.setShowWarnings(false);
org.w3c.dom.Document root = null;
InputStream is = new FileInputStream(file);
try {
root = tidy.parseDOM(is, null);
} finally {
is.close();
}
rawDoc = root.getDocumentElement();
}
/**
* Constructs an <code>HtmlDocument</code> from an {@link
* java.io.InputStream}.
*
*@param is the <code>InputStream</code>
* containing the HTML
*/
public HtmlDocument(InputStream is) {
Tidy tidy = new Tidy();
tidy.setQuiet(true);
tidy.setShowWarnings(false);
org.w3c.dom.Document root = tidy.parseDOM(is, null);
rawDoc = root.getDocumentElement();
}
/**
* Constructs an <code>HtmlDocument</code> from a
* {@link java.io.File}.
* @param file the <code>File</code> containing the
* HTML to parse
* @param tidyConfigFile the <code>String</code>
* containing the full path to the Tidy config file
* @exception IOException if an I/O exception occurs */
public HtmlDocument(File file, String tidyConfigFile) throws IOException {
Tidy tidy = new Tidy();
tidy.setConfigurationFromFile(tidyConfigFile);
tidy.setQuiet(true);
tidy.setShowWarnings(false);
org.w3c.dom.Document root =
tidy.parseDOM(new FileInputStream(file), null);
rawDoc = root.getDocumentElement();
}
/**
* Creates a Lucene <code>Document</code> from a
* {@link java.io.File}.
* @param file
* @param tidyConfigFile the full path to the Tidy
* config file
* @exception IOException */
public static org.apache.lucene.document.Document
Document(File file, String tidyConfigFile) throws IOException {
HtmlDocument htmlDoc = new HtmlDocument(file, tidyConfigFile);
org.apache.lucene.document.Document luceneDoc = new org.apache.lucene.document.Document();
luceneDoc.add(new Field("title", htmlDoc.getTitle(), Field.Store.YES, Field.Index.ANALYZED));
luceneDoc.add(new Field("contents", htmlDoc.getBody(), Field.Store.YES, Field.Index.ANALYZED));
String contents = null;
BufferedReader br =
new BufferedReader(new FileReader(file));
StringWriter sw = new StringWriter();
String line = br.readLine();
while (line != null) {
sw.write(line);
line = br.readLine();
}
br.close();
contents = sw.toString();
sw.close();
luceneDoc.add(new Field("rawcontents", contents, Field.Store.YES, Field.Index.NO));
return luceneDoc;
}
/**
* Creates a Lucene <code>Document</code> from an {@link
* java.io.InputStream}.
*
*@param is
*/
public static org.apache.lucene.document.Document
getDocument(InputStream is) {
HtmlDocument htmlDoc = new HtmlDocument(is);
org.apache.lucene.document.Document luceneDoc =
new org.apache.lucene.document.Document();
luceneDoc.add(new Field("title", htmlDoc.getTitle(), Field.Store.YES, Field.Index.ANALYZED));
luceneDoc.add(new Field("contents", htmlDoc.getBody(), Field.Store.YES, Field.Index.ANALYZED));
return luceneDoc;
}
//-------------------------------------------------------------
// Public methods
//-------------------------------------------------------------
/**
* Creates a Lucene <code>Document</code> from a {@link
* java.io.File}.
*
*@param file
*@exception IOException
*/
public static org.apache.lucene.document.Document
Document(File file) throws IOException {
HtmlDocument htmlDoc = new HtmlDocument(file);
org.apache.lucene.document.Document luceneDoc =
new org.apache.lucene.document.Document();
luceneDoc.add(new Field("title", htmlDoc.getTitle(), Field.Store.YES, Field.Index.ANALYZED));
luceneDoc.add(new Field("contents", htmlDoc.getBody(), Field.Store.YES, Field.Index.ANALYZED));
String contents = null;
BufferedReader br =
new BufferedReader(new FileReader(file));
StringWriter sw = new StringWriter();
String line = br.readLine();
while (line != null) {
sw.write(line);
line = br.readLine();
}
br.close();
contents = sw.toString();
sw.close();
luceneDoc.add(new Field("rawcontents", contents, Field.Store.YES, Field.Index.NO));
return luceneDoc;
}
//-------------------------------------------------------------
// Private methods
//-------------------------------------------------------------
/**
* Runs <code>HtmlDocument</code> on the files specified on
* the command line.
*
*@param args Command line arguments
*@exception Exception Description of Exception
*/
public static void main(String args[]) throws Exception {
// HtmlDocument doc = new HtmlDocument(new File(args[0]));
// System.out.println("Title = " + doc.getTitle());
// System.out.println("Body = " + doc.getBody());
HtmlDocument doc =
new HtmlDocument(new FileInputStream(new File(args[0])));
System.out.println("Title = " + doc.getTitle());
System.out.println("Body = " + doc.getBody());
}
/**
* Gets the title attribute of the <code>HtmlDocument</code>
* object.
*
*@return the title value
*/
public String getTitle() {
if (rawDoc == null) {
return null;
}
String title = "";
NodeList nl = rawDoc.getElementsByTagName("title");
if (nl.getLength() > 0) {
Element titleElement = ((Element) nl.item(0));
Text text = (Text) titleElement.getFirstChild();
if (text != null) {
title = text.getData();
}
}
return title;
}
/**
* Gets the bodyText attribute of the
* <code>HtmlDocument</code> object.
*
*@return the bodyText value
*/
public String getBody() {
if (rawDoc == null) {
return null;
}
String body = "";
NodeList nl = rawDoc.getElementsByTagName("body");
if (nl.getLength() > 0) {
body = getBodyText(nl.item(0));
}
return body;
}
/**
* Gets the bodyText attribute of the
* <code>HtmlDocument</code> object.
*
*@param node a DOM Node
*@return The bodyText value
*/
private String getBodyText(Node node) {
NodeList nl = node.getChildNodes();
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < nl.getLength(); i++) {
Node child = nl.item(i);
switch (child.getNodeType()) {
case Node.ELEMENT_NODE:
buffer.append(getBodyText(child));
buffer.append(" ");
break;
case Node.TEXT_NODE:
buffer.append(((Text) child).getData());
break;
}
}
return buffer.toString();
}
}

View File

@ -1,444 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;
import java.lang.reflect.Constructor;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.analysis.core.StopAnalyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.TieredMergePolicy;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DynamicConfigurator;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
/**
* Ant task to index files with Lucene
*
*/
public class IndexTask extends Task {
/**
* resources
*/
protected Vector<ResourceCollection> rcs = new Vector<ResourceCollection>();
/**
* overwrite index?
*/
private boolean overwrite = false;
/**
* index path
*/
private File indexDir;
/**
* document handler classname
*/
private String handlerClassName =
FileExtensionDocumentHandler.class.getName();
/**
* document handler instance
*/
private DocumentHandler handler;
/**
*
*/
private String analyzerClassName =
StandardAnalyzer.class.getName();
/**
* analyzer instance
*/
private Analyzer analyzer;
/**
* Lucene merge factor
*/
private int mergeFactor = 20;
private HandlerConfig handlerConfig;
private boolean useCompoundIndex = true;
/**
* Creates new instance
*/
public IndexTask() {
}
/**
* Specifies the directory where the index will be stored
*/
public void setIndex(File indexDir) {
this.indexDir = indexDir;
}
/**
* Sets the mergeFactor attribute of the IndexTask object
*
*@param mergeFactor The new mergeFactor value
*/
public void setMergeFactor(int mergeFactor) {
this.mergeFactor = mergeFactor;
}
/**
* Sets the overwrite attribute of the IndexTask object
*
*@param overwrite The new overwrite value
*/
public void setOverwrite(boolean overwrite) {
this.overwrite = overwrite;
}
/**
* If creating a new index and this is set to true, the
* index will be created in compound format.
*/
public void setUseCompoundIndex(boolean useCompoundIndex) {
this.useCompoundIndex = useCompoundIndex;
}
/**
* Sets the documentHandler attribute of the IndexTask object
*
*@param classname The new documentHandler value
*/
public void setDocumentHandler(String classname) {
handlerClassName = classname;
}
/**
* Sets the analyzer based on the builtin Lucene analyzer types.
*
* TODO: Enforce analyzer and analyzerClassName to be mutually exclusive
*/
public void setAnalyzer(AnalyzerType type) {
analyzerClassName = type.getClassname();
}
public void setAnalyzerClassName(String classname) {
analyzerClassName = classname;
}
/**
* Adds a set of files (nested fileset attribute).
*
*@param set FileSet to be added
*/
public void addFileset(FileSet set) {
add(set);
}
/**
* Add a collection of files to copy.
* @param res a resource collection to copy.
* @since Ant 1.7
*/
public void add(ResourceCollection res) {
rcs.add(res);
}
/**
* Sets custom properties for a configurable document handler.
*/
public void addConfig(HandlerConfig config) throws BuildException {
if (handlerConfig != null) {
throw new BuildException("Only one config element allowed");
}
handlerConfig = config;
}
private static final Analyzer createAnalyzer(String className) throws Exception{
final Class<? extends Analyzer> clazz = Class.forName(className).asSubclass(Analyzer.class);
try {
// first try to use a ctor with version parameter (needed for many new Analyzers that have no default one anymore
Constructor<? extends Analyzer> cnstr = clazz.getConstructor(Version.class);
return cnstr.newInstance(Version.LUCENE_CURRENT);
} catch (NoSuchMethodException nsme) {
// otherwise use default ctor
return clazz.newInstance();
}
}
/**
* Begins the indexing
*
*@exception BuildException If an error occurs indexing the
* fileset
*/
@Override
public void execute() throws BuildException {
// construct handler and analyzer dynamically
try {
handler = Class.forName(handlerClassName).asSubclass(DocumentHandler.class).newInstance();
analyzer = IndexTask.createAnalyzer(analyzerClassName);
} catch (Exception e) {
throw new BuildException(e);
}
log("Document handler = " + handler.getClass(), Project.MSG_VERBOSE);
log("Analyzer = " + analyzer.getClass(), Project.MSG_VERBOSE);
if (handler instanceof ConfigurableDocumentHandler) {
((ConfigurableDocumentHandler) handler).configure(handlerConfig.getProperties());
}
try {
indexDocs();
} catch (IOException e) {
throw new BuildException(e);
}
}
/**
* Index the fileset.
*
*@exception IOException if Lucene I/O exception
*TODO: refactor!!!!!
*/
private void indexDocs() throws IOException {
Date start = new Date();
boolean create = overwrite;
// If the index directory doesn't exist,
// create it and force create mode
if (indexDir.mkdirs() && !overwrite) {
create = true;
}
FSDirectory dir = FSDirectory.open(indexDir);
try {
IndexSearcher searcher = null;
boolean checkLastModified = false;
if (!create) {
try {
searcher = new IndexSearcher(dir, true);
checkLastModified = true;
} catch (IOException ioe) {
log("IOException: " + ioe.getMessage());
// Empty - ignore, which indicates to index all
// documents
}
}
log("checkLastModified = " + checkLastModified, Project.MSG_VERBOSE);
IndexWriterConfig conf = new IndexWriterConfig(
Version.LUCENE_CURRENT, analyzer).setOpenMode(
create ? OpenMode.CREATE : OpenMode.APPEND);
TieredMergePolicy tmp = (TieredMergePolicy) conf.getMergePolicy();
tmp.setUseCompoundFile(useCompoundIndex);
tmp.setMaxMergeAtOnce(mergeFactor);
IndexWriter writer = new IndexWriter(dir, conf);
int totalFiles = 0;
int totalIndexed = 0;
int totalIgnored = 0;
try {
for (int i = 0; i < rcs.size(); i++) {
ResourceCollection rc = rcs.elementAt(i);
if (rc.isFilesystemOnly()) {
Iterator resources = rc.iterator();
while (resources.hasNext()) {
Resource r = (Resource) resources.next();
if (!r.isExists() || !(r instanceof FileResource)) {
continue;
}
totalFiles++;
File file = ((FileResource) r).getFile();
if (!file.exists() || !file.canRead()) {
throw new BuildException("File \"" +
file.getAbsolutePath()
+ "\" does not exist or is not readable.");
}
boolean indexIt = true;
if (checkLastModified) {
Term pathTerm =
new Term("path", file.getPath());
TermQuery query =
new TermQuery(pathTerm);
ScoreDoc[] hits = searcher.search(query, null, 1).scoreDocs;
// if document is found, compare the
// indexed last modified time with the
// current file
// - don't index if up to date
if (hits.length > 0) {
Document doc = searcher.doc(hits[0].doc);
String indexModified =
doc.get("modified").trim();
if (indexModified != null) {
long lastModified = 0;
try {
lastModified = DateTools.stringToTime(indexModified);
} catch (ParseException e) {
// if modified time is not parsable, skip
}
if (lastModified == file.lastModified()) {
// TODO: remove existing document
indexIt = false;
}
}
}
}
if (indexIt) {
try {
log("Indexing " + file.getPath(),
Project.MSG_VERBOSE);
Document doc =
handler.getDocument(file);
if (doc == null) {
totalIgnored++;
} else {
// Add the path of the file as a field named "path". Use a Keyword field, so
// that the index stores the path, and so that the path is searchable
doc.add(new Field("path", file.getPath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
// Add the last modified date of the file a field named "modified". Use a
// Keyword field, so that it's searchable, but so that no attempt is made
// to tokenize the field into words.
doc.add(new Field("modified", DateTools.timeToString(file.lastModified(), DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
totalIndexed++;
}
} catch (DocumentHandlerException e) {
throw new BuildException(e);
}
}
}
// for j
}
// if (fs != null)
}
// for i
writer.optimize();
}
//try
finally {
// always make sure everything gets closed,
// no matter how we exit.
writer.close();
if (searcher != null) {
searcher.close();
}
}
Date end = new Date();
log(totalIndexed + " out of " + totalFiles + " indexed (" +
totalIgnored + " ignored) in " + (end.getTime() - start.getTime()) +
" milliseconds");
} finally {
dir.close();
}
}
public static class HandlerConfig implements DynamicConfigurator {
Properties props = new Properties();
public void setDynamicAttribute(String attributeName, String value) throws BuildException {
props.setProperty(attributeName, value);
}
public Object createDynamicElement(String elementName) throws BuildException {
throw new BuildException("Sub elements not supported");
}
public Properties getProperties() {
return props;
}
}
public static class AnalyzerType extends EnumeratedAttribute {
private static Map<String,String> analyzerLookup = new HashMap<String,String>();
static {
analyzerLookup.put("simple", SimpleAnalyzer.class.getName());
analyzerLookup.put("standard", StandardAnalyzer.class.getName());
analyzerLookup.put("stop", StopAnalyzer.class.getName());
analyzerLookup.put("whitespace", WhitespaceAnalyzer.class.getName());
}
/**
* @see EnumeratedAttribute#getValues
*/
@Override
public String[] getValues() {
Set<String> keys = analyzerLookup.keySet();
return keys.toArray(new String[0]);
}
public String getClassname() {
return analyzerLookup.get(getValue());
}
}
}

View File

@ -1,98 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
/**
* A utility for making Lucene Documents from a File.
*
*@since December 6, 2001
*TODO: Fix JavaDoc comments here
*/
public class TextDocument {
private String contents;
/**
* Constructor for the TextDocument object
*
*@param file Description of Parameter
*@exception IOException Description of Exception
*/
public TextDocument(File file) throws IOException {
BufferedReader br =
new BufferedReader(new FileReader(file));
StringWriter sw = new StringWriter();
String line = br.readLine();
while (line != null) {
sw.write(line);
line = br.readLine();
}
br.close();
contents = sw.toString();
sw.close();
}
/**
* Makes a document for a File. <p>
*
* The document has a single field:
* <ul>
* <li> <code>contents</code>--containing the full contents
* of the file, as a Text field;
*
*@param f Description of Parameter
*@return Description of the Returned Value
*@exception IOException Description of Exception
*/
public static Document Document(File f) throws IOException {
TextDocument textDoc = new TextDocument(f);
// make a new, empty document
Document doc = new Document();
doc.add(new Field("title", f.getName(), Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("contents", textDoc.getContents(), Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("rawcontents", textDoc.getContents(), Field.Store.YES, Field.Index.NO));
// return the document
return doc;
}
/**
*@return The contents value
*TODO: finish this method
*/
public String getContents() {
return contents;
}
}

View File

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

View File

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

View File

@ -1,21 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<antlib>
<taskdef name="index" classname="org.apache.lucene.ant.IndexTask"/>
</antlib>

View File

@ -1,36 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import org.apache.lucene.util.LuceneTestCase;
public abstract class DocumentTestCase extends LuceneTestCase
{
protected File getFile(String filename) throws IOException {
String fullname =
this.getClass().getResource(filename).getFile();
File file = new File(URLDecoder.decode(fullname, "UTF-8"));
return file;
}
}

View File

@ -1,44 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.ant.DocumentTestCase;
import org.apache.lucene.ant.HtmlDocument;
public class HtmlDocumentTest extends DocumentTestCase
{
HtmlDocument doc;
@Override
public void setUp() throws Exception {
super.setUp();
doc = new HtmlDocument(getFile("test.html"));
}
public void testDoc() {
assertEquals("Title", "Test Title", doc.getTitle());
assertTrue("Body", doc.getBody().startsWith("This is some test"));
}
@Override
public void tearDown() throws Exception {
doc = null;
super.tearDown();
}
}

View File

@ -1,95 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException; // javadoc
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.StopAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.apache.lucene.util.LuceneTestCase;
/**
* Test cases for index task
*
*/
public class IndexTaskTest extends LuceneTestCase {
private final static String docHandler =
"org.apache.lucene.ant.FileExtensionDocumentHandler";
private IndexSearcher searcher;
private Analyzer analyzer;
private Directory dir;
/**
* The JUnit setup method
*
*@exception IOException Description of Exception
*/
@Override
public void setUp() throws Exception {
super.setUp();
// slightly hackish way to get the src/test dir
String docsDir = getDataFile("test.txt").getParent();
File indexDir = TEMP_DIR;
Project project = new Project();
IndexTask task = new IndexTask();
FileSet fs = new FileSet();
fs.setProject(project);
fs.setDir(new File(docsDir));
task.addFileset(fs);
task.setOverwrite(true);
task.setDocumentHandler(docHandler);
task.setIndex(indexDir);
task.setProject(project);
task.execute();
dir = newFSDirectory(indexDir);
searcher = new IndexSearcher(dir, true);
analyzer = new StopAnalyzer(TEST_VERSION_CURRENT);
}
public void testSearch() throws Exception {
Query query = new QueryParser(TEST_VERSION_CURRENT, "contents",analyzer).parse("test");
int numHits = searcher.search(query, null, 1000).totalHits;
assertEquals("Find document(s)", 2, numHits);
}
/**
* The teardown method for JUnit
* TODO: remove indexDir?
*/
@Override
public void tearDown() throws Exception {
searcher.close();
dir.close();
super.tearDown();
}
}

View File

@ -1,43 +0,0 @@
package org.apache.lucene.ant;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.ant.DocumentTestCase;
import org.apache.lucene.ant.TextDocument;
public class TextDocumentTest extends DocumentTestCase
{
TextDocument doc;
@Override
public void setUp() throws Exception {
super.setUp();
doc = new TextDocument(getFile("test.txt"));
}
public void testDoc() {
assertEquals("Contents", "Test Contents", doc.getContents());
}
@Override
public void tearDown() throws Exception {
doc = null;
super.tearDown();
}
}

View File

@ -1,7 +0,0 @@
<html>
<head>
<title>Test Title</title>
</head>
<body>
<i>This is <b>some</b>test</i>
</body>

View File

@ -1 +0,0 @@
Test Contents

View File

@ -1,50 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="bdb-je" default="default">
<description>
Lucene Berkeley DB Java Edition integration
</description>
<property name="je.version" value="3.3.93" />
<path id="je.jar">
<pathelement location="lib/je-${je.version}.jar" />
</path>
<available classname="com.sleepycat.je.Database" property="je.jar.exists">
<classpath refid="je.jar" />
</available>
<pathconvert property="project.classpath" targetos="unix" refid="je.jar" />
<property name="build.dir" location="../../../build/contrib/db/bdb-je" />
<property name="dist.dir" location="../../../dist/contrib/db/bdb-je" />
<property name="maven.dist.dir" location="../../../dist/maven" />
<import file="../../contrib-build.xml" />
<target name="get-je-jar" unless="je.jar.exists">
<mkdir dir="lib" />
<get src="http://download.oracle.com/maven/com/sleepycat/je/${je.version}/je-${je.version}.jar"
dest="lib/je-${je.version}.jar" />
</target>
<target name="check-and-get-je-jar" depends="get-je-jar" />
<target name="init" depends="contrib-build.init,check-and-get-je-jar" />
</project>

View File

@ -1,2 +0,0 @@
AnyObjectId[9a9ff077cdd36a96e7e0506986edd4e52b90a22f] was removed in git history.
Apache SVN contains full history.

View File

@ -1 +0,0 @@
No bdb jars are shipped with lucene. This is a fake license to work around the automated license checking.

View File

@ -1 +0,0 @@
No bdb jars are shipped with lucene. This is a fake license to work around the automated license checking.

View File

@ -1,83 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
/**
* Port of Andi Vajda's DbDirectory to Java Edition of Berkeley Database
*
*/
public class Block extends Object {
protected DatabaseEntry key, data;
protected Block(File file) throws IOException {
byte[] fileKey = file.getKey();
key = new DatabaseEntry(new byte[fileKey.length + 8]);
data = new DatabaseEntry(new byte[JEIndexOutput.BLOCK_LEN]);
System.arraycopy(fileKey, 0, key.getData(), 0, fileKey.length);
seek(0L);
}
protected byte[] getKey() {
return key.getData();
}
protected byte[] getData() {
return data.getData();
}
protected void seek(long position) throws IOException {
byte[] data = key.getData();
int index = data.length - 8;
position >>>= JEIndexOutput.BLOCK_SHIFT;
data[index + 0] = (byte) (0xff & (position >>> 56));
data[index + 1] = (byte) (0xff & (position >>> 48));
data[index + 2] = (byte) (0xff & (position >>> 40));
data[index + 3] = (byte) (0xff & (position >>> 32));
data[index + 4] = (byte) (0xff & (position >>> 24));
data[index + 5] = (byte) (0xff & (position >>> 16));
data[index + 6] = (byte) (0xff & (position >>> 8));
data[index + 7] = (byte) (0xff & (position >>> 0));
}
protected void get(JEDirectory directory) throws IOException {
try {
// TODO check LockMode
directory.blocks.get(directory.txn, key, data, null);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
protected void put(JEDirectory directory) throws IOException {
try {
directory.blocks.put(directory.txn, key, data);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -1,237 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Random;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
/**
* Port of Andi Vajda's DbDirectory to Java Edition of Berkeley Database
*
*/
public class File extends Object {
static protected Random random = new Random();
protected DatabaseEntry key, data;
protected long length, timeModified;
protected String name;
protected byte[] uuid;
protected File(String name) throws IOException {
setName(name);
data = new DatabaseEntry(new byte[32]);
}
protected File(JEDirectory directory, String name, boolean create)
throws IOException {
this(name);
if (!exists(directory)) {
if (!create)
throw new IOException("File does not exist: " + name);
else {
DatabaseEntry key = new DatabaseEntry(new byte[24]);
DatabaseEntry data = new DatabaseEntry(null);
Database blocks = directory.blocks;
Transaction txn = directory.txn;
data.setPartial(true);
uuid = new byte[16];
try {
do {
/* generate a v.4 random-uuid unique to this db */
random.nextBytes(uuid);
uuid[6] = (byte) ((byte) 0x40 | (uuid[6] & (byte) 0x0f));
uuid[8] = (byte) ((byte) 0x80 | (uuid[8] & (byte) 0x3f));
System.arraycopy(uuid, 0, key.getData(), 0, 16);
// TODO check LockMode
} while (blocks.get(txn, key, data, null) != OperationStatus.NOTFOUND);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
} else if (create)
length = 0L;
}
protected String getName() {
return name;
}
private void setName(String name) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(128);
DataOutputStream out = new DataOutputStream(buffer);
out.writeUTF(name);
out.close();
key = new DatabaseEntry(buffer.toByteArray());
this.name = name;
}
protected byte[] getKey() throws IOException {
if (uuid == null)
throw new IOException("Uninitialized file");
return uuid;
}
protected long getLength() {
return length;
}
protected long getTimeModified() {
return timeModified;
}
protected boolean exists(JEDirectory directory) throws IOException {
Database files = directory.files;
Transaction txn = directory.txn;
try {
// TODO check LockMode
if (files.get(txn, key, data, null) == OperationStatus.NOTFOUND)
return false;
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
byte[] bytes = data.getData();
ByteArrayInputStream buffer = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(buffer);
length = in.readLong();
timeModified = in.readLong();
in.close();
uuid = new byte[16];
System.arraycopy(bytes, 16, uuid, 0, 16);
return true;
}
protected void modify(JEDirectory directory, long length, long timeModified)
throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(32);
DataOutputStream out = new DataOutputStream(buffer);
Database files = directory.files;
Transaction txn = directory.txn;
out.writeLong(length);
out.writeLong(timeModified);
out.write(getKey());
out.close();
System.arraycopy(buffer.toByteArray(), 0, data.getData(), 0, 32);
try {
files.put(txn, key, data);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
this.length = length;
this.timeModified = timeModified;
}
protected void delete(JEDirectory directory) throws IOException {
if (!exists(directory))
throw new IOException("File does not exist: " + getName());
Cursor cursor = null;
try {
try {
byte[] bytes = getKey();
int ulen = bytes.length + 8;
byte[] cursorBytes = new byte[ulen];
DatabaseEntry cursorKey = new DatabaseEntry(cursorBytes);
DatabaseEntry cursorData = new DatabaseEntry(null);
Database files = directory.files;
Database blocks = directory.blocks;
Transaction txn = directory.txn;
System.arraycopy(bytes, 0, cursorBytes, 0, bytes.length);
cursorData.setPartial(true);
cursor = blocks.openCursor(txn, null);
if (cursor.getSearchKey(cursorKey, cursorData, null) != OperationStatus.NOTFOUND) {
cursor.delete();
advance: while (cursor.getNext(cursorKey, cursorData, null) != OperationStatus.NOTFOUND) {
byte[] temp = cursorKey.getData();
for (int i = 0; i < bytes.length; i++)
if (bytes[i] != temp[i]) {
break advance;
}
cursor.delete();
}
}
files.delete(txn, key);
} finally {
if (cursor != null)
cursor.close();
}
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
protected void rename(JEDirectory directory, String name)
throws IOException {
if (!exists(directory))
throw new IOException("File does not exist: " + getName());
File newFile = new File(name);
if (newFile.exists(directory))
newFile.delete(directory);
try {
Database files = directory.files;
Transaction txn = directory.txn;
files.delete(txn, key);
setName(name);
files.put(txn, key, data);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -1,213 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.Lock;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
/**
* Port of Andi Vajda's DbDirectory to to Java Edition of Berkeley Database
*
* A JEDirectory is a Berkeley DB JE based implementation of
* {@link org.apache.lucene.store.Directory Directory}. It uses two
* {@link com.sleepycat.je.Database Db} database handles, one for storing file
* records and another for storing file data blocks.
*
*/
public class JEDirectory extends Directory {
protected Set<JEIndexOutput> openFiles = Collections.synchronizedSet(new HashSet<JEIndexOutput>());
protected Database files, blocks;
protected Transaction txn;
protected int flags;
/**
* Instantiate a DbDirectory. The same threading rules that apply to
* Berkeley DB handles apply to instances of DbDirectory.
*
* @param txn
* a transaction handle that is going to be used for all db
* operations done by this instance. This parameter may be
* <code>null</code>.
* @param files
* a db handle to store file records.
* @param blocks
* a db handle to store file data blocks.
* @param flags
* flags used for db read operations.
*/
public JEDirectory(Transaction txn, Database files, Database blocks,
int flags) {
super();
this.txn = txn;
this.files = files;
this.blocks = blocks;
this.flags = flags;
}
public JEDirectory(Transaction txn, Database files, Database blocks) {
this(txn, files, blocks, 0);
}
@Override
public void close() throws IOException {
flush();
}
/**
* Flush the currently open files. After they have been flushed it is safe
* to commit the transaction without closing this DbDirectory instance
* first.
*
* @see #setTransaction
*/
public void flush() throws IOException {
Iterator<JEIndexOutput> iterator = openFiles.iterator();
while (iterator.hasNext()) {
System.out
.println(iterator.next().file.getName());
// ((IndexOutput) iterator.next()).flush();
}
}
@Override
public IndexOutput createOutput(String name) throws IOException {
return new JEIndexOutput(this, name, true);
}
@Override
public void deleteFile(String name) throws IOException {
new File(name).delete(this);
}
@Override
public boolean fileExists(String name) throws IOException {
return new File(name).exists(this);
}
@Override
public long fileLength(String name) throws IOException {
File file = new File(name);
if (file.exists(this))
return file.getLength();
throw new FileNotFoundException(name);
}
@Override
public long fileModified(String name) throws IOException {
File file = new File(name);
if (file.exists(this))
return file.getTimeModified();
throw new IOException("File does not exist: " + name);
}
@Override
public String[] listAll() throws IOException {
Cursor cursor = null;
List<String> list = new ArrayList<String>();
try {
try {
DatabaseEntry key = new DatabaseEntry(new byte[0]);
DatabaseEntry data = new DatabaseEntry(null);
data.setPartial(true);
// TODO see if cursor needs configuration
cursor = files.openCursor(txn, null);
// TODO see if LockMode should be set
if (cursor.getNext(key, data, null) != OperationStatus.NOTFOUND) {
ByteArrayInputStream buffer = new ByteArrayInputStream(key
.getData());
DataInputStream in = new DataInputStream(buffer);
String name = in.readUTF();
in.close();
list.add(name);
while (cursor.getNext(key, data, null) != OperationStatus.NOTFOUND) {
buffer = new ByteArrayInputStream(key.getData());
in = new DataInputStream(buffer);
name = in.readUTF();
in.close();
list.add(name);
}
}
} finally {
if (cursor != null)
cursor.close();
}
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
return list.toArray(new String[list.size()]);
}
@Override
public IndexInput openInput(String name) throws IOException {
return new JEIndexInput(this, name);
}
@Override
public void sync(Collection<String> names) throws IOException {
}
@Override
public Lock makeLock(String name) {
return new JELock();
}
/**
* Once a transaction handle was committed it is no longer valid. In order
* to continue using this JEDirectory instance after a commit, the
* transaction handle has to be replaced.
*
* @param txn
* the new transaction handle to use
*/
public void setTransaction(Transaction txn) {
this.txn = txn;
}
}

View File

@ -1,141 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.store.IndexInput;
/**
* Port of Andi Vajda's DbDirectory to Java Edition of Berkeley Database
*
*/
public class JEIndexInput extends IndexInput {
protected long position = 0L, length = 0L;
protected JEDirectory directory;
protected Block block;
protected File file;
protected JEIndexInput(JEDirectory directory, String name)
throws IOException {
super();
this.directory = directory;
this.file = new File(name);
if (!file.exists(directory))
throw new IOException("File does not exist: " + name);
length = file.getLength();
block = new Block(file);
block.get(directory);
}
@Override
public Object clone() {
try {
JEIndexInput clone = (JEIndexInput) super.clone();
clone.block = new Block(file);
clone.block.seek(position);
clone.block.get(directory);
return clone;
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
@Override
public void close() throws IOException {
}
@Override
public long length() {
return length;
}
@Override
public byte readByte() throws IOException {
if (position + 1 > length)
throw new IOException(file.getName() + ": Reading past end of file");
int blockPos = (int) (position++ & JEIndexOutput.BLOCK_MASK);
byte b = block.getData()[blockPos];
if (blockPos + 1 == JEIndexOutput.BLOCK_LEN) {
block.seek(position);
block.get(directory);
}
return b;
}
@Override
public void readBytes(byte[] b, int offset, int len) throws IOException {
if (position + len > length)
throw new IOException("Reading past end of file");
else {
int blockPos = (int) (position & JEIndexOutput.BLOCK_MASK);
while (blockPos + len >= JEIndexOutput.BLOCK_LEN) {
int blockLen = JEIndexOutput.BLOCK_LEN - blockPos;
System
.arraycopy(block.getData(), blockPos, b, offset,
blockLen);
len -= blockLen;
offset += blockLen;
position += blockLen;
block.seek(position);
block.get(directory);
blockPos = 0;
}
if (len > 0) {
System.arraycopy(block.getData(), blockPos, b, offset, len);
position += len;
}
}
}
@Override
public void seek(long pos) throws IOException {
if (pos > length)
throw new IOException("seeking past end of file");
if ((pos >>> JEIndexOutput.BLOCK_SHIFT) != (position >>> JEIndexOutput.BLOCK_SHIFT)) {
block.seek(pos);
block.get(directory);
}
position = pos;
}
@Override
public long getFilePointer() {
return position;
}
}

View File

@ -1,147 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.store.IndexOutput;
/**
* Port of Andi Vajda's DbDirectory to Java Edition of Berkeley Database
*
*/
public class JEIndexOutput extends IndexOutput {
/**
* The size of data blocks, currently 16k (2^14), is determined by this
* constant.
*/
static public final int BLOCK_SHIFT = 14;
static public final int BLOCK_LEN = 1 << BLOCK_SHIFT;
static public final int BLOCK_MASK = BLOCK_LEN - 1;
protected long position = 0L, length = 0L;
protected JEDirectory directory;
protected Block block;
protected File file;
protected JEIndexOutput(JEDirectory directory, String name, boolean create)
throws IOException {
super();
this.directory = directory;
file = new File(directory, name, create);
block = new Block(file);
length = file.getLength();
seek(length);
block.get(directory);
directory.openFiles.add(this);
}
@Override
public void close() throws IOException {
flush();
file.modify(directory, length, System.currentTimeMillis());
directory.openFiles.remove(this);
}
@Override
public void flush() throws IOException {
if (length > 0)
block.put(directory);
}
@Override
public void writeByte(byte b) throws IOException {
int blockPos = (int) (position++ & BLOCK_MASK);
block.getData()[blockPos] = b;
if (blockPos + 1 == BLOCK_LEN) {
block.put(directory);
block.seek(position);
block.get(directory);
}
if (position > length)
length = position;
}
@Override
public void writeBytes(byte[] b, int offset, int len) throws IOException {
int blockPos = (int) (position & BLOCK_MASK);
while (blockPos + len >= BLOCK_LEN) {
int blockLen = BLOCK_LEN - blockPos;
System.arraycopy(b, offset, block.getData(), blockPos, blockLen);
block.put(directory);
len -= blockLen;
offset += blockLen;
position += blockLen;
block.seek(position);
block.get(directory);
blockPos = 0;
}
if (len > 0) {
System.arraycopy(b, offset, block.getData(), blockPos, len);
position += len;
}
if (position > length)
length = position;
}
@Override
public long length() throws IOException {
return length;
}
@Override
public void seek(long pos) throws IOException {
if (pos > length)
throw new IOException("seeking past end of file");
if ((pos >>> BLOCK_SHIFT) == (position >>> BLOCK_SHIFT))
position = pos;
else {
block.put(directory);
block.seek(pos);
block.get(directory);
position = pos;
}
}
@Override
public long getFilePointer() {
return position;
}
}

View File

@ -1,53 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.store.Lock;
/**
* Port of Andi Vajda's DbDirectory to Java Edition of Berkeley Database
*
*/
public class JELock extends Lock {
boolean isLocked = false;
public JELock()
{
}
@Override
public boolean obtain()
{
return (isLocked = true);
}
@Override
public void release()
{
isLocked = false;
}
@Override
public boolean isLocked()
{
return isLocked;
}
}

View File

@ -1,22 +0,0 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<body>
Berkeley DB Java Edition based implementation of {@link org.apache.lucene.store.Directory Directory}.
</body>
</html>

View File

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

View File

@ -1,636 +0,0 @@
package org.apache.lucene.store.je;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.util.LuceneTestCase;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
/**
* Tests {@link JEDirectory}.
*
* Adapted from Andi Vajda's org.apache.lucene.db.DbStoreTest.
*
*/
public class JEStoreTest extends LuceneTestCase {
protected File dbHome = new File(TEMP_DIR,"index");
protected Environment env;
protected Database index, blocks;
@Override
public void setUp() throws Exception {
super.setUp();
if (!dbHome.exists())
dbHome.mkdir();
else {
File[] files = dbHome.listFiles();
for (int i = 0; i < files.length; i++) {
String name = files[i].getName();
if (name.endsWith("jdb") || name.equals("je.lck"))
files[i].delete();
}
}
EnvironmentConfig envConfig = new EnvironmentConfig();
DatabaseConfig dbConfig = new DatabaseConfig();
envConfig.setTransactional(true);
envConfig.setAllowCreate(true);
dbConfig.setAllowCreate(true);
dbConfig.setTransactional(true);
env = new Environment(dbHome, envConfig);
Transaction txn = null;
try {
txn = env.beginTransaction(null, null);
index = env.openDatabase(txn, "__index__", dbConfig);
blocks = env.openDatabase(txn, "__blocks__", dbConfig);
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
index = null;
blocks = null;
throw e;
} finally {
if (txn != null)
txn.commit();
txn = null;
}
}
@Override
public void tearDown() throws Exception {
if (index != null)
index.close();
if (blocks != null)
blocks.close();
if (env != null)
env.close();
super.tearDown();
}
public void testBytes() throws Exception {
final int count = 250;
final int LENGTH_MASK = 0xffff;
Random r = random;
final long seed = r.nextLong();
Random gen = new Random(seed);
int totalLength = 0;
int duration;
Date end;
Date veryStart = new Date();
Date start = new Date();
Transaction txn = env.beginTransaction(null, null);
Directory store = null;
if (VERBOSE) System.out.println("Writing files byte by byte");
try {
store = new JEDirectory(txn, index, blocks);
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexOutput file = store.createOutput(name);
totalLength += length;
for (int j = 0; j < length; j++) {
byte b = (byte) (gen.nextInt() & 0x7F);
file.writeByte(b);
}
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to create, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexInput file = store.openInput(name);
if (file.length() != length)
throw new Exception("length incorrect");
for (int j = 0; j < length; j++) {
byte b = (byte) (gen.nextInt() & 0x7F);
if (file.readByte() != b)
throw new Exception("contents incorrect");
}
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
store.deleteFile(name);
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete");
System.out.print(end.getTime() - veryStart.getTime());
System.out.println(" total milliseconds");
}
}
public void testDelete() throws Exception {
final int count = 250;
final int LENGTH_MASK = 0xffff;
Random r = random;
final long seed = r.nextLong();
Random gen = new Random(seed);
int totalLength = 0;
int duration;
Date end;
Date veryStart = new Date();
Date start = new Date();
Transaction txn = env.beginTransaction(null, null);
Directory store = null;
if (VERBOSE) System.out.println("Writing files byte by byte");
try {
store = new JEDirectory(txn, index, blocks);
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexOutput file = store.createOutput(name);
totalLength += length;
for (int j = 0; j < length; j++) {
byte b = (byte) (gen.nextInt() & 0x7F);
file.writeByte(b);
}
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
if (i % 2 == 0) {
String name = i + ".dat";
store.deleteFile(name);
}
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete even files");
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to create, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
int length = gen.nextInt() & LENGTH_MASK;
if (i % 2 != 0) {
String name = i + ".dat";
IndexInput file = store.openInput(name);
if (file.length() != length)
throw new Exception("length incorrect");
for (int j = 0; j < length; j++) {
byte b = (byte) (gen.nextInt() & 0x7F);
if (file.readByte() != b)
throw new Exception("contents incorrect");
}
file.close();
} else {
for (int j = 0; j < length; j++) {
gen.nextInt();
}
}
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
if (i % 2 != 0) {
String name = i + ".dat";
store.deleteFile(name);
}
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete");
System.out.print(end.getTime() - veryStart.getTime());
System.out.println(" total milliseconds");
}
Cursor cursor = null;
try {
cursor = index.openCursor(null, null);
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
if (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
fail("index database is not empty");
}
} catch (DatabaseException e) {
throw e;
} finally {
if (cursor != null)
cursor.close();
}
cursor = null;
try {
cursor = blocks.openCursor(null, null);
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
if (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
fail("blocks database is not empty");
}
} catch (DatabaseException e) {
throw e;
} finally {
if (cursor != null)
cursor.close();
}
}
public void testArrays() throws Exception {
final int count = 250;
final int LENGTH_MASK = 0xffff;
Random r = random;
final long seed = r.nextLong();
Random gen = new Random(seed);
int totalLength = 0;
int duration;
Date end;
Date veryStart = new Date();
Date start = new Date();
Transaction txn = env.beginTransaction(null, null);
Directory store = null;
if (VERBOSE) System.out.println("Writing files as one byte array");
try {
store = new JEDirectory(txn, index, blocks);
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexOutput file = store.createOutput(name);
byte[] data = new byte[length];
totalLength += length;
gen.nextBytes(data);
file.writeBytes(data, length);
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to create, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexInput file = store.openInput(name);
if (file.length() != length)
throw new Exception("length incorrect");
byte[] data = new byte[length];
byte[] read = new byte[length];
gen.nextBytes(data);
file.readBytes(read, 0, length);
if (!Arrays.equals(data, read))
throw new Exception("contents incorrect");
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new JEDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
store.deleteFile(name);
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null) {
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete");
System.out.print(end.getTime() - veryStart.getTime());
System.out.println(" total milliseconds");
}
}
}

View File

@ -1,77 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="bdb" default="default">
<description>
Lucene Berkeley DB integration
</description>
<property name="db.version" value="4.7.25" />
<path id="db.jar">
<pathelement location="lib/db-${db.version}.jar" />
</path>
<available classname="com.sleepycat.db.internal.Db" property="db.jar.exists">
<classpath refid="db.jar" />
</available>
<pathconvert property="project.classpath" targetos="unix" refid="db.jar" />
<property name="build.dir" location="../../../build/contrib/db/bdb" />
<property name="dist.dir" location="../../../dist/contrib/db/bdb" />
<property name="maven.dist.dir" location="../../../dist/maven" />
<import file="../../contrib-build.xml" />
<target name="get-db-jar" unless="db.jar.exists">
<mkdir dir="lib" />
<get src="http://downloads.osafoundation.org/db/db-${db.version}.jar"
dest="lib/db-${db.version}.jar" />
</target>
<target name="sanity-load-lib" depends="compile-test">
<java classname="org.apache.lucene.store.db.SanityLoadLibrary"
classpathref="junit.classpath"
fork="true"
failonerror="false"
logError="false"
outputproperty="sanity-load-lib-error"
/>
<condition property="no-bdb-lib" value="true">
<and>
<isset property="sanity-load-lib-error"/>
<not>
<equals arg1="${sanity-load-lib-error}" arg2="" trim="true" />
</not>
</and>
</condition>
</target>
<target name="warn-no-lib" if="no-bdb-lib">
<echo>Unit Tests Skipped: Could not sanity check Native Library</echo>
</target>
<target name="test" depends="sanity-load-lib,warn-no-lib"
unless="no-bdb-lib">
<antcall target="common.test" inheritAll="true" inheritRefs="true" />
</target>
<target name="check-and-get-db-jar" depends="get-db-jar" />
<target name="init" depends="contrib-build.init,check-and-get-db-jar" />
</project>

View File

@ -1 +0,0 @@
No bdb jars are shipped with lucene. This is a fake license to work around the automated license checking.

View File

@ -1,2 +0,0 @@
AnyObjectId[99baf20bacd712cae91dd6e4e1f46224cafa1a37] was removed in git history.
Apache SVN contains full history.

View File

@ -1 +0,0 @@
No bdb jars are shipped with lucene. This is a fake license to work around the automated license checking.

View File

@ -1,50 +0,0 @@
package com.sleepycat.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.sleepycat.db.internal.Db;
import com.sleepycat.db.internal.DbTxn;
/**
* This class is a hack to workaround the need to rewrite the entire
* org.apache.lucene.store.db package after Sleepycat radically changed its
* Java API from version 4.2.52 to version 4.3.21.
*
* The code below extracts the package-accessible internal handle instances
* that were the entrypoint objects in the pre-4.3 Java API and that wrap the
* actual Berkeley DB C objects via SWIG.
*
*/
public class DbHandleExtractor {
private DbHandleExtractor()
{
}
static public Db getDb(Database database)
{
return database.db;
}
static public DbTxn getDbTxn(Transaction transaction)
{
return transaction.txn;
}
}

View File

@ -1,92 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.db.DatabaseException;
public class Block extends Object {
protected DatabaseEntry key, data;
protected Block(File file)
throws IOException
{
byte[] fileKey = file.getKey();
key = new DatabaseEntry(new byte[fileKey.length + 8]);
key.setUserBuffer(fileKey.length + 8, true);
data = new DatabaseEntry(new byte[DbIndexOutput.BLOCK_LEN]);
data.setUserBuffer(data.getSize(), true);
System.arraycopy(fileKey, 0, key.getData(), 0, fileKey.length);
seek(0L);
}
protected byte[] getKey()
{
return key.getData();
}
protected byte[] getData()
{
return data.getData();
}
protected void seek(long position)
throws IOException
{
byte[] data = key.getData();
int index = data.length - 8;
position >>>= DbIndexOutput.BLOCK_SHIFT;
data[index + 0] = (byte) (0xff & (position >>> 56));
data[index + 1] = (byte) (0xff & (position >>> 48));
data[index + 2] = (byte) (0xff & (position >>> 40));
data[index + 3] = (byte) (0xff & (position >>> 32));
data[index + 4] = (byte) (0xff & (position >>> 24));
data[index + 5] = (byte) (0xff & (position >>> 16));
data[index + 6] = (byte) (0xff & (position >>> 8));
data[index + 7] = (byte) (0xff & (position >>> 0));
}
protected void get(DbDirectory directory)
throws IOException
{
try {
directory.blocks.get(directory.txn, key, data, directory.flags);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
protected void put(DbDirectory directory)
throws IOException
{
try {
directory.blocks.put(directory.txn, key, data, 0);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -1,246 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.IndexInput;
import com.sleepycat.db.internal.Db;
import com.sleepycat.db.internal.DbConstants;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.db.internal.Dbc;
import com.sleepycat.db.internal.DbTxn;
import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.Database;
import com.sleepycat.db.Transaction;
import com.sleepycat.db.DbHandleExtractor;
/**
* A DbDirectory is a Berkeley DB 4.3 based implementation of
* {@link org.apache.lucene.store.Directory Directory}. It uses two
* {@link com.sleepycat.db.internal.Db Db} database handles, one for storing file
* records and another for storing file data blocks.
*
*/
public class DbDirectory extends Directory {
protected Set<DbIndexOutput> openFiles = Collections.synchronizedSet(new HashSet<DbIndexOutput>());
protected Db files, blocks;
protected DbTxn txn;
protected int flags;
/**
* Instantiate a DbDirectory. The same threading rules that apply to
* Berkeley DB handles apply to instances of DbDirectory.
*
* @param txn a transaction handle that is going to be used for all db
* operations done by this instance. This parameter may be
* <code>null</code>.
* @param files a db handle to store file records.
* @param blocks a db handle to store file data blocks.
* @param flags flags used for db read operations.
*/
public DbDirectory(DbTxn txn, Db files, Db blocks, int flags)
{
super();
this.txn = txn;
this.files = files;
this.blocks = blocks;
this.flags = flags;
}
public DbDirectory(Transaction txn, Database files, Database blocks,
int flags)
{
super();
this.txn = txn != null ? DbHandleExtractor.getDbTxn(txn) : null;
this.files = DbHandleExtractor.getDb(files);
this.blocks = DbHandleExtractor.getDb(blocks);
this.flags = flags;
}
public DbDirectory(Transaction txn, Database files, Database blocks)
{
this(txn, files, blocks, 0);
}
@Override
public void close()
throws IOException
{
flush();
}
/**
* Flush the currently open files. After they have been flushed it is
* safe to commit the transaction without closing this DbDirectory
* instance first.
* @see #setTransaction
*/
public void flush()
throws IOException
{
Iterator<DbIndexOutput> iterator = openFiles.iterator();
while (iterator.hasNext())
iterator.next().flush();
}
@Override
public IndexOutput createOutput(String name)
throws IOException
{
return new DbIndexOutput(this, name, true);
}
@Override
public void deleteFile(String name)
throws IOException
{
new File(name).delete(this);
}
@Override
public boolean fileExists(String name)
throws IOException
{
return new File(name).exists(this);
}
@Override
public long fileLength(String name) throws IOException {
File file = new File(name);
if (file.exists(this))
return file.getLength();
throw new FileNotFoundException(name);
}
@Override
public long fileModified(String name)
throws IOException
{
File file = new File(name);
if (file.exists(this))
return file.getTimeModified();
throw new IOException("File does not exist: " + name);
}
@Override
public String[] listAll()
throws IOException
{
Dbc cursor = null;
List<String> list = new ArrayList<String>();
try {
try {
DatabaseEntry key = new DatabaseEntry(new byte[0]);
DatabaseEntry data = new DatabaseEntry((byte[]) null);
data.setPartial(true);
cursor = files.cursor(txn, flags);
if (cursor.get(key, data,
DbConstants.DB_SET_RANGE | flags) != DbConstants.DB_NOTFOUND)
{
ByteArrayInputStream buffer =
new ByteArrayInputStream(key.getData());
DataInputStream in = new DataInputStream(buffer);
String name = in.readUTF();
in.close();
list.add(name);
while (cursor.get(key, data,
DbConstants.DB_NEXT | flags) != DbConstants.DB_NOTFOUND) {
buffer = new ByteArrayInputStream(key.getData());
in = new DataInputStream(buffer);
name = in.readUTF();
in.close();
list.add(name);
}
}
} finally {
if (cursor != null)
cursor.close();
}
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
return list.toArray(new String[list.size()]);
}
@Override
public void sync(Collection<String> names) throws IOException {
}
@Override
public IndexInput openInput(String name)
throws IOException
{
return new DbIndexInput(this, name);
}
@Override
public Lock makeLock(String name)
{
return new DbLock();
}
/**
* Once a transaction handle was committed it is no longer valid. In
* order to continue using this DbDirectory instance after a commit, the
* transaction handle has to be replaced.
* @param txn the new transaction handle to use
*/
public void setTransaction(Transaction txn)
{
setTransaction(txn != null ? DbHandleExtractor.getDbTxn(txn) : null);
}
/**
* Once a transaction handle was committed it is no longer valid. In
* order to continue using this DbDirectory instance after a commit, the
* transaction handle has to be replaced.
* @param txn the new transaction handle to use
*/
public void setTransaction(DbTxn txn)
{
this.txn = txn;
}
}

View File

@ -1,152 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.store.IndexInput;
public class DbIndexInput extends IndexInput {
protected long position = 0L, length = 0L;
protected DbDirectory directory;
protected Block block;
protected File file;
protected DbIndexInput(DbDirectory directory, String name)
throws IOException
{
super();
this.directory = directory;
this.file = new File(name);
if (!file.exists(directory))
throw new IOException("File does not exist: " + name);
length = file.getLength();
block = new Block(file);
block.get(directory);
}
@Override
public Object clone()
{
try {
DbIndexInput clone = (DbIndexInput) super.clone();
clone.block = new Block(file);
clone.block.seek(position);
clone.block.get(directory);
return clone;
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
@Override
public void close()
throws IOException
{
}
@Override
public long length()
{
return length;
}
@Override
public byte readByte()
throws IOException
{
if (position + 1 > length)
throw new IOException("Reading past end of file");
int blockPos = (int) (position++ & DbIndexOutput.BLOCK_MASK);
byte b = block.getData()[blockPos];
if (blockPos + 1 == DbIndexOutput.BLOCK_LEN)
{
block.seek(position);
block.get(directory);
}
return b;
}
@Override
public void readBytes(byte[] b, int offset, int len)
throws IOException
{
if (position + len > length)
throw new IOException("Reading past end of file");
else
{
int blockPos = (int) (position & DbIndexOutput.BLOCK_MASK);
while (blockPos + len >= DbIndexOutput.BLOCK_LEN) {
int blockLen = DbIndexOutput.BLOCK_LEN - blockPos;
System.arraycopy(block.getData(), blockPos,
b, offset, blockLen);
len -= blockLen;
offset += blockLen;
position += blockLen;
block.seek(position);
block.get(directory);
blockPos = 0;
}
if (len > 0)
{
System.arraycopy(block.getData(), blockPos, b, offset, len);
position += len;
}
}
}
@Override
public void seek(long pos)
throws IOException
{
if (pos > length)
throw new IOException("seeking past end of file");
if ((pos >>> DbIndexOutput.BLOCK_SHIFT) !=
(position >>> DbIndexOutput.BLOCK_SHIFT))
{
block.seek(pos);
block.get(directory);
}
position = pos;
}
@Override
public long getFilePointer()
{
return position;
}
}

View File

@ -1,156 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.store.IndexOutput;
public class DbIndexOutput extends IndexOutput {
/**
* The size of data blocks, currently 16k (2^14), is determined by this
* constant.
*/
static public final int BLOCK_SHIFT = 14;
static public final int BLOCK_LEN = 1 << BLOCK_SHIFT;
static public final int BLOCK_MASK = BLOCK_LEN - 1;
protected long position = 0L, length = 0L;
protected DbDirectory directory;
protected Block block;
protected File file;
protected DbIndexOutput(DbDirectory directory, String name, boolean create)
throws IOException
{
super();
this.directory = directory;
file = new File(directory, name, create);
block = new Block(file);
length = file.getLength();
seek(length);
block.get(directory);
directory.openFiles.add(this);
}
@Override
public void close()
throws IOException
{
flush();
file.modify(directory, length, System.currentTimeMillis());
directory.openFiles.remove(this);
}
@Override
public void flush()
throws IOException
{
if (length > 0)
block.put(directory);
}
@Override
public void writeByte(byte b)
throws IOException
{
int blockPos = (int) (position++ & BLOCK_MASK);
block.getData()[blockPos] = b;
if (blockPos + 1 == BLOCK_LEN)
{
block.put(directory);
block.seek(position);
block.get(directory);
}
if (position > length)
length = position;
}
@Override
public void writeBytes(byte[] b, int offset, int len)
throws IOException
{
int blockPos = (int) (position & BLOCK_MASK);
while (blockPos + len >= BLOCK_LEN) {
int blockLen = BLOCK_LEN - blockPos;
System.arraycopy(b, offset, block.getData(), blockPos, blockLen);
block.put(directory);
len -= blockLen;
offset += blockLen;
position += blockLen;
block.seek(position);
block.get(directory);
blockPos = 0;
}
if (len > 0)
{
System.arraycopy(b, offset, block.getData(), blockPos, len);
position += len;
}
if (position > length)
length = position;
}
@Override
public long length()
throws IOException
{
return length;
}
@Override
public void seek(long pos)
throws IOException
{
if (pos > length)
throw new IOException("seeking past end of file");
if ((pos >>> BLOCK_SHIFT) == (position >>> BLOCK_SHIFT))
position = pos;
else
{
block.put(directory);
block.seek(pos);
block.get(directory);
position = pos;
}
}
@Override
public long getFilePointer()
{
return position;
}
}

View File

@ -1,55 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.store.Lock;
/**
* This implementation of {@link org.apache.lucene.store.Lock Lock} is
* trivial as {@link DbDirectory} operations are managed by the Berkeley DB
* locking system.
*
*/
public class DbLock extends Lock {
boolean isLocked = false;
public DbLock()
{
}
@Override
public boolean obtain()
{
return (isLocked = true);
}
@Override
public void release()
{
isLocked = false;
}
@Override
public boolean isLocked()
{
return isLocked;
}
}

View File

@ -1,263 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.Random;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.db.internal.DbConstants;
import com.sleepycat.db.internal.Dbc;
import com.sleepycat.db.internal.Db;
import com.sleepycat.db.internal.DbTxn;
import com.sleepycat.db.DatabaseException;
public class File extends Object {
static protected Random random = new Random();
protected DatabaseEntry key, data;
protected long length, timeModified;
protected String name;
protected byte[] uuid;
protected File(String name)
throws IOException
{
setName(name);
data = new DatabaseEntry(new byte[32]);
data.setUserBuffer(data.getSize(), true);
}
protected File(DbDirectory directory, String name, boolean create)
throws IOException
{
this(name);
if (!exists(directory))
{
if (!create)
throw new IOException("File does not exist: " + name);
else
{
DatabaseEntry key = new DatabaseEntry(new byte[24]);
DatabaseEntry data = new DatabaseEntry((byte[]) null);
Db blocks = directory.blocks;
DbTxn txn = directory.txn;
int flags = directory.flags;
key.setUserBuffer(24, true);
data.setPartial(true);
uuid = new byte[16];
try {
do {
/* generate a v.4 random-uuid unique to this db */
random.nextBytes(uuid);
uuid[6] = (byte) ((byte) 0x40 |
(uuid[6] & (byte) 0x0f));
uuid[8] = (byte) ((byte) 0x80 |
(uuid[8] & (byte) 0x3f));
System.arraycopy(uuid, 0, key.getData(), 0, 16);
} while (blocks.get(txn, key, data,
flags) != DbConstants.DB_NOTFOUND);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
}
else if (create)
length = 0L;
}
protected String getName()
{
return name;
}
private void setName(String name)
throws IOException
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream(128);
DataOutputStream out = new DataOutputStream(buffer);
out.writeUTF(name);
out.close();
key = new DatabaseEntry(buffer.toByteArray());
key.setUserBuffer(key.getSize(), true);
this.name = name;
}
protected byte[] getKey()
throws IOException
{
if (uuid == null)
throw new IOException("Uninitialized file");
return uuid;
}
protected long getLength()
{
return length;
}
protected long getTimeModified()
{
return timeModified;
}
protected boolean exists(DbDirectory directory)
throws IOException
{
Db files = directory.files;
DbTxn txn = directory.txn;
int flags = directory.flags;
try {
if (files.get(txn, key, data, flags) == DbConstants.DB_NOTFOUND)
return false;
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
byte[] bytes = data.getData();
ByteArrayInputStream buffer = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(buffer);
length = in.readLong();
timeModified = in.readLong();
in.close();
uuid = new byte[16];
System.arraycopy(bytes, 16, uuid, 0, 16);
return true;
}
protected void modify(DbDirectory directory, long length, long timeModified)
throws IOException
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream(32);
DataOutputStream out = new DataOutputStream(buffer);
Db files = directory.files;
DbTxn txn = directory.txn;
out.writeLong(length);
out.writeLong(timeModified);
out.write(getKey());
out.close();
System.arraycopy(buffer.toByteArray(), 0, data.getData(), 0, 32);
try {
files.put(txn, key, data, 0);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
this.length = length;
this.timeModified = timeModified;
}
protected void delete(DbDirectory directory)
throws IOException
{
if (!exists(directory))
throw new IOException("File does not exist: " + getName());
Dbc cursor = null;
try {
try {
byte[] bytes = getKey();
int ulen = bytes.length + 8;
byte[] cursorBytes = new byte[ulen];
DatabaseEntry cursorKey = new DatabaseEntry(cursorBytes);
DatabaseEntry cursorData = new DatabaseEntry((byte[]) null);
Db files = directory.files;
Db blocks = directory.blocks;
DbTxn txn = directory.txn;
int flags = directory.flags;
System.arraycopy(bytes, 0, cursorBytes, 0, bytes.length);
cursorKey.setUserBuffer(ulen, true);
cursorData.setPartial(true);
cursor = blocks.cursor(txn, flags);
if (cursor.get(cursorKey, cursorData,
DbConstants.DB_SET_RANGE | flags) != DbConstants.DB_NOTFOUND)
{
cursor.del(0);
outer:
while (cursor.get(cursorKey, cursorData,
DbConstants.DB_NEXT | flags) != DbConstants.DB_NOTFOUND)
{
for (int i = 0; i < bytes.length; i++)
if (bytes[i] != cursorBytes[i])
break outer;
cursor.del(0);
}
}
files.del(txn, key, 0);
} finally {
if (cursor != null)
cursor.close();
}
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
protected void rename(DbDirectory directory, String name)
throws IOException
{
if (!exists(directory))
throw new IOException("File does not exist: " + getName());
File newFile = new File(name);
if (newFile.exists(directory))
newFile.delete(directory);
try {
Db files = directory.files;
DbTxn txn = directory.txn;
files.del(txn, key, 0);
setName(name);
files.put(txn, key, data, 0);
} catch (DatabaseException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -1,22 +0,0 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<body>
Berkeley DB 4.3 based implementation of {@link org.apache.lucene.store.Directory Directory}.
</body>
</html>

View File

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

View File

@ -1,413 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Date;
import java.util.Random;
import java.util.Arrays;
import java.io.File;
import java.io.IOException;
import com.sleepycat.db.EnvironmentConfig;
import com.sleepycat.db.Environment;
import com.sleepycat.db.Transaction;
import com.sleepycat.db.Database;
import com.sleepycat.db.DatabaseConfig;
import com.sleepycat.db.DatabaseType;
import com.sleepycat.db.DatabaseException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.util.LuceneTestCase;
/**
* Tests {@link DbDirectory}.
*
* Adapted from org.apache.lucene.StoreTest with larger files and random bytes.
*/
public class DbStoreTest extends LuceneTestCase {
protected File dbHome = new File(TEMP_DIR,"index");
protected Environment env;
protected Database index, blocks;
@Override
public void setUp() throws Exception {
super.setUp();
if (!dbHome.exists())
dbHome.mkdir();
else
{
File[] files = dbHome.listFiles();
for (int i = 0; i < files.length; i++) {
String name = files[i].getName();
if (name.startsWith("__") || name.startsWith("log."))
files[i].delete();
}
}
EnvironmentConfig envConfig = new EnvironmentConfig();
DatabaseConfig dbConfig = new DatabaseConfig();
envConfig.setTransactional(true);
envConfig.setInitializeCache(true);
envConfig.setInitializeLocking(true);
envConfig.setInitializeLogging(true);
envConfig.setAllowCreate(true);
envConfig.setThreaded(true);
dbConfig.setAllowCreate(true);
dbConfig.setType(DatabaseType.BTREE);
env = new Environment(dbHome, envConfig);
Transaction txn = null;
try {
txn = env.beginTransaction(null, null);
index = env.openDatabase(txn, "__index__", null, dbConfig);
blocks = env.openDatabase(txn, "__blocks__", null, dbConfig);
} catch (DatabaseException e) {
if (txn != null)
{
txn.abort();
txn = null;
}
index = null;
blocks = null;
throw e;
} finally {
if (txn != null)
txn.commit();
txn = null;
}
}
@Override
public void tearDown() throws Exception {
if (index != null)
index.close();
if (blocks != null)
blocks.close();
if (env != null)
env.close();
super.tearDown();
}
public void testBytes()
throws Exception
{
final int count = 250;
final int LENGTH_MASK = 0xffff;
Random r = random;
final long seed = r.nextLong();
Random gen = new Random(seed);
int totalLength = 0;
int duration;
Date end;
Date veryStart = new Date();
Date start = new Date();
Transaction txn = env.beginTransaction(null, null);
Directory store = null;
if (VERBOSE) System.out.println("Writing files byte by byte");
try {
store = new DbDirectory(txn, index, blocks);
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexOutput file = store.createOutput(name);
totalLength += length;
for (int j = 0; j < length; j++) {
byte b = (byte)(gen.nextInt() & 0x7F);
file.writeByte(b);
}
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to create, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new DbDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexInput file = store.openInput(name);
if (file.length() != length)
throw new Exception("length incorrect");
for (int j = 0; j < length; j++) {
byte b = (byte)(gen.nextInt() & 0x7F);
if (file.readByte() != b)
throw new Exception("contents incorrect");
}
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null)
{
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new DbDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
store.deleteFile(name);
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null)
{
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete");
System.out.print(end.getTime() - veryStart.getTime());
System.out.println(" total milliseconds");
}
}
public void testArrays()
throws Exception
{
final int count = 250;
final int LENGTH_MASK = 0xffff;
Random r = random;
final long seed = r.nextLong();
Random gen = new Random(seed);
int totalLength = 0;
int duration;
Date end;
Date veryStart = new Date();
Date start = new Date();
Transaction txn = env.beginTransaction(null, null);
Directory store = null;
if (VERBOSE) System.out.println("Writing files as one byte array");
try {
store = new DbDirectory(txn, index, blocks);
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexOutput file = store.createOutput(name);
byte[] data = new byte[length];
totalLength += length;
gen.nextBytes(data);
file.writeBytes(data, length);
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to create, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new DbDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
int length = gen.nextInt() & LENGTH_MASK;
IndexInput file = store.openInput(name);
if (file.length() != length)
throw new Exception("length incorrect");
byte[] data = new byte[length];
byte[] read = new byte[length];
gen.nextBytes(data);
file.readBytes(read, 0, length);
if (!Arrays.equals(data, read))
throw new Exception("contents incorrect");
file.close();
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null)
{
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
duration = (int) (end.getTime() - start.getTime());
System.out.print(duration);
System.out.print(" total milliseconds to read, ");
System.out.print(totalLength / duration);
System.out.println(" kb/s");
}
try {
txn = env.beginTransaction(null, null);
store = new DbDirectory(txn, index, blocks);
gen = new Random(seed);
start = new Date();
for (int i = 0; i < count; i++) {
String name = i + ".dat";
store.deleteFile(name);
}
} catch (IOException e) {
txn.abort();
txn = null;
throw e;
} catch (DatabaseException e) {
if (txn != null)
{
txn.abort();
txn = null;
}
throw e;
} finally {
if (txn != null)
txn.commit();
store.close();
}
end = new Date();
if (VERBOSE) {
System.out.print(end.getTime() - start.getTime());
System.out.println(" total milliseconds to delete");
System.out.print(end.getTime() - veryStart.getTime());
System.out.println(" total milliseconds");
}
}
}

View File

@ -1,36 +0,0 @@
package org.apache.lucene.store.db;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.sleepycat.db.EnvironmentConfig;
import com.sleepycat.db.Environment;
/**
* Simple sanity testing application to verify that the underlying
* native library can be loaded cleanly.
*
* For use in the build.xml of this contrib, to determine if tests
* should be skipped.
*/
public class SanityLoadLibrary {
public static void main(String[] ignored) throws Exception {
EnvironmentConfig envConfig = EnvironmentConfig.DEFAULT;
envConfig.setAllowCreate(false);
new Environment(null, envConfig);
}
}

View File

@ -1,74 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="db" default="default">
<description>
Lucene DB integration
- bdb: using the Java interface of C Berkeley DB
- bdb-je: using Berkeley DB Java Edition
</description>
<!-- we dont import contrib-build.xml here, as this file only delegates to the real build files -->
<target name="bdb">
<ant dir="bdb" />
</target>
<target name="bdb-je">
<ant dir="bdb-je" />
</target>
<target name="default" depends="bdb,bdb-je" />
<target name="clean">
<ant dir="bdb" target="clean" />
<ant dir="bdb-je" target="clean" />
</target>
<target name="compile-core">
<ant dir="bdb" target="compile-core" />
<ant dir="bdb-je" target="compile-core" />
</target>
<target name="compile-test">
<ant dir="bdb" target="compile-test" />
<ant dir="bdb-je" target="compile-test" />
</target>
<target name="test">
<ant dir="bdb" target="test" />
<ant dir="bdb-je" target="test" />
</target>
<target name="build-artifacts-and-tests" depends="default,compile-test" />
<target name="dist-maven" depends="default">
<ant dir="bdb" target="dist-maven" />
<ant dir="bdb-je" target="dist-maven" />
</target>
<target name="javadocs">
<ant dir="bdb" target="javadocs" />
<ant dir="bdb-je" target="javadocs" />
</target>
<target name="javadocs-index.html">
<ant dir="bdb" target="javadocs-index.html" />
<ant dir="bdb-je" target="javadocs-index.html" />
</target>
</project>

View File

@ -1,24 +0,0 @@
lucli (pronounced Luckily) is the Lucene Command Line Interface.
INSTALLATION
Call "ant", then call the run.sh shell script. If it doesn't work right away:
Edit JAVA_HOME to point to your java directory.
Edit LUCLI to point to where you installed lucli.
Edit LUCLI_MEMORY and set it to the maximum amount of memory you want to allocate to lucli
You can also replace the Lucene jar file that came with lucli with your own.
ENABLING READLINE
Readline support should automatically work thanks to JLine, see http://jline.sourceforge.net/
Documentation
There is none :-). Type help at the command line or read the code.
Enjoy
Dror Matalon
dror@zapatec.com.

View File

@ -1,71 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="lucli" default="jar">
<description>
Lucene Command Line Interface
</description>
<path id="additional.dependencies">
<pathelement location="lib/jline.jar"/>
</path>
<pathconvert property="project.classpath"
targetos="unix"
refid="additional.dependencies"
/>
<import file="../contrib-build.xml"/>
<module-uptodate name="analysis/common" jarfile="${common.dir}/../modules/analysis/build/common/lucene-analyzers-common-${version}.jar"
property="analyzers-common.uptodate" classpath.property="analyzers-common.jar"/>
<path id="classpath">
<pathelement path="${analyzers-common.jar}"/>
<path refid="base.classpath"/>
</path>
<target name="compile-core" depends="compile-analyzers-common, common.compile-core" />
<target name="compile-analyzers-common" unless="analyzers-common.uptodate">
<subant target="default">
<fileset dir="${common.dir}/../modules/analysis/common" includes="build.xml"/>
</subant>
</target>
<target name="jar" depends="compile" description="Create JAR">
<jarify>
<manifest-attributes>
<attribute name="Main-Class" value="lucli.Lucli" />
<attribute name="Class-Path" value="lib/jline.jar lib/lucene.jar" />
</manifest-attributes>
</jarify>
</target>
<target name="jar-src" depends="init">
<jarify basedir="${src.dir}" destfile="${build.dir}/${final.name}-src.jar">
<manifest-attributes>
<attribute name="Main-Class" value="lucli.Lucli" />
<attribute name="Class-Path" value="lib/jline.jar lib/lucene.jar" />
</manifest-attributes>
</jarify>
</target>
</project>

View File

@ -1,33 +0,0 @@
Copyright (c) 2002, 2003, 2004, 2005, Marc Prud'hommeaux <mwp1@cornell.edu>
All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
Neither the name of JLine nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,2 +0,0 @@
JLine (under contrib/lucli/lib/jline.jar) is licensed under the BSD License.
See http://jline.sourceforge.net/

View File

@ -1,2 +0,0 @@
AnyObjectId[b841cf167aa3ca6c82f2e40ba2fd8732e829525f] was removed in git history.
Apache SVN contains full history.

View File

@ -1,22 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LUCLI=.
LUCLI_MEMORY=128M
#JAVA_HOME=/home/dror/j2sdk1.4.1_03/
CLASSPATH=${CLASSPATH}:$LUCLI/lib/jline.jar:$LUCLI/lib/lucene.jar:$LUCLI/dist/lucli-dev.jar
export CLASSPATH
$JAVA_HOME/bin/java -Xmx${LUCLI_MEMORY} lucli.Lucli

View File

@ -1,406 +0,0 @@
package lucli;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import jline.ConsoleReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Fields;
import org.apache.lucene.index.FieldsEnum;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.index.MultiFields;
import org.apache.lucene.index.IndexReader.FieldOption;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.util.BytesRef;
/**
* Various methods that interact with Lucene and provide info about the
* index, search, etc. Parts adapted from Lucene demo.
*/
class LuceneMethods {
private int numDocs;
private final FSDirectory indexName; //directory of this index
private List<String> fields; //Fields as a vector
private List<String> indexedFields; //Fields as a vector
private String fieldsArray[]; //Fields as an array
private IndexSearcher searcher;
private Query query; //current query string
private String analyzerClassFQN = null; // Analyzer class, if NULL, use default Analyzer
public LuceneMethods(String index) throws IOException {
indexName = FSDirectory.open(new File(index));
message("Lucene CLI. Using directory '" + indexName + "'. Type 'help' for instructions.");
}
private Analyzer createAnalyzer() {
if (analyzerClassFQN == null) return new StandardAnalyzer(Version.LUCENE_CURRENT);
try {
return Class.forName(analyzerClassFQN).asSubclass(Analyzer.class).newInstance();
} catch (ClassCastException cce) {
message("Given class is not an Analyzer: " + analyzerClassFQN);
return new StandardAnalyzer(Version.LUCENE_CURRENT);
} catch (Exception e) {
message("Unable to use Analyzer " + analyzerClassFQN);
return new StandardAnalyzer(Version.LUCENE_CURRENT);
}
}
public void info() throws java.io.IOException {
IndexReader indexReader = IndexReader.open(indexName, true);
getFieldInfo();
numDocs = indexReader.numDocs();
message("Index has " + numDocs + " documents ");
message("All Fields:" + fields.toString());
message("Indexed Fields:" + indexedFields.toString());
if (IndexWriter.isLocked(indexName)) {
message("Index is locked");
}
//IndexReader.getCurrentVersion(indexName);
//System.out.println("Version:" + version);
indexReader.close();
}
public void search(String queryString, boolean explain, boolean showTokens, ConsoleReader cr)
throws java.io.IOException, org.apache.lucene.queryParser.ParseException {
initSearch(queryString);
int numHits = computeCount(query);
message(numHits + " total matching documents");
if (explain) {
query = explainQuery(queryString);
}
final int HITS_PER_PAGE = 10;
message("--------------------------------------");
for (int start = 0; start < numHits; start += HITS_PER_PAGE) {
int end = Math.min(numHits, start + HITS_PER_PAGE);
ScoreDoc[] hits = search(query, end);
for (int ii = start; ii < end; ii++) {
Document doc = searcher.doc(hits[ii].doc);
message("---------------- " + (ii + 1) + " score:" + hits[ii].score + "---------------------");
printHit(doc);
if (showTokens) {
invertDocument(doc);
}
if (explain) {
Explanation exp = searcher.explain(query, hits[ii].doc);
message("Explanation:" + exp.toString());
}
}
message("#################################################");
if (numHits > end) {
// TODO: don't let the input end up in the command line history
queryString = cr.readLine("more (y/n) ? ");
if (queryString.length() == 0 || queryString.charAt(0) == 'n')
break;
}
}
searcher.close();
}
/**
* TODO: Allow user to specify what field(s) to display
*/
private void printHit(Document doc) {
for (int ii = 0; ii < fieldsArray.length; ii++) {
String currField = fieldsArray[ii];
String[] result = doc.getValues(currField);
if (result != null) {
for (int i = 0; i < result.length; i++) {
message(currField + ":" + result[i]);
}
} else {
message(currField + ": <not available>");
}
}
//another option is to just do message(doc);
}
public void optimize() throws IOException {
//open the index writer. False: don't create a new one
IndexWriter indexWriter = new IndexWriter(indexName, new IndexWriterConfig(
Version.LUCENE_CURRENT, createAnalyzer()).setOpenMode(
OpenMode.APPEND));
message("Starting to optimize index.");
long start = System.currentTimeMillis();
indexWriter.optimize();
message("Done optimizing index. Took " + (System.currentTimeMillis() - start) + " msecs");
indexWriter.close();
}
private Query explainQuery(String queryString) throws IOException, ParseException {
searcher = new IndexSearcher(indexName, true);
Analyzer analyzer = createAnalyzer();
getFieldInfo();
int arraySize = indexedFields.size();
String indexedArray[] = new String[arraySize];
for (int ii = 0; ii < arraySize; ii++) {
indexedArray[ii] = indexedFields.get(ii);
}
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, indexedArray, analyzer);
query = parser.parse(queryString);
message("Searching for: " + query.toString());
return (query);
}
/**
* TODO: Allow user to specify analyzer
*/
private void initSearch(String queryString) throws IOException, ParseException {
searcher = new IndexSearcher(indexName, true);
Analyzer analyzer = createAnalyzer();
getFieldInfo();
int arraySize = fields.size();
fieldsArray = new String[arraySize];
for (int ii = 0; ii < arraySize; ii++) {
fieldsArray[ii] = fields.get(ii);
}
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, fieldsArray, analyzer);
query = parser.parse(queryString);
System.out.println("Searching for: " + query.toString());
}
final static class CountingCollector extends Collector {
public int numHits = 0;
@Override
public void setScorer(Scorer scorer) throws IOException {}
@Override
public void collect(int doc) throws IOException {
numHits++;
}
@Override
public void setNextReader(AtomicReaderContext context) {}
@Override
public boolean acceptsDocsOutOfOrder() {
return true;
}
}
private int computeCount(Query q) throws IOException {
CountingCollector countingCollector = new CountingCollector();
searcher.search(q, countingCollector);
return countingCollector.numHits;
}
public void count(String queryString) throws java.io.IOException, ParseException {
initSearch(queryString);
message(computeCount(query) + " total documents");
searcher.close();
}
private ScoreDoc[] search(Query q, int numHits) throws IOException {
return searcher.search(query, numHits).scoreDocs;
}
static public void message(String s) {
System.out.println(s);
}
private void getFieldInfo() throws IOException {
IndexReader indexReader = IndexReader.open(indexName, true);
fields = new ArrayList<String>();
indexedFields = new ArrayList<String>();
//get the list of all field names
for(String field : indexReader.getFieldNames(FieldOption.ALL)) {
if (field != null && !field.equals(""))
fields.add(field.toString());
}
//
//get the list of indexed field names
for(String field : indexReader.getFieldNames(FieldOption.INDEXED)) {
if (field != null && !field.equals(""))
indexedFields.add(field.toString());
}
indexReader.close();
}
// Copied from DocumentWriter
// Tokenizes the fields of a document into Postings.
private void invertDocument(Document doc)
throws IOException {
Map<String,Integer> tokenMap = new HashMap<String,Integer>();
final int maxFieldLength = 10000;
Analyzer analyzer = createAnalyzer();
for (Fieldable field : doc.getFields()) {
String fieldName = field.name();
if (field.isIndexed()) {
if (field.isTokenized()) { // un-tokenized field
Reader reader; // find or make Reader
if (field.readerValue() != null)
reader = field.readerValue();
else if (field.stringValue() != null)
reader = new StringReader(field.stringValue());
else
throw new IllegalArgumentException
("field must have either String or Reader value");
int position = 0;
// Tokenize field and add to postingTable
TokenStream stream = analyzer.reusableTokenStream(fieldName, reader);
CharTermAttribute termAtt = stream.addAttribute(CharTermAttribute.class);
PositionIncrementAttribute posIncrAtt = stream.addAttribute(PositionIncrementAttribute.class);
try {
stream.reset();
while (stream.incrementToken()) {
position += (posIncrAtt.getPositionIncrement() - 1);
position++;
String name = termAtt.toString();
Integer Count = tokenMap.get(name);
if (Count == null) { // not in there yet
tokenMap.put(name, Integer.valueOf(1)); //first one
} else {
int count = Count.intValue();
tokenMap.put(name, Integer.valueOf(count + 1));
}
if (position > maxFieldLength) break;
}
stream.end();
} finally {
stream.close();
}
}
}
}
Map.Entry<String,Integer>[] sortedHash = getSortedMapEntries(tokenMap);
for (int ii = 0; ii < sortedHash.length && ii < 10; ii++) {
Map.Entry<String,Integer> currentEntry = sortedHash[ii];
message((ii + 1) + ":" + currentEntry.getKey() + " " + currentEntry.getValue());
}
}
/** Provides a list of the top terms of the index.
*
* @param field - the name of the command or null for all of them.
*/
public void terms(String field) throws IOException {
TreeMap<String,Integer> termMap = new TreeMap<String,Integer>();
IndexReader indexReader = IndexReader.open(indexName, true);
Fields fields = MultiFields.getFields(indexReader);
if (fields != null) {
FieldsEnum fieldsEnum = fields.iterator();
String curField;
while((curField = fieldsEnum.next()) != null) {
TermsEnum terms = fieldsEnum.terms();
BytesRef text;
while ((text = terms.next()) != null) {
//message(term.field() + ":" + term.text() + " freq:" + terms.docFreq());
//if we're either not looking by field or we're matching the specific field
if ((field == null) || field.equals(curField)) {
termMap.put(curField + ":" + text.utf8ToString(), Integer.valueOf((terms.docFreq())));
}
}
}
}
Iterator<String> termIterator = termMap.keySet().iterator();
for (int ii = 0; termIterator.hasNext() && ii < 100; ii++) {
String termDetails = termIterator.next();
Integer termFreq = termMap.get(termDetails);
message(termDetails + ": " + termFreq);
}
indexReader.close();
}
/** Sort Map values
* @param m the map we're sorting
* from http://developer.java.sun.com/developer/qow/archive/170/index.jsp
*/
@SuppressWarnings("unchecked")
public static <K,V extends Comparable<V>> Map.Entry<K,V>[]
getSortedMapEntries(Map<K,V> m) {
Set<Map.Entry<K, V>> set = m.entrySet();
Map.Entry<K,V>[] entries =
set.toArray(new Map.Entry[set.size()]);
Arrays.sort(entries, new Comparator<Map.Entry<K,V>>() {
public int compare(Map.Entry<K,V> o1, Map.Entry<K,V> o2) {
V v1 = o1.getValue();
V v2 = o2.getValue();
return v2.compareTo(v1); //descending order
}
});
return entries;
}
public void analyzer(String word) {
if ("current".equals(word)) {
String current = analyzerClassFQN == null ? "StandardAnalyzer" : analyzerClassFQN;
message("The currently used Analyzer class is: " + current);
return;
}
analyzerClassFQN = word;
message("Switched to Analyzer class " + analyzerClassFQN);
}
}

View File

@ -1,321 +0,0 @@
package lucli;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
import jline.FileNameCompletor;
import jline.History;
import jline.SimpleCompletor;
import org.apache.lucene.queryParser.ParseException;
/**
* Main class for lucli: the Lucene Command Line Interface.
* This class handles mostly the actual CLI part, command names, help, etc.
*/
public class Lucli {
final static String DEFAULT_INDEX = "index"; //directory "index" under the current directory
final static String HISTORYFILE = ".lucli"; //history file in user's home directory
public final static int MAX_TERMS = 100; //Maximum number of terms we're going to show
// List of commands
// To add another command, add it in here, in the list of addcomand(), and in the switch statement
final static int NOCOMMAND = -2;
final static int UNKOWN = -1;
final static int INFO = 0;
final static int SEARCH = 1;
final static int OPTIMIZE = 2;
final static int QUIT = 3;
final static int HELP = 4;
final static int COUNT = 5;
final static int TERMS = 6;
final static int INDEX = 7;
final static int TOKENS = 8;
final static int EXPLAIN = 9;
final static int ANALYZER = 10;
String historyFile;
TreeMap<String,Command> commandMap = new TreeMap<String,Command>();
LuceneMethods luceneMethods; //current cli class we're using
boolean enableReadline; //false: use plain java. True: shared library readline
/**
Main entry point. The first argument can be a filename with an
application initialization file.
*/
public Lucli(String[] args) throws IOException {
String line;
historyFile = System.getProperty("user.home") + File.separator + HISTORYFILE;
/*
* Initialize the list of commands
*/
addCommand("info", INFO, "Display info about the current Lucene index. Example: info");
addCommand("search", SEARCH, "Search the current index. Example: search foo", 1);
addCommand("count", COUNT, "Return the number of hits for a search. Example: count foo", 1);
addCommand("optimize", OPTIMIZE, "Optimize the current index");
addCommand("quit", QUIT, "Quit/exit the program");
addCommand("help", HELP, "Display help about commands");
addCommand("terms", TERMS, "Show the first " + MAX_TERMS + " terms in this index. Supply a field name to only show terms in a specific field. Example: terms");
addCommand("index", INDEX, "Choose a different lucene index. Example index my_index", 1);
addCommand("tokens", TOKENS, "Does a search and shows the top 10 tokens for each document. Verbose! Example: tokens foo", 1);
addCommand("explain", EXPLAIN, "Explanation that describes how the document scored against query. Example: explain foo", 1);
addCommand("analyzer", ANALYZER, "Specifies the Analyzer class to be used. Example: analyzer org.apache.lucene.analysis.SimpleAnalyzer", 1);
//parse command line arguments
parseArgs(args);
ConsoleReader cr = new ConsoleReader();
//Readline.readHistoryFile(fullPath);
cr.setHistory(new History(new File(historyFile)));
// set completer with list of words
Completor[] comp = new Completor[]{
new SimpleCompletor(getCommandsAsArray()),
new FileNameCompletor()
};
cr.addCompletor (new ArgumentCompletor(comp));
// main input loop
luceneMethods = new LuceneMethods(DEFAULT_INDEX);
while (true) {
try {
line = cr.readLine("lucli> ");
if (line != null) {
handleCommand(line, cr);
}
} catch (java.io.EOFException eof) {
System.out.println("");//new line
exit();
} catch (UnsupportedEncodingException enc) {
enc.printStackTrace(System.err);
} catch (ParseException pe) {
pe.printStackTrace(System.err);
} catch (IOException ioe) {
ioe.printStackTrace(System.err);
}
}
}
private String[] getCommandsAsArray() {
Set<String> commandSet = commandMap.keySet();
String[] commands = new String[commandMap.size()];
int i = 0;
for (Iterator<String> iter = commandSet.iterator(); iter.hasNext();) {
String cmd = iter.next();
commands[i++] = cmd;
}
return commands;
}
public static void main(String[] args) throws IOException {
new Lucli(args);
}
private void handleCommand(String line, ConsoleReader cr) throws IOException, ParseException {
String [] words = tokenizeCommand(line);
if (words.length == 0)
return; //white space
String query = "";
if (line.trim().startsWith("#")) // # = comment
return;
//Command name and number of arguments
switch (getCommandId(words[0], words.length - 1)) {
case INFO:
luceneMethods.info();
break;
case SEARCH:
for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " ";
}
luceneMethods.search(query, false, false, cr);
break;
case COUNT:
for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " ";
}
luceneMethods.count(query);
break;
case QUIT:
exit();
break;
case TERMS:
if(words.length > 1)
luceneMethods.terms(words[1]);
else
luceneMethods.terms(null);
break;
case INDEX:
LuceneMethods newLm = new LuceneMethods(words[1]);
try {
newLm.info(); //will fail if can't open the index
luceneMethods = newLm; //OK, so we'll use the new one
} catch (IOException ioe) {
//problem we'll keep using the old one
error(ioe.toString());
}
break;
case OPTIMIZE:
luceneMethods.optimize();
break;
case TOKENS:
for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " ";
}
luceneMethods.search(query, false, true, cr);
break;
case EXPLAIN:
for (int ii = 1; ii < words.length; ii++) {
query += words[ii] + " ";
}
luceneMethods.search(query, true, false, cr);
break;
case ANALYZER:
luceneMethods.analyzer(words[1]);
break;
case HELP:
help();
break;
case NOCOMMAND: //do nothing
break;
case UNKOWN:
System.out.println("Unknown command: " + words[0] + ". Type help to get a list of commands.");
break;
}
}
private String [] tokenizeCommand(String line) {
StringTokenizer tokenizer = new StringTokenizer(line, " \t");
int size = tokenizer.countTokens();
String [] tokens = new String[size];
for (int ii = 0; tokenizer.hasMoreTokens(); ii++) {
tokens[ii] = tokenizer.nextToken();
}
return tokens;
}
private void exit() {
System.exit(0);
}
/**
* Add a command to the list of commands for the interpreter for a
* command that doesn't take any parameters.
* @param name - the name of the command
* @param id - the unique id of the command
* @param help - the help message for this command
*/
private void addCommand(String name, int id, String help) {
addCommand(name, id, help, 0);
}
/**
* Add a command to the list of commands for the interpreter.
* @param name - the name of the command
* @param id - the unique id of the command
* @param help - the help message for this command
* @param params - the minimum number of required params if any
*/
private void addCommand(String name, int id, String help, int params) {
Command command = new Command(name, id, help, params);
commandMap.put(name, command);
}
private int getCommandId(String name, int params) {
name = name.toLowerCase(); //treat uppercase and lower case commands the same
Command command = commandMap.get(name);
if (command == null) {
return(UNKOWN);
}
else {
if(command.params > params) {
error(command.name + " needs at least " + command.params + " arguments.");
return (NOCOMMAND);
}
return (command.id);
}
}
private void help() {
Iterator<String> commands = commandMap.keySet().iterator();
while (commands.hasNext()) {
Command command = commandMap.get(commands.next());
System.out.println("\t" + command.name + ": " + command.help);
}
}
private void error(String message) {
System.err.println("Error:" + message);
}
private void message(String text) {
System.out.println(text);
}
/*
* Parse command line arguments (currently none)
*/
private void parseArgs(String[] args) {
if (args.length > 0) {
usage();
System.exit(1);
}
}
private void usage() {
message("Usage: lucli.Lucli");
message("(currently, no parameters are supported)");
}
private class Command {
String name;
int id;
String help;
int params;
Command(String name, int id, String help, int params) {
this.name = name;
this.id = id;
this.help = help;
this.params = params;
}
/**
* Prints out a usage message for this command.
*/
public String commandUsage() {
return (name + ":" + help + ". Command takes " + params + " params");
}
}
}

View File

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

View File

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

View File

@ -1,57 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="swing" default="default">
<description>
Swing Models
</description>
<import file="../contrib-build.xml"/>
<module-uptodate name="analysis/common" jarfile="${common.dir}/../modules/analysis/build/common/lucene-analyzers-common-${version}.jar"
property="analyzers-common.uptodate" classpath.property="analyzers-common.jar"/>
<path id="classpath">
<pathelement path="${analyzers-common.jar}"/>
<path refid="base.classpath"/>
</path>
<target name="compile-core" depends="compile-analyzers-common, common.compile-core" />
<target name="compile-analyzers-common" unless="analyzers-common.uptodate">
<subant target="default">
<fileset dir="${common.dir}/../modules/analysis/common" includes="build.xml"/>
</subant>
</target>
<target name="list-demo" depends="compile">
<java classname="org.apache.lucene.swing.models.ListSearcherSimulator"
fork="yes" spawn="yes"
classpathref="test.classpath"
/>
</target>
<target name="table-demo" depends="compile">
<java classname="org.apache.lucene.swing.models.TableSearcherSimulator"
fork="yes" spawn="yes"
classpathref="test.classpath"
/>
</target>
</project>

View File

@ -1,97 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Lucene Powered Swing Data Models</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h1><strong> Lucene Powered Swing Data Models </strong></h1>
<p><strong>by Jonathan Simon </strong></p>
<p>&nbsp;</p>
<p><strong>What it is.</strong></p>
<p>This package contains classes that help you easily integrate Lucene based searching
into your Swing components. Currently there are classes to index and search
JTables and JLists. This is done using model decorators rather than custom models
to make it easier to search current models as well as new ones. </p>
<p><em>These models do not actually contain any data</em>. Rather, the ListModel
decorator (ListSearcher) and the TableModel decorator (TableSearcher) take a
model in the constructor and delegate all calls to it (after a little alteration,
but we'll get to that). That said, these are not full fledged models themselves.
You still have to have another model to decorate with the searching models.
If you are adding searching to a pre-existing model, you can use your pre-existing
model directly. Otherwise, you can implement a model from scratch or use a pre-existing
one to get started. </p>
<p><strong>What it isn't. </strong></p>
<p>A complete component: These are just models. They are not complete components
with search fields and buttons laid out like a searchable interface. You still
have to build that since the UI changes drastically between applciations.</p>
<p>A complete model: There are just model decorators. You can't just set the model
of a JList or JTable to one of these models, and you can't add data directly
to these models. </p>
<p>A front end for a lucene index: In other words, you can't use these classes
to point a JTable directly to a Lucene index. Although that's interesting in
its own right, this is not that. </p>
<p><strong>Usage: </strong></p>
<p>Coding to both models nearly identical. They both take the model to decorate
at construction time. Here is the code from the demo to decorate a JTable model
with the TableSearcher and set it as the table model. </p>
<pre><code>//make a new JTable
JTable table = new JTable();
//make my base model, the model with the data
BaseTableModel tableModel = new BaseTableModel(DataStore.getRestaurants());
//decorate the tableModel with the TableSearcher
TableSearcher searchTableModel = new TableSearcher(tableModel);
//set the TableModel in the table to the TableSearcher
table.setModel(searchTableModel);
</code></pre>
<p>Initially, you won't notice a difference. This is because there is no active
search which displays all data from the underlying model. You search by calling
the <code>search</code>() method passing a search string. This filters the data
set down without changing the underlying data model -- one of the main reasons
for decorating in the first place. Any valid Lucene search string should work
(see notes for more info on this). You'll probaby have some code somewhere like
this in your app to connect a text field and search button to the model. </p>
<pre><code>//create components
final JTextField searchField = new JTextField();
JButton searchButton = new JButton("Go");
//make an action listener
ActionListener searchListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
searchTableModel.search(searchField.getText().trim().toLowerCase());
}
};
//register listeners
searchButton.addActionListener(searchListener);
searchField.addActionListener(searchListener);</code></pre>
<p>You also might want to have a clear search button, working the same way. But
to keep things simple, if you search will a <code>null </code>String or an empty
String, the search clears and you will once again see all of your data. </p>
<p><strong>Demo notes:</strong> </p>
<p>The list demo does real time searching. In other words, as you type, searches
run and the result set updates. The table demo has a search button, and only
searches when the button is clicked. They both work, I just implemented them
this way to show the different UI metaphors and that they both work.</p>
<p><strong>Implementation notes: </strong></p>
<p>This code started as a proof of concept so it's not a <em>fully</em> featured
model. Don't get me wrong, it <em>fully</em> works, but it could use some improvement
that it will hopefully get over time. I just wanted to get it out there and
get people using it. I'm also trying to keep everything as simple as possible.
Here are some of the issues. </p>
<ul>
<li>You can't change the model after the Searcher is constructed. </li>
<li>The search model decorators <em>do</em> update when the decorated model
is updated, but not in a very efficient way. The whole search model is reindexed
when anything changes. This is a definite scaling issue. </li>
<li>The indexing and searching logic needs to be generally more configurable
to allow custom tailoring of searched and indexing. </li>
<li>The TableSearcher uses column names to index column values. This could be
an issue with multiple word column names. </li>
<li>The ListSearcher uses MultiFieldQueryParser even though its not really indexing
multiple fields. </li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>

View File

@ -1,311 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
/**
* See table searcher explanation.
*
*/
public class ListSearcher extends AbstractListModel {
private ListModel listModel;
/**
* The reference links between the decorated ListModel
* and this list model based on search criteria
*/
private ArrayList<Integer> rowToModelIndex = new ArrayList<Integer>();
/**
* In memory lucene index
*/
private RAMDirectory directory;
/**
* Cached lucene analyzer
*/
private Analyzer analyzer;
/**
* Links between this list model and the decorated list model
* are maintained through links based on row number. This is a
* key constant to denote "row number" for indexing
*/
private static final String ROW_NUMBER = "ROW_NUMBER";
/**
* Since we only have one field, unlike lists with multiple
* fields -- we are just using a constant to denote field name.
* This is most likely unnecessary and should be removed at
* a later date
*/
private static final String FIELD_NAME = "FIELD_NAME";
/**
* Cache the current search String. Also used internally to
* key whether there is an active search running or not. i.e. if
* searchString is null, there is no active search.
*/
private String searchString = null;
private ListDataListener listModelListener;
public ListSearcher(ListModel newModel) {
analyzer = new WhitespaceAnalyzer(Version.LUCENE_CURRENT);
setListModel(newModel);
listModelListener = new ListModelHandler();
newModel.addListDataListener(listModelListener);
clearSearchingState();
}
private void setListModel(ListModel newModel) {
//remove listeners if there...
if (newModel != null) {
newModel.removeListDataListener(listModelListener);
}
listModel = newModel;
if (listModel != null) {
listModel.addListDataListener(listModelListener);
}
//recalculate the links between this list model and
//the inner list model since the decorated model just changed
reindex();
// let all listeners know the list has changed
fireContentsChanged(this, 0, getSize());
}
private void reindex() {
try {
// recreate the RAMDirectory
directory = new RAMDirectory();
IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_CURRENT, analyzer));
// iterate through all rows
for (int row=0; row < listModel.getSize(); row++){
//for each row make a new document
Document document = new Document();
//add the row number of this row in the decorated list model
//this will allow us to retrieve the results later
//and map this list model's row to a row in the decorated
//list model
document.add(new Field(ROW_NUMBER, "" + row, Field.Store.YES, Field.Index.ANALYZED));
//add the string representation of the row to the index
document.add(new Field(FIELD_NAME, String.valueOf(listModel.getElementAt(row)).toLowerCase(), Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(document);
}
writer.optimize();
writer.close();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* Run a new search.
*
* @param searchString Any valid lucene search string
*/
public void search(String searchString){
//if search string is null or empty, clear the search == search all
if (searchString == null || searchString.equals("")){
clearSearchingState();
fireContentsChanged(this, 0, getSize());
return;
}
try {
//cache search String
this.searchString = searchString;
//make a new index searcher with the in memory (RAM) index.
IndexSearcher is = new IndexSearcher(directory, true);
//make an array of fields - one for each column
String[] fields = {FIELD_NAME};
//build a query based on the fields, searchString and cached analyzer
//NOTE: This is an area for improvement since the MultiFieldQueryParser
// has some weirdness.
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, fields, analyzer);
Query query =parser.parse(searchString);
//reset this list model with the new results
resetSearchResults(is, query);
} catch (Exception e){
e.printStackTrace();
}
//notify all listeners that the list has been changed
fireContentsChanged(this, 0, getSize());
}
final static class CountingCollector extends Collector {
public int numHits = 0;
@Override
public void setScorer(Scorer scorer) throws IOException {}
@Override
public void collect(int doc) throws IOException {
numHits++;
}
@Override
public void setNextReader(AtomicReaderContext context) {}
@Override
public boolean acceptsDocsOutOfOrder() {
return true;
}
}
/**
*
* @param hits The new result set to set this list to.
*/
private void resetSearchResults(IndexSearcher searcher, Query query) {
try {
//clear our index mapping this list model rows to
//the decorated inner list model
rowToModelIndex.clear();
CountingCollector countingCollector = new CountingCollector();
searcher.search(query, countingCollector);
ScoreDoc[] hits = searcher.search(query, countingCollector.numHits).scoreDocs;
//iterate through the hits
//get the row number stored at the index
//that number is the row number of the decorated
//table model row that we are mapping to
for (int t=0; t<hits.length; t++){
Document document = searcher.doc(hits[t].doc);
Fieldable field = document.getField(ROW_NUMBER);
rowToModelIndex.add(Integer.valueOf(field.stringValue()));
}
} catch (Exception e){
e.printStackTrace();
}
}
/**
* @return The current lucene analyzer
*/
public Analyzer getAnalyzer() {
return analyzer;
}
/**
* @param analyzer The new analyzer to use
*/
public void setAnalyzer(Analyzer analyzer) {
this.analyzer = analyzer;
//reindex from the model with the new analyzer
reindex();
//rerun the search if there is an active search
if (isSearching()){
search(searchString);
}
}
private boolean isSearching() {
return searchString != null;
}
private void clearSearchingState() {
searchString = null;
rowToModelIndex.clear();
for (int t=0; t<listModel.getSize(); t++){
rowToModelIndex.add(t);
}
}
private int getModelRow(int row){
return rowToModelIndex.get(row);
}
public int getSize() {
return (listModel == null) ? 0 : rowToModelIndex.size();
}
public Object getElementAt(int index) {
return listModel.getElementAt(getModelRow(index));
}
class ListModelHandler implements ListDataListener {
public void contentsChanged(ListDataEvent e) {
somethingChanged();
}
public void intervalAdded(ListDataEvent e) {
somethingChanged();
}
public void intervalRemoved(ListDataEvent e) {
somethingChanged();
}
private void somethingChanged(){
// If we're not searching, just pass the event along.
if (!isSearching()) {
clearSearchingState();
reindex();
fireContentsChanged(ListSearcher.this, 0, getSize());
return;
}
// Something has happened to the data that may have invalidated the search.
reindex();
search(searchString);
fireContentsChanged(ListSearcher.this, 0, getSize());
return;
}
}
}

View File

@ -1,362 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.swing.models.ListSearcher.CountingCollector;
import org.apache.lucene.util.Version;
/**
* This is a TableModel that encapsulates Lucene
* search logic within a TableModel implementation.
* It is implemented as a TableModel decorator,
* similar to the TableSorter demo from Sun that decorates
* a TableModel and provides sorting functionality. The benefit
* of this architecture is that you can decorate any TableModel
* implementation with this searching table model -- making it
* easy to add searching functionality to existing JTables -- or
* making new search capable table lucene.
*
* <p>This decorator works by holding a reference to a decorated ot inner
* TableModel. All data is stored within that table model, not this
* table model. Rather, this table model simply manages links to
* data in the inner table model according to the search. All methods on
* TableSearcher forward to the inner table model with subtle filtering
* or alteration according to the search criteria.
*
* <p>Using the table model:
*
* Pass the TableModel you want to decorate in at the constructor. When
* the TableModel initializes, it displays all search results. Call
* the search method with any valid Lucene search String and the data
* will be filtered by the search string. Users can always clear the search
* at any time by searching with an empty string. Additionally, you can
* add a button calling the clearSearch() method.
*
*/
public class TableSearcher extends AbstractTableModel {
/**
* The inner table model we are decorating
*/
protected TableModel tableModel;
/**
* This listener is used to register this class as a listener to
* the decorated table model for update events
*/
private TableModelListener tableModelListener;
/**
* these keeps reference to the decorated table model for data
* only rows that match the search criteria are linked
*/
private ArrayList<Integer> rowToModelIndex = new ArrayList<Integer>();
//Lucene stuff.
/**
* In memory lucene index
*/
private RAMDirectory directory;
/**
* Cached lucene analyzer
*/
private Analyzer analyzer;
/**
* Links between this table model and the decorated table model
* are maintained through links based on row number. This is a
* key constant to denote "row number" for indexing
*/
private static final String ROW_NUMBER = "ROW_NUMBER";
/**
* Cache the current search String. Also used internally to
* key whether there is an active search running or not. i.e. if
* searchString is null, there is no active search.
*/
private String searchString = null;
/**
* @param tableModel The table model to decorate
*/
public TableSearcher(TableModel tableModel) {
analyzer = new WhitespaceAnalyzer(Version.LUCENE_CURRENT);
tableModelListener = new TableModelHandler();
setTableModel(tableModel);
tableModel.addTableModelListener(tableModelListener);
clearSearchingState();
}
/**
*
* @return The inner table model this table model is decorating
*/
public TableModel getTableModel() {
return tableModel;
}
/**
* Set the table model used by this table model
* @param tableModel The new table model to decorate
*/
public void setTableModel(TableModel tableModel) {
//remove listeners if there...
if (this.tableModel != null) {
this.tableModel.removeTableModelListener(tableModelListener);
}
this.tableModel = tableModel;
if (this.tableModel != null) {
this.tableModel.addTableModelListener(tableModelListener);
}
//recalculate the links between this table model and
//the inner table model since the decorated model just changed
reindex();
// let all listeners know the table has changed
fireTableStructureChanged();
}
/**
* Reset the search results and links to the decorated (inner) table
* model from this table model.
*/
private void reindex() {
try {
// recreate the RAMDirectory
directory = new RAMDirectory();
IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(
Version.LUCENE_CURRENT, analyzer));
// iterate through all rows
for (int row=0; row < tableModel.getRowCount(); row++){
//for each row make a new document
Document document = new Document();
//add the row number of this row in the decorated table model
//this will allow us to retrieve the results later
//and map this table model's row to a row in the decorated
//table model
document.add(new Field(ROW_NUMBER, "" + row, Field.Store.YES, Field.Index.ANALYZED));
//iterate through all columns
//index the value keyed by the column name
//NOTE: there could be a problem with using column names with spaces
for (int column=0; column < tableModel.getColumnCount(); column++){
String columnName = tableModel.getColumnName(column);
String columnValue = String.valueOf(tableModel.getValueAt(row, column)).toLowerCase();
document.add(new Field(columnName, columnValue, Field.Store.YES, Field.Index.ANALYZED));
}
writer.addDocument(document);
}
writer.optimize();
writer.close();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* @return The current lucene analyzer
*/
public Analyzer getAnalyzer() {
return analyzer;
}
/**
* @param analyzer The new analyzer to use
*/
public void setAnalyzer(Analyzer analyzer) {
this.analyzer = analyzer;
//reindex from the model with the new analyzer
reindex();
//rerun the search if there is an active search
if (isSearching()){
search(searchString);
}
}
/**
* Run a new search.
*
* @param searchString Any valid lucene search string
*/
public void search(String searchString){
//if search string is null or empty, clear the search == search all
if (searchString == null || searchString.equals("")){
clearSearchingState();
fireTableDataChanged();
return;
}
try {
//cache search String
this.searchString = searchString;
//make a new index searcher with the in memory (RAM) index.
IndexSearcher is = new IndexSearcher(directory, true);
//make an array of fields - one for each column
String[] fields = new String[tableModel.getColumnCount()];
for (int t=0; t<tableModel.getColumnCount(); t++){
fields[t]=tableModel.getColumnName(t);
}
//build a query based on the fields, searchString and cached analyzer
//NOTE: This is an area for improvement since the MultiFieldQueryParser
// has some weirdness.
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, fields, analyzer);
Query query = parser.parse(searchString);
//reset this table model with the new results
resetSearchResults(is, query);
} catch (Exception e){
e.printStackTrace();
}
//notify all listeners that the table has been changed
fireTableStructureChanged();
}
/**
*
* @param hits The new result set to set this table to.
*/
private void resetSearchResults(IndexSearcher searcher, Query query) {
try {
//clear our index mapping this table model rows to
//the decorated inner table model
rowToModelIndex.clear();
CountingCollector countingCollector = new CountingCollector();
searcher.search(query, countingCollector);
ScoreDoc[] hits = searcher.search(query, countingCollector.numHits).scoreDocs;
//iterate through the hits
//get the row number stored at the index
//that number is the row number of the decorated
//table model row that we are mapping to
for (int t=0; t<hits.length; t++){
Document document = searcher.doc(hits[t].doc);
Fieldable field = document.getField(ROW_NUMBER);
rowToModelIndex.add(Integer.valueOf(field.stringValue()));
}
} catch (Exception e){
e.printStackTrace();
}
}
private int getModelRow(int row){
return rowToModelIndex.get(row);
}
/**
* Clear the currently active search
* Resets the complete dataset of the decorated
* table model.
*/
private void clearSearchingState(){
searchString = null;
rowToModelIndex.clear();
for (int t=0; t<tableModel.getRowCount(); t++){
rowToModelIndex.add(t);
}
}
// TableModel interface methods
public int getRowCount() {
return (tableModel == null) ? 0 : rowToModelIndex.size();
}
public int getColumnCount() {
return (tableModel == null) ? 0 : tableModel.getColumnCount();
}
@Override
public String getColumnName(int column) {
return tableModel.getColumnName(column);
}
@Override
public Class<?> getColumnClass(int column) {
return tableModel.getColumnClass(column);
}
@Override
public boolean isCellEditable(int row, int column) {
return tableModel.isCellEditable(getModelRow(row), column);
}
public Object getValueAt(int row, int column) {
return tableModel.getValueAt(getModelRow(row), column);
}
@Override
public void setValueAt(Object aValue, int row, int column) {
tableModel.setValueAt(aValue, getModelRow(row), column);
}
private boolean isSearching() {
return searchString != null;
}
private class TableModelHandler implements TableModelListener {
public void tableChanged(TableModelEvent e) {
// If we're not searching, just pass the event along.
if (!isSearching()) {
clearSearchingState();
reindex();
fireTableChanged(e);
return;
}
// Something has happened to the data that may have invalidated the search.
reindex();
search(searchString);
fireTableDataChanged();
return;
}
}
}

View File

@ -1,22 +0,0 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<body>
Decorators for JTable TableModel and JList ListModel encapsulating Lucene indexing and searching functionality.
</body>
</html>

View File

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

View File

@ -1,55 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.AbstractListModel;
public class BaseListModel extends AbstractListModel {
private List<Object> data = new ArrayList<Object>();
public BaseListModel(Iterator<?> iterator) {
while (iterator.hasNext()) {
data.add(iterator.next());
}
}
public int getSize() {
return data.size();
}
public Object getElementAt(int index) {
return data.get(index);
}
public void addRow(Object toAdd) {
data.add(toAdd);
fireContentsChanged(this, 0, getSize());
}
public void removeRow(Object toRemove) {
data.remove(toRemove);
fireContentsChanged(this, 0, getSize());
}
}

View File

@ -1,104 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public class BaseTableModel extends AbstractTableModel {
private List<String> columnNames = new ArrayList<String>();
private List<Object> rows = new ArrayList<Object>();
public BaseTableModel(Iterator<?> data) {
columnNames.add("Name");
columnNames.add("Type");
columnNames.add("Phone");
columnNames.add("Street");
columnNames.add("City");
columnNames.add("State");
columnNames.add("Zip");
while (data.hasNext()) {
Object nextRow = data.next();
rows.add(nextRow);
}
}
public int getColumnCount() {
return columnNames.size();
}
public int getRowCount() {
return rows.size();
}
public void addRow(RestaurantInfo info){
rows.add(info);
fireTableDataChanged();
}
public void removeRow(RestaurantInfo info){
rows.remove(info);
fireTableDataChanged();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
public Object getValueAt(int rowIndex, int columnIndex) {
RestaurantInfo restaurantInfo = (RestaurantInfo) rows.get(rowIndex);
if (columnIndex == 0){ // name
return restaurantInfo.getName();
} else if (columnIndex == 1){ // category
return restaurantInfo.getType();
} else if (columnIndex == 2){ // phone
return restaurantInfo.getPhone();
} else if (columnIndex == 3){ // street
return restaurantInfo.getStreet();
} else if (columnIndex == 4){ // city
return restaurantInfo.getCity();
} else if (columnIndex == 5){ // state
return restaurantInfo.getState();
} else if (columnIndex == 6){ // zip
return restaurantInfo.getZip();
} else {
return "";
}
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
//no op
}
@Override
public String getColumnName(int columnIndex) {
return columnNames.get(columnIndex).toString();
}
}

View File

@ -1,202 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class DataStore {
private static final String ITALIAN_CATEGORY = "Italian";
private static final String CUBAN_CATEGORY = "Cuban";
private static final String STEAK_CATEGORY = "Steak";
private static int id = 0;
static Collection<RestaurantInfo> restaurants = new ArrayList<RestaurantInfo>();
static RestaurantInfo pinos = new RestaurantInfo();
static RestaurantInfo canolis = new RestaurantInfo();
static RestaurantInfo picadillo = new RestaurantInfo();
static RestaurantInfo versailles = new RestaurantInfo();
static RestaurantInfo laCaretta = new RestaurantInfo();
static RestaurantInfo laCaretta2 = new RestaurantInfo();
static RestaurantInfo laCaretta3 = new RestaurantInfo();
static RestaurantInfo ranchaLuna = new RestaurantInfo();
static RestaurantInfo leMerais = new RestaurantInfo();
static RestaurantInfo chris = new RestaurantInfo();
static RestaurantInfo outback = new RestaurantInfo();
static RestaurantInfo outback2 = new RestaurantInfo();
static RestaurantInfo outback3 = new RestaurantInfo();
static RestaurantInfo outback4 = new RestaurantInfo();
public static Iterator<RestaurantInfo> getRestaurants(){
return restaurants.iterator();
}
static {
pinos.setId(getNextId());
pinos.setType(ITALIAN_CATEGORY);
pinos.setName("Pino's");
pinos.setPhone("(305) 111-2222");
pinos.setStreet("12115 105th Street ");
pinos.setCity("Miami");
pinos.setState("FL");
pinos.setZip("33176");
restaurants.add(pinos);
canolis.setId(getNextId());
canolis.setType(ITALIAN_CATEGORY);
canolis.setName("Canoli's");
canolis.setPhone("(305) 234-5543");
canolis.setStreet("12123 85th Street ");
canolis.setCity("Miami");
canolis.setState("FL");
canolis.setZip("33176");
restaurants.add(canolis);
picadillo.setId(getNextId());
picadillo.setType(CUBAN_CATEGORY);
picadillo.setName("Picadillo");
picadillo.setPhone("(305) 746-7865");
picadillo.setStreet("109 12th Street ");
picadillo.setCity("Miami");
picadillo.setState("FL");
picadillo.setZip("33176");
restaurants.add(picadillo);
versailles.setId(getNextId());
versailles.setType(CUBAN_CATEGORY);
versailles.setName("Cafe Versailles");
versailles.setPhone("(305) 201-5438");
versailles.setStreet("312 8th Street ");
versailles.setCity("Miami");
versailles.setState("FL");
versailles.setZip("33176");
restaurants.add(versailles);
laCaretta.setId(getNextId());
laCaretta.setType(CUBAN_CATEGORY);
laCaretta.setName("La Carretta");
laCaretta.setPhone("(305) 342-9876");
laCaretta.setStreet("348 8th Street ");
laCaretta.setCity("Miami");
laCaretta.setState("FL");
laCaretta.setZip("33176");
restaurants.add(laCaretta);
laCaretta2.setId(getNextId());
laCaretta2.setType(CUBAN_CATEGORY);
laCaretta2.setName("La Carretta");
laCaretta2.setPhone("(305) 556-9876");
laCaretta2.setStreet("31224 23rd Street ");
laCaretta2.setCity("Miami");
laCaretta2.setState("FL");
laCaretta2.setZip("33176");
restaurants.add(laCaretta2);
laCaretta3.setId(getNextId());
laCaretta3.setType(CUBAN_CATEGORY);
laCaretta3.setName("La Carretta");
laCaretta3.setPhone("(305) 682-9876");
laCaretta3.setStreet("23543 107th Street ");
laCaretta3.setCity("Miami");
laCaretta3.setState("FL");
laCaretta3.setZip("33176");
restaurants.add(laCaretta3);
ranchaLuna.setId(getNextId());
ranchaLuna.setType(CUBAN_CATEGORY);
ranchaLuna.setName("Rancha Luna");
ranchaLuna.setPhone("(305) 777-4384");
ranchaLuna.setStreet("110 23rd Street ");
ranchaLuna.setCity("Miami");
ranchaLuna.setState("FL");
ranchaLuna.setZip("33176");
restaurants.add(ranchaLuna);
leMerais.setId(getNextId());
leMerais.setType(STEAK_CATEGORY);
leMerais.setName("Le Merais");
leMerais.setPhone("(212) 654-9187");
leMerais.setStreet("11 West 46th Street");
leMerais.setCity("New York");
leMerais.setState("NY");
leMerais.setZip("10018");
restaurants.add(leMerais);
chris.setId(getNextId());
chris.setType(STEAK_CATEGORY);
chris.setName("Ruth's Chris Seakhouse");
chris.setPhone("(305) 354-8885");
chris.setStreet("12365 203rd Street ");
chris.setCity("Miami");
chris.setState("FL");
chris.setZip("33176");
restaurants.add(chris);
outback.setId(getNextId());
outback.setType(STEAK_CATEGORY);
outback.setName("Outback");
outback.setPhone("(305) 244-7623");
outback.setStreet("348 136th Street ");
outback.setCity("Miami");
outback.setState("FL");
outback.setZip("33176");
restaurants.add(outback);
outback2.setId(getNextId());
outback2.setType(STEAK_CATEGORY);
outback2.setName("Outback");
outback2.setPhone("(305) 533-6522");
outback2.setStreet("21 207th Street ");
outback2.setCity("Miami");
outback2.setState("FL");
outback2.setZip("33176");
restaurants.add(outback2);
outback3.setId(getNextId());
outback3.setType(STEAK_CATEGORY);
outback3.setName("Outback");
outback3.setPhone("(305) 244-7623");
outback3.setStreet("10117 107th Street ");
outback3.setCity("Miami");
outback3.setState("FL");
outback3.setZip("33176");
restaurants.add(outback3);
outback4.setId(getNextId());
outback4.setType(STEAK_CATEGORY);
outback4.setName("Outback");
outback4.setPhone("(954) 221-3312");
outback4.setStreet("10 11th Street ");
outback4.setCity("Aventura");
outback4.setState("FL");
outback4.setZip("32154");
restaurants.add(outback4);
}
private static int getNextId(){
id++;
return id;
}
}

View File

@ -1,88 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class ListSearcherSimulator {
public ListSearcherSimulator() {
JFrame frame = new JFrame();
frame.setBounds(200,200, 400,250);
JList list = new JList();
JScrollPane scrollPane = new JScrollPane(list);
final BaseListModel listModel = new BaseListModel(DataStore.getRestaurants());
final ListSearcher listSearcher = new ListSearcher(listModel);
list.setModel(listSearcher);
final JTextField searchField = new JTextField();
searchField.getDocument().addDocumentListener(
new DocumentListener(){
public void changedUpdate(DocumentEvent e) {
listSearcher.search(searchField.getText().trim().toLowerCase());
}
public void insertUpdate(DocumentEvent e) {
listSearcher.search(searchField.getText().trim().toLowerCase());
}
public void removeUpdate(DocumentEvent e) {
listSearcher.search(searchField.getText().trim().toLowerCase());
}
}
);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
JPanel searchPanel = new JPanel();
searchPanel.setLayout(new BorderLayout(10,10));
searchPanel.add(searchField, BorderLayout.CENTER);
searchPanel.add(new JLabel("Search: "), BorderLayout.WEST);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(searchPanel, BorderLayout.CENTER);
topPanel.add(new JPanel(), BorderLayout.EAST);
topPanel.add(new JPanel(), BorderLayout.WEST);
topPanel.add(new JPanel(), BorderLayout.NORTH);
topPanel.add(new JPanel(), BorderLayout.SOUTH);
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
frame.setTitle("Lucene powered table searching");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
public static void main(String[] args) {
new ListSearcherSimulator();
}
}

View File

@ -1,101 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class RestaurantInfo {
private int id;
private String name;
private String type;
private String phone;
private String street;
private String city;
private String state;
private String zip;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return getName() + " - " + getPhone();
}
}

View File

@ -1,81 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TableSearcherSimulator {
public TableSearcherSimulator() {
JFrame frame = new JFrame();
frame.setBounds(200,200, 400,250);
JTable table = new JTable();
final BaseTableModel tableModel = new BaseTableModel(DataStore.getRestaurants());
final TableSearcher searchTableModel = new TableSearcher(tableModel);
table.setModel(searchTableModel);
JScrollPane scrollPane = new JScrollPane(table);
final JTextField searchField = new JTextField();
JButton searchButton = new JButton("Go");
ActionListener searchListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
searchTableModel.search(searchField.getText().trim().toLowerCase());
searchField.requestFocus();
}
};
searchButton.addActionListener(searchListener);
searchField.addActionListener(searchListener);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
JPanel searchPanel = new JPanel();
searchPanel.setLayout(new BorderLayout(10,10));
searchPanel.add(searchField, BorderLayout.CENTER);
searchPanel.add(searchButton, BorderLayout.EAST);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(searchPanel, BorderLayout.CENTER);
topPanel.add(new JPanel(), BorderLayout.EAST);
topPanel.add(new JPanel(), BorderLayout.WEST);
topPanel.add(new JPanel(), BorderLayout.NORTH);
topPanel.add(new JPanel(), BorderLayout.SOUTH);
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
frame.setTitle("Lucene powered table searching");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
public static void main(String[] args) {
new TableSearcherSimulator();
}
}

View File

@ -1,53 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.List;
import javax.swing.ListModel;
import org.apache.lucene.util.LuceneTestCase;
/**
**/
public class TestBasicList extends LuceneTestCase {
private ListModel baseListModel;
private ListSearcher listSearcher;
private List<RestaurantInfo> list;
@Override
public void setUp() throws Exception {
super.setUp();
list = new ArrayList<RestaurantInfo>();
list.add(DataStore.canolis);
list.add(DataStore.chris);
baseListModel = new BaseListModel(list.iterator());
listSearcher = new ListSearcher(baseListModel);
}
public void testRows(){
assertEquals(list.size(), listSearcher.getSize());
}
public void testValueAt(){
assertEquals(baseListModel.getElementAt(0), listSearcher.getElementAt(0));
assertNotSame(baseListModel.getElementAt(1), listSearcher.getElementAt(0));
}
}

View File

@ -1,60 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.TableModel;
import org.apache.lucene.util.LuceneTestCase;
public class TestBasicTable extends LuceneTestCase {
private TableModel baseTableModel;
private TableSearcher tableSearcher;
private List<RestaurantInfo> list;
@Override
public void setUp() throws Exception {
super.setUp();
list = new ArrayList<RestaurantInfo>();
list.add(DataStore.canolis);
list.add(DataStore.chris);
baseTableModel = new BaseTableModel(list.iterator());
tableSearcher = new TableSearcher(baseTableModel);
}
public void testColumns(){
assertEquals(baseTableModel.getColumnCount(), tableSearcher.getColumnCount());
assertEquals(baseTableModel.getColumnName(0), tableSearcher.getColumnName(0));
assertNotSame(baseTableModel.getColumnName(0), tableSearcher.getColumnName(1));
assertEquals(baseTableModel.getColumnClass(0), tableSearcher.getColumnClass(0));
}
public void testRows(){
assertEquals(list.size(), tableSearcher.getRowCount());
}
public void testValueAt(){
assertEquals(baseTableModel.getValueAt(0,0), tableSearcher.getValueAt(0,0));
assertEquals(baseTableModel.getValueAt(0,3), tableSearcher.getValueAt(0,3));
}
}

View File

@ -1,47 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javax.swing.ListModel;
import org.apache.lucene.util.LuceneTestCase;
public class TestSearchingList extends LuceneTestCase {
private ListModel baseListModel;
private ListSearcher listSearcher;
@Override
public void setUp() throws Exception {
super.setUp();
baseListModel = new BaseListModel(DataStore.getRestaurants());
listSearcher = new ListSearcher(baseListModel);
}
public void testSearch(){
//make sure data is there
assertEquals(baseListModel.getSize(), listSearcher.getSize());
//search for pino's
listSearcher.search("pino's");
assertEquals(1, listSearcher.getSize());
//clear search and check that
listSearcher.search(null);
assertEquals(baseListModel.getSize(), listSearcher.getSize());
}
}

View File

@ -1,45 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javax.swing.table.TableModel;
import org.apache.lucene.util.LuceneTestCase;
public class TestSearchingTable extends LuceneTestCase {
private TableModel baseTableModel;
private TableSearcher tableSearcher;
@Override
public void setUp() throws Exception {
super.setUp();
baseTableModel = new BaseTableModel(DataStore.getRestaurants());
tableSearcher = new TableSearcher(baseTableModel);
}
public void testSearch(){
//make sure data is there
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
//search for pino's
tableSearcher.search("pino's");
assertEquals(1, tableSearcher.getRowCount());
//clear search and check that
tableSearcher.search(null);
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
}
}

View File

@ -1,79 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.util.LuceneTestCase;
public class TestUpdatingList extends LuceneTestCase {
private BaseListModel baseListModel;
private ListSearcher listSearcher;
RestaurantInfo infoToAdd1, infoToAdd2;
@Override
public void setUp() throws Exception {
super.setUp();
baseListModel = new BaseListModel(DataStore.getRestaurants());
listSearcher = new ListSearcher(baseListModel);
infoToAdd1 = new RestaurantInfo();
infoToAdd1.setName("Pino's");
infoToAdd2 = new RestaurantInfo();
infoToAdd2.setName("Pino's");
infoToAdd2.setType("Italian");
}
public void testAddWithoutSearch(){
assertEquals(baseListModel.getSize(), listSearcher.getSize());
int count = listSearcher.getSize();
baseListModel.addRow(infoToAdd1);
count++;
assertEquals(count, listSearcher.getSize());
}
public void testRemoveWithoutSearch(){
assertEquals(baseListModel.getSize(), listSearcher.getSize());
baseListModel.addRow(infoToAdd1);
int count = listSearcher.getSize();
baseListModel.removeRow(infoToAdd1);
count--;
assertEquals(count, listSearcher.getSize());
}
public void testAddWithSearch(){
assertEquals(baseListModel.getSize(), listSearcher.getSize());
listSearcher.search("pino's");
int count = listSearcher.getSize();
baseListModel.addRow(infoToAdd2);
count++;
assertEquals(count, listSearcher.getSize());
}
public void testRemoveWithSearch(){
assertEquals(baseListModel.getSize(), listSearcher.getSize());
baseListModel.addRow(infoToAdd1);
listSearcher.search("pino's");
int count = listSearcher.getSize();
baseListModel.removeRow(infoToAdd1);
count--;
assertEquals(count, listSearcher.getSize());
}
}

View File

@ -1,79 +0,0 @@
package org.apache.lucene.swing.models;
/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.util.LuceneTestCase;
public class TestUpdatingTable extends LuceneTestCase {
private BaseTableModel baseTableModel;
private TableSearcher tableSearcher;
RestaurantInfo infoToAdd1, infoToAdd2;
@Override
public void setUp() throws Exception {
super.setUp();
baseTableModel = new BaseTableModel(DataStore.getRestaurants());
tableSearcher = new TableSearcher(baseTableModel);
infoToAdd1 = new RestaurantInfo();
infoToAdd1.setName("Pino's");
infoToAdd1.setType("Italian");
infoToAdd2 = new RestaurantInfo();
infoToAdd2.setName("Pino's");
infoToAdd2.setType("Italian");
}
public void testAddWithoutSearch(){
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
int count = tableSearcher.getRowCount();
baseTableModel.addRow(infoToAdd1);
count++;
assertEquals(count, tableSearcher.getRowCount());
}
public void testRemoveWithoutSearch(){
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
int count = tableSearcher.getRowCount();
baseTableModel.addRow(infoToAdd1);
baseTableModel.removeRow(infoToAdd1);
assertEquals(count, tableSearcher.getRowCount());
}
public void testAddWithSearch(){
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
tableSearcher.search("pino's");
int count = tableSearcher.getRowCount();
baseTableModel.addRow(infoToAdd2);
count++;
assertEquals(count, tableSearcher.getRowCount());
}
public void testRemoveWithSearch(){
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
baseTableModel.addRow(infoToAdd1);
tableSearcher.search("pino's");
int count = tableSearcher.getRowCount();
baseTableModel.removeRow(infoToAdd1);
count--;
assertEquals(count, tableSearcher.getRowCount());
}
}

View File

@ -50,11 +50,6 @@
<a href="http://svn.apache.org/repos/asf/lucene/dev/trunk/lucene/contrib/">http://svn.apache.org/repos/asf/lucene/dev/trunk/lucene/contrib/</a>.
</p>
<section id="ant"><title>ant</title>
<p>Ant task to create Lucene indexes.</p>
<p>See <a href="../api/contrib-ant/index.html">ant javadoc</a></p>
</section>
<section id="benchmark"><title>benchmark</title>
<p>The benchmark contribution contains tools for benchmarking Lucene using standard, freely available corpora.</p>
<p>See <a href="../api/contrib-benchmark/index.html">benchmark javadoc</a></p>
@ -66,11 +61,6 @@
<p>See <a href="../api/contrib-demo/index.html">demo javadoc</a></p>
</section>
<section id="db"><title>db</title>
<p>Provides integration with Berkley DB.</p>
<p>See <a href="../api/contrib-db/index.html">db javadoc</a></p>
</section>
<section id="highlighter"><title>highlighter</title>
<p>A set of classes for highlighting matching terms in search results.</p>
<p>See <a href="../api/contrib-highlighter/index.html">highlighter javadoc</a></p>
@ -81,11 +71,6 @@
<p>See <a href="../api/contrib-instantiated/index.html">instantiated javadoc</a></p>
</section>
<section id="lucli"><title>lucli</title>
<p>An application that allows Lucene index manipulation from the command-line.</p>
<p>See <a href="../api/contrib-lucli/index.html">lucli javadoc</a></p>
</section>
<section id="memory"><title>memory</title>
<p>High-performance single-document main memory index.</p>
<p>See <a href="../api/contrib-memory/index.html">memory javadoc</a></p>
@ -121,11 +106,6 @@
<p>See <a href="../api/contrib-spellchecker/index.html">spellchecker javadoc</a></p>
</section>
<section id="swing"><title>swing</title>
<p>Swing components designed to integrate with Lucene.</p>
<p>See <a href="../api/contrib-swing/index.html">swing javadoc</a></p>
</section>
<section id="wordnet"><title>wordnet</title>
<p>Tools to help utilize wordnet synonyms with Lucene</p>
<p>See <a href="../api/contrib-wordnet/index.html">wordnet javadoc</a></p>

View File

@ -52,14 +52,10 @@ See http://forrest.apache.org/docs/linking.html for more info
<javadoc-core label="Core" href="ext:javadocs-core"/>
<javadoc-test-framework label="Test Framework" href="ext:javadocs-test-framework"/>
<javadoc-contrib label="Contrib">
<javadoc-contrib-ant label="Ant" href="ext:javadocs-contrib-ant"/>
<javadoc-contrib-bdb label="Bdb" href="ext:javadocs-contrib-bdb"/>
<javadoc-contrib-bdb-je label="Bdb-je" href="ext:javadocs-contrib-bdb-je"/>
<javadoc-contrib-benchmark label="Benchmark" href="ext:javadocs-contrib-benchmark"/>
<javadoc-contrib-demo label="Demo" href="ext:javadocs-contrib-demo"/>
<javadoc-contrib-highlighter label="Highlighter" href="ext:javadocs-contrib-highlighter"/>
<javadoc-contrib-instantiated label="Instantiated" href="ext:javadocs-contrib-instantiated"/>
<javadoc-contrib-lucli label="Lucli" href="ext:javadocs-contrib-lucli"/>
<javadoc-contrib-memory label="Memory" href="ext:javadocs-contrib-memory"/>
<javadoc-contrib-misc label="Miscellaneous" href="ext:javadocs-contrib-misc"/>
<javadoc-contrib-queries label="Queries" href="ext:javadocs-contrib-queries"/>
@ -70,7 +66,6 @@ See http://forrest.apache.org/docs/linking.html for more info
<javadoc-contrib-remote label="Remote" href="ext:javadocs-contrib-remote"/>
<javadoc-contrib-spatial label="Spatial" href="ext:javadocs-contrib-spatial"/>
<javadoc-contrib-spellchecker label="Spellchecker" href="ext:javadocs-contrib-spellchecker"/>
<javadoc-contrib-swing label="Swing" href="ext:javadocs-contrib-swing"/>
<javadoc-contrib-wordnet label="Wordnet" href="ext:javadocs-contrib-wordnet"/>
<javadoc-contrib-xml-query-parser label="XML Query Parser" href="ext:javadocs-contrib-xml-query-parser"/>
</javadoc-contrib>
@ -100,14 +95,10 @@ See http://forrest.apache.org/docs/linking.html for more info
<javadocs-all href="api/all/index.html"/>
<javadocs-core href="api/core/index.html"/>
<javadocs-test-framework href="api/test-framework/index.html"/>
<javadocs-contrib-ant href="api/contrib-ant/index.html"/>
<javadocs-contrib-bdb href="api/contrib-bdb/index.html"/>
<javadocs-contrib-bdb-je href="api/contrib-bdb-je/index.html"/>
<javadocs-contrib-benchmark href="api/contrib-benchmark/index.html"/>
<javadocs-contrib-demo href="api/contrib-demo/index.html"/>
<javadocs-contrib-highlighter href="api/contrib-highlighter/index.html"/>
<javadocs-contrib-instantiated href="api/contrib-instantiated/index.html"/>
<javadocs-contrib-lucli href="api/contrib-lucli/index.html"/>
<javadocs-contrib-memory href="api/contrib-memory/index.html"/>
<javadocs-contrib-misc href="api/contrib-misc/index.html"/>
<javadocs-contrib-queries href="api/contrib-queries/index.html"/>
@ -115,7 +106,6 @@ See http://forrest.apache.org/docs/linking.html for more info
<javadocs-contrib-remote href="api/contrib-remote/index.html"/>
<javadocs-contrib-spatial href="api/contrib-spatial/index.html"/>
<javadocs-contrib-spellchecker href="api/contrib-spellchecker/index.html"/>
<javadocs-contrib-swing href="api/contrib-swing/index.html"/>
<javadocs-contrib-wordnet href="api/contrib-wordnet/index.html"/>
<javadocs-contrib-xml-query-parser href="api/contrib-xml-query-parser/index.html"/>