1 16 package org.apache.cocoon.components.search; 17 import org.apache.avalon.excalibur.pool.Recyclable; 18 import org.apache.avalon.framework.activity.Disposable; 19 import org.apache.avalon.framework.configuration.Configurable; 20 import org.apache.avalon.framework.configuration.Configuration; 21 import org.apache.avalon.framework.configuration.ConfigurationException; 22 import org.apache.avalon.framework.logger.AbstractLogEnabled; 23 import org.apache.avalon.framework.service.ServiceException; 24 import org.apache.avalon.framework.service.ServiceManager; 25 import org.apache.avalon.framework.service.Serviceable; 26 import org.apache.cocoon.ProcessingException; 27 import org.apache.cocoon.util.ClassUtils; 28 import org.apache.lucene.analysis.Analyzer; 29 import org.apache.lucene.index.IndexReader; 30 import org.apache.lucene.queryParser.ParseException; 31 import org.apache.lucene.queryParser.QueryParser; 32 import org.apache.lucene.search.Hits; 33 import org.apache.lucene.search.IndexSearcher; 34 import org.apache.lucene.search.Query; 35 import org.apache.lucene.store.Directory; 36 import org.apache.lucene.store.FSDirectory; 37 38 import java.io.File ; 39 import java.io.IOException ; 40 41 62 public class SimpleLuceneCocoonSearcherImpl extends AbstractLogEnabled 63 implements LuceneCocoonSearcher, Configurable, Serviceable, Disposable, Recyclable 64 { 65 66 74 protected final static String ANALYZER_CLASSNAME_CONFIG = "analyzer-classname"; 75 83 protected final static String ANALYZER_CLASSNAME_DEFAULT = "org.apache.lucene.analysis.standard.StandardAnalyzer"; 84 85 93 protected final static String DEFAULT_SEARCH_FIELD_CONFIG = "default-search-field"; 94 101 protected final static String DEFAULT_SEARCH_FIELD_DEFAULT = "body"; 102 103 111 protected final static String DEFAULT_QUERY_CONFIG = "default-query"; 112 119 protected final static String DEFAULT_QUERY_DEFAULT = null; 120 121 129 protected final static String QUERYPARSER_CLASSNAME_CONFIG = "queryparser-classname"; 130 138 protected final static String QUERYPARSER_CLASSNAME_DEFAULT = "org.apache.lucene.queryParser.QueryParser"; 139 140 148 protected final static String DIRECTORY_CONFIG = "directory"; 149 156 protected final static String DIRECTORY_DEFAULT = null; 157 158 162 protected ServiceManager manager = null; 163 164 private String analyzerClassnameDefault = ANALYZER_CLASSNAME_DEFAULT; 165 private String defaultSearchFieldDefault = DEFAULT_SEARCH_FIELD_DEFAULT; 166 private String defaultQueryDefault = DEFAULT_QUERY_DEFAULT; 167 private String directoryDefault = DIRECTORY_DEFAULT; 169 170 173 private Analyzer analyzer; 174 177 private Directory directory; 178 181 private IndexSearcher indexSearcher; 182 183 187 private IndexReaderCache indexReaderCache; 188 189 194 public void setAnalyzer(Analyzer analyzer) { 195 this.analyzer = analyzer; 196 } 197 198 202 public Analyzer getAnalyzer() { 203 return this.analyzer; 204 } 205 206 211 public void setDirectory(Directory directory) { 212 this.directory = directory; 213 if (indexReaderCache != null) { 214 indexReaderCache.close(); 215 indexReaderCache = null; 216 } 217 } 218 219 220 231 public IndexReader getReader() throws IOException { 232 if (indexReaderCache == null) { 233 indexReaderCache = new IndexReaderCache(); 234 } 235 return indexReaderCache.getIndexReader(directory); 236 } 237 238 239 246 public void configure(Configuration conf) throws ConfigurationException { 247 Configuration child; 248 String value; 249 250 child = conf.getChild(ANALYZER_CLASSNAME_CONFIG, false); 251 if (child != null) { 252 value = child.getValue(ANALYZER_CLASSNAME_DEFAULT); 255 if (value != null) { 256 analyzerClassnameDefault = value; 257 try { 258 analyzer = (Analyzer) ClassUtils.newInstance(analyzerClassnameDefault); 259 } catch (Exception e) { 260 throw new ConfigurationException("Cannot create analyzer of class " + 261 analyzerClassnameDefault, e); 262 } 263 } 264 } 265 266 child = conf.getChild(DEFAULT_SEARCH_FIELD_CONFIG, false); 267 if (child != null) { 268 value = child.getValue(DEFAULT_SEARCH_FIELD_DEFAULT); 269 if (value != null) { 270 defaultSearchFieldDefault = value; 271 } 272 } 273 274 child = conf.getChild(DEFAULT_QUERY_CONFIG, false); 275 if (child != null) { 276 value = child.getValue(DEFAULT_QUERY_DEFAULT); 277 if (value != null) { 278 defaultQueryDefault = value; 279 } 280 } 281 290 child = conf.getChild(DIRECTORY_CONFIG, false); 291 if (child != null) { 292 value = child.getValue(DIRECTORY_DEFAULT); 293 if (value != null) { 294 directoryDefault = value; 295 try { 296 setDirectory(FSDirectory.getDirectory(new File (directoryDefault), false)); 297 } catch (IOException ioe) { 298 throw new ConfigurationException("Cannot set index directory " + directoryDefault, ioe); 299 } 300 } 301 } 302 } 303 304 305 312 public void service(ServiceManager manager) throws ServiceException { 313 this.manager = manager; 314 } 315 316 317 320 public void dispose() { 321 releaseIndexSearcher(); 322 releaseIndexReaderCache(); 323 } 324 325 326 329 public void recycle() { 330 releaseIndexSearcher(); 331 releaseIndexReaderCache(); 332 } 333 334 335 343 public Hits search(String query_string, String default_field) throws ProcessingException { 344 Hits hits = null; 345 346 if (query_string == null) { 347 query_string = defaultQueryDefault; 348 } 349 if (default_field == null) { 350 default_field = defaultSearchFieldDefault; 351 } 352 353 try { 354 Query query = QueryParser.parse(query_string, default_field, analyzer); 355 356 releaseIndexSearcher(); 358 359 IndexSearcher indexSearcher = new IndexSearcher(getReader()); 360 hits = indexSearcher.search(query); 361 } catch (ParseException pe) { 364 throw new ProcessingException("Cannot parse query " + query_string, pe); 365 } catch (IOException ioe) { 366 throw new ProcessingException("Cannot access hits", ioe); 367 } 368 return hits; 369 } 370 371 379 public Hits search(Query query) throws ProcessingException { 380 Hits hits = null; 381 try { 382 releaseIndexSearcher(); 384 385 IndexSearcher indexSearcher = new IndexSearcher(getReader()); 386 hits = indexSearcher.search(query); 387 } catch (IOException ioe) { 390 throw new ProcessingException("Cannot access hits", ioe); 391 } 392 return hits; 393 } 394 395 399 private void releaseIndexSearcher() { 400 if (indexSearcher != null) { 401 try { 402 indexSearcher.close(); 403 } catch (IOException ioe) { 404 } 406 indexSearcher = null; 407 } 408 } 409 410 411 415 private void releaseIndexReaderCache() { 416 if (indexReaderCache != null) { 417 indexReaderCache = null; 418 } 419 } 420 421 422 426 static class IndexReaderCache 427 { 428 private IndexReader indexReader; 429 private long lastModified; 430 431 432 436 IndexReaderCache() { } 437 438 439 445 public IndexReader getIndexReader(Directory directory) throws IOException { 446 if (indexReader == null) { 447 createIndexReader(directory); 448 } else { 449 if (!indexReaderIsValid(directory)) { 450 createIndexReader(directory); 451 } 452 } 453 return indexReader; 454 } 455 456 457 461 public void close() { 462 if (indexReader != null) { 463 try { 464 indexReader.close(); 465 } catch (IOException ioe) { 466 } 468 indexReader = null; 469 } 470 } 471 472 473 482 public boolean indexReaderIsValid(Directory directory) throws IOException { 483 return indexReader != null && 484 IndexReader.getCurrentVersion(directory) == lastModified; 485 } 486 487 488 493 protected void finalize() throws Throwable { 494 close(); 495 } 496 497 498 504 private void createIndexReader(Directory directory) throws IOException { 505 close(); 506 indexReader = IndexReader.open(directory); 507 lastModified = IndexReader.getCurrentVersion(directory); 508 } 509 } 510 } 511 512 | Popular Tags |