/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.server.assertion.index;
import com.esri.gpt.catalog.lucene.LuceneIndexAdapter;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.server.assertion.components.AsnContext;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.NativeFSLockFactory;
/**
* Base class for an adapter that handles read/write operations against a
* Lucene index of assertions.
*/
public class AsnBaseIndexAdapter {
/** class variables ========================================================= */
/** The Logger. */
private static Logger LOGGER = Logger.getLogger(AsnBaseIndexAdapter.class.getName());
/** Hold NativeFSLockFactory objects statically within the JVM */
private static final Map<String,NativeFSLockFactory> NATIVEFSLOCKFACTORIES =
new HashMap<String,NativeFSLockFactory>();
/** instance variables ====================================================== */
private AsnIndexReference indexReference;
/** constructors ============================================================ */
/** Default constructor */
public AsnBaseIndexAdapter() {}
/** properties ============================================================== */
/**
* Gets the configuration reference for the index.
* @return the index configuration reference
*/
public AsnIndexReference getIndexReference() {
return this.indexReference;
}
/**
* Sets the configuration reference for the index.
* @param indexReference index configuration reference
*/
public void setIndexReference(AsnIndexReference indexReference) {
this.indexReference = indexReference;
}
/** methods ================================================================= */
/**
* Closes an index reader.
* @param reader the reader to close
*/
public void closeReader(IndexReader reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE,"IndexReader failed to close.",e);
}
}
}
/**
* Closes an index searcher.
* @param searcher the searcher to close
*/
public void closeSearcher(IndexSearcher searcher) {
if (searcher != null) {
try {
searcher.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE,"IndexSearcher failed to close.",e);
}
}
}
/**
* Closes an index writer.
* @param writer the writer to close
*/
public void closeWriter(IndexWriter writer) {
if (writer != null) {
try {
writer.close();
} catch (CorruptIndexException e) {
LOGGER.log(Level.SEVERE,"IndexWriter failed to close.",e);
} catch (IOException e) {
LOGGER.log(Level.SEVERE,"IndexWriter failed to close.",e);
}
}
}
/**
* Configures the adapter from an index configuration reference.
* @param indexReference index configuration reference
*/
public void configure(AsnIndexReference indexReference) {
this.setIndexReference(indexReference);
}
/**
* Gets the Lucene Directory assoctated with the index.
* @return the directory
* @throws IOException if an I/O exception occurs
*/
protected Directory getDirectory() throws IOException {
File fDir = new File(this.getIndexReference().getIndexLocation());
NativeFSLockFactory nativeLockFactory = this.getNativeLockFactory();
if (nativeLockFactory != null) {
return FSDirectory.open(fDir,nativeLockFactory);
} else {
return FSDirectory.open(fDir);
}
}
/**
* Gets the native lock factory if it has been configured for use.
* @return the native lock factory (null if not configured for use)
* @throws IOException if an I/O exception occurs
*/
protected synchronized NativeFSLockFactory getNativeLockFactory() throws IOException {
NativeFSLockFactory factory = null;
if (this.getIndexReference().getUseNativeFSLockFactory()) {
File dir = new File(this.getIndexReference().getIndexLocation());
String path = dir.getCanonicalPath();
synchronized (NATIVEFSLOCKFACTORIES) {
factory = NATIVEFSLOCKFACTORIES.get(path);
if (factory == null) {
factory = new NativeFSLockFactory(dir);
NATIVEFSLOCKFACTORIES.put(path,factory);
}
}
}
return factory;
}
/**
* Makes an index reader.
* <br/>The reader must be closed following use.
* @return the reader
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if an I/O exception occurs
*/
public IndexReader makeIndexReader() throws CorruptIndexException, IOException {
IndexReader reader = IndexReader.open(this.getDirectory(),true);
return reader;
}
/**
* Makes an index writer.
* <br/>The writer must be closed following use.
* @param analyzer the analyzer
* @return the writer
* @throws CorruptIndexException if the index is corrupt
* @throws LockObtainFailedException if a write lock cannot be obtained
* @throws IOException if an I/O exception occurs
*/
public IndexWriter makeIndexWriter(Analyzer analyzer)
throws CorruptIndexException, LockObtainFailedException, IOException {
IndexWriter.MaxFieldLength mfl = IndexWriter.MaxFieldLength.UNLIMITED;
return new IndexWriter(this.getDirectory(),analyzer,mfl);
}
/**
* Instantiates a new analyzer.
* @param context the assertion operation context
* @return the analyzer
*/
public Analyzer newAnalyzer(AsnContext context) {
RequestContext rc = null;
try {
LuceneIndexAdapter adapter = null;
if ((context != null) && (context.getRequestContext() != null)) {
adapter = new LuceneIndexAdapter(context.getRequestContext());
} else {
rc = RequestContext.extract(null);
adapter = new LuceneIndexAdapter(rc);
}
return adapter.newAnalyzer();
} finally {
if (rc != null) rc.getConnectionBroker().closeAll();
}
}
/**
* Optimizes the index.
* @throws CorruptIndexException if the index is corrupt
* @throws LockObtainFailedException if a write lock cannot be obtained
* @throws IOException if an I/O exception occurs
*/
public void optimize()
throws CorruptIndexException, LockObtainFailedException, IOException {
IndexWriter writer = null;
try {
writer = this.makeIndexWriter(this.newAnalyzer(null));
writer.optimize();
} finally {
this.closeWriter(writer);
}
}
/**
* Opens and closes a writer.
* <br/>This ensures that a directory folder structure exists.
* @throws CorruptIndexException if the index is corrupt
* @throws LockObtainFailedException if a write lock cannot be obtained
* @throws IOException if an I/O exception occurs
*/
public void touch() throws CorruptIndexException, LockObtainFailedException, IOException {
IndexWriter writer = null;
try {
writer = this.makeIndexWriter(this.newAnalyzer(null));
} finally {
closeWriter(writer);
}
}
}