org.pageseeder.flint.lucene.LuceneLocalIndex Maven / Gradle / Ivy
/*
* Copyright 2015 Allette Systems (Australia)
* http://www.allette.com.au
*
* 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.
*/
package org.pageseeder.flint.lucene;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.pageseeder.flint.IndexException;
import org.pageseeder.flint.IndexIO;
import org.pageseeder.flint.content.DeleteRule;
import org.pageseeder.flint.indexing.FlintField;
import org.pageseeder.flint.local.LocalIndex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* A basic implementation of a local index.
*
* @author Christophe Lauret
* @version 27 February 2013
*/
public final class LuceneLocalIndex extends LocalIndex {
/**
* A logger for this class and to provide for Flint.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(LuceneLocalIndex.class);
private final Directory _directory;
private final Analyzer _analyzer;
private final IndexIO _io;
private final File _contentRoot;
/**
* Create a new local index.
*
* @param indexLocation The location of the local index.
* @param analyzer The analyzer of the local index.
* @param contentLocation The location of the content to index
*
* @throws NullPointerException if the location is null
.
* @throws IndexException if creating the index failed (for example: there's already in index running pointing to that location)
*/
public LuceneLocalIndex(File indexLocation, Analyzer analyzer, File contentLocation) throws IndexException {
this(indexLocation, "lucene", analyzer, contentLocation);
}
/**
* Create a new local index.
*
*
* @param indexLocation The location of the local index.
* @param catalog The name of the catalog
* @param analyzer The analyzer of the local index.
* @param contentLocation The location of the content to index
*
* @throws NullPointerException if the location is null
.
* @throws IndexException if creating the index failed (for example: there's already in index running pointing to that location)
*/
public LuceneLocalIndex(File indexLocation, String catalog, Analyzer analyzer, File contentLocation)
throws IndexException {
super(indexLocation.getName(), catalog);
this._directory = ensureFolderExists(indexLocation);
this._analyzer = analyzer;
this._io = new LuceneIndexIO(this._directory, this._analyzer);
this._contentRoot = contentLocation;
}
public Analyzer getAnalyzer() {
return this._analyzer;
}
/**
* Return the Index Directory object.
*
* @return The Index Directory object
*/
public Directory getIndexDirectory() {
return this._directory;
}
@Override
public IndexIO getIndexIO() {
return this._io;
}
@Override
public DeleteRule getDeleteRule(File file) {
return new LuceneDeleteRule("_src", file.getAbsolutePath());
}
@Override
public File getContentLocation() {
return this._contentRoot;
}
@Override
public Collection getFields(File file) {
Collection fields = new ArrayList<>();
if (file.exists()) {
fields.add(buildField("_src", file.getAbsolutePath()));
fields.add(buildField("_path", fileToPath(file)));
fields.add(buildField("_lastmodified", String.valueOf(file.lastModified())));
fields.add(buildField("_creator", "flint-lucene"));
}
return fields;
}
@Override
public Map getParameters(File file) {
HashMap params = new HashMap<>();
if (file.exists()) {
params.put("_src", file.getAbsolutePath());
params.put("_path", fileToPath(file));
params.put("_lastmodified", String.valueOf(file.lastModified()));
params.put("_filename", file.getName());
}
return params;
}
public String fileToPath(File f) {
try {
String rootPath = this._contentRoot.getCanonicalPath();
String thisPath = f.getCanonicalPath();
if (thisPath.startsWith(rootPath)) {
String p = thisPath.substring(rootPath.length()).replace('\\', '/');
return p.isEmpty() || p.charAt(0) != '/' ? '/' + p : p;
}
} catch (IOException ex) {
LOGGER.error("Failed to compute file relative path", ex);
}
return f.getAbsolutePath();
}
public File pathToFile(String path) {
return new File(this._contentRoot, path);
}
// Utility methods for public usage
// ----------------------------------------------------------------------------------------------
/**
* Indicates whether the folder exists and is a valid Lucene index.
*
* This method uses the Lucene {@link IndexReader} to check whether the folder corresponds to a valid Lucene Index.
*
* @param location the folder where the index is located.
* @return true
if the folder exists and is a Lucene index; false
otherwise
*/
public static boolean exists(File location) {
if (!location.exists() || !location.isDirectory()) return false;
boolean exists = false;
// Get the last modified from the index
try {
Directory directory = FSDirectory.open(location.toPath());
exists = DirectoryReader.indexExists(directory);
directory.close();
} catch (IOException ex) {
LOGGER.error("Unable to check if local index exists", ex);
}
return exists;
}
// private helpers
// ----------------------------------------------------------------------------------------------
/**
* Ensures that the specified folder exists by creating the folder if it does not.
*
*
This method will log any creation problem as a warning.
*
* @param folder The folder to be created.
*/
private static Directory ensureFolderExists(File folder) {
if (!folder.exists()) {
folder.mkdirs();
if (!folder.exists()) {
LOGGER.warn("Unable to create location {}", folder);
}
}
try {
return FSDirectory.open(folder.toPath());
} catch (IOException ex) {
throw new IllegalArgumentException("Unable to return a directory on local index "+folder.getName(), ex);
}
}
private FlintField buildField(String name, String value) {
// use filed builder as it will add the fields to the catalog
return new FlintField(getCatalog()).store(true).tokenize(false).name(name).value(value);
}
}