Coverage Report - org.owasp.dependencycheck.data.cpe.CpeIndexReader
 
Classes in this File Line Coverage Branch Coverage Complexity
CpeIndexReader
60%
32/53
33%
6/18
2.5
 
 1  
 /*
 2  
  * This file is part of dependency-check-core.
 3  
  *
 4  
  * Dependency-check-core is free software: you can redistribute it and/or modify it
 5  
  * under the terms of the GNU General Public License as published by the Free
 6  
  * Software Foundation, either version 3 of the License, or (at your option) any
 7  
  * later version.
 8  
  *
 9  
  * Dependency-check-core is distributed in the hope that it will be useful, but
 10  
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 12  
  * details.
 13  
  *
 14  
  * You should have received a copy of the GNU General Public License along with
 15  
  * dependency-check-core. If not, see http://www.gnu.org/licenses/.
 16  
  *
 17  
  * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
 18  
  */
 19  
 package org.owasp.dependencycheck.data.cpe;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.HashMap;
 23  
 import java.util.Map;
 24  
 import java.util.logging.Level;
 25  
 import java.util.logging.Logger;
 26  
 import org.apache.lucene.analysis.Analyzer;
 27  
 import org.apache.lucene.analysis.core.KeywordAnalyzer;
 28  
 import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper;
 29  
 import org.apache.lucene.document.Document;
 30  
 import org.apache.lucene.index.CorruptIndexException;
 31  
 import org.apache.lucene.index.DirectoryReader;
 32  
 import org.apache.lucene.index.IndexReader;
 33  
 import org.apache.lucene.queryparser.classic.ParseException;
 34  
 import org.apache.lucene.queryparser.classic.QueryParser;
 35  
 import org.apache.lucene.search.IndexSearcher;
 36  
 import org.apache.lucene.search.Query;
 37  
 import org.apache.lucene.search.TopDocs;
 38  
 import org.apache.lucene.util.Version;
 39  
 import org.owasp.dependencycheck.data.lucene.FieldAnalyzer;
 40  
 import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer;
 41  
 
 42  
 /**
 43  
  *
 44  
  * @author Jeremy Long (jeremy.long@owasp.org)
 45  
  */
 46  15
 public class CpeIndexReader extends BaseIndex {
 47  
 
 48  
     /**
 49  
      * The Lucene IndexReader.
 50  
      */
 51  
     private IndexReader indexReader;
 52  
     /**
 53  
      * The Lucene IndexSearcher.
 54  
      */
 55  
     private IndexSearcher indexSearcher;
 56  
     /**
 57  
      * The Lucene Analyzer used for Searching.
 58  
      */
 59  
     private Analyzer searchingAnalyzer;
 60  
     /**
 61  
      * The Lucene QueryParser used for Searching.
 62  
      */
 63  
     private QueryParser queryParser;
 64  
     /**
 65  
      * The search field analyzer for the product field.
 66  
      */
 67  
     private SearchFieldAnalyzer productSearchFieldAnalyzer;
 68  
     /**
 69  
      * The search field analyzer for the vendor field.
 70  
      */
 71  
     private SearchFieldAnalyzer vendorSearchFieldAnalyzer;
 72  
 
 73  
     /**
 74  
      * Opens the CPE Index.
 75  
      *
 76  
      * @throws IOException is thrown if an IOException occurs opening the index.
 77  
      */
 78  
     @Override
 79  
     public void open() throws IOException {
 80  
         //TODO add spinlock (shared)
 81  15
         super.open();
 82  15
         indexReader = DirectoryReader.open(getDirectory());
 83  15
         indexSearcher = new IndexSearcher(indexReader);
 84  15
         searchingAnalyzer = createSearchingAnalyzer();
 85  15
         queryParser = new QueryParser(Version.LUCENE_43, Fields.DOCUMENT_KEY, searchingAnalyzer);
 86  15
     }
 87  
 
 88  
     /**
 89  
      * Closes the CPE Index.
 90  
      */
 91  
     @Override
 92  
     public void close() {
 93  
         //TODO remove spinlock (shared)
 94  15
         if (searchingAnalyzer != null) {
 95  15
             searchingAnalyzer.close();
 96  15
             searchingAnalyzer = null;
 97  
         }
 98  15
         if (indexReader != null) {
 99  
             try {
 100  15
                 indexReader.close();
 101  0
             } catch (IOException ex) {
 102  0
                 Logger.getLogger(CpeIndexReader.class.getName()).log(Level.FINEST, null, ex);
 103  15
             }
 104  15
             indexReader = null;
 105  
         }
 106  15
         queryParser = null;
 107  15
         indexSearcher = null;
 108  15
         super.close();
 109  15
     }
 110  
 
 111  
     /**
 112  
      * Searches the index using the given search string.
 113  
      *
 114  
      * @param searchString the query text
 115  
      * @param maxQueryResults the maximum number of documents to return
 116  
      * @return the TopDocs found by the search
 117  
      * @throws ParseException thrown when the searchString is invalid
 118  
      * @throws IOException is thrown if there is an issue with the underlying
 119  
      * Index
 120  
      */
 121  
     public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
 122  73
         if (searchString == null || searchString.trim().isEmpty()) {
 123  0
             throw new ParseException("Query is null or empty");
 124  
         }
 125  73
         if (queryParser == null) {
 126  0
             if (isOpen()) {
 127  0
                 final String msg = String.format("QueryParser is null for query: '%s'. Attempting to reopen index.",
 128  
                         searchString);
 129  0
                 Logger.getLogger(CpeIndexReader.class.getName()).log(Level.WARNING, msg);
 130  0
                 close();
 131  0
                 open();
 132  0
             } else {
 133  0
                 final String msg = String.format("QueryParser is null, but data source is open, for query: '%s'. Attempting to reopen index.",
 134  
                         searchString);
 135  0
                 Logger.getLogger(CpeIndexReader.class.getName()).log(Level.WARNING, msg);
 136  0
                 close();
 137  0
                 open();
 138  
             }
 139  
         }
 140  73
         final Query query = queryParser.parse(searchString);
 141  73
         return indexSearcher.search(query, maxQueryResults);
 142  
     }
 143  
 
 144  
     /**
 145  
      * Searches the index using the given query.
 146  
      *
 147  
      * @param query the query used to search the index
 148  
      * @param maxQueryResults the max number of results to return
 149  
      * @return the TopDocs found be the query
 150  
      * @throws CorruptIndexException thrown if the Index is corrupt
 151  
      * @throws IOException thrown if there is an IOException
 152  
      */
 153  
     public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
 154  0
         resetSearchingAnalyzer();
 155  0
         return indexSearcher.search(query, maxQueryResults);
 156  
     }
 157  
 
 158  
     /**
 159  
      * Retrieves a document from the Index.
 160  
      *
 161  
      * @param documentId the id of the document to retrieve
 162  
      * @return the Document
 163  
      * @throws IOException thrown if there is an IOException
 164  
      */
 165  
     public Document getDocument(int documentId) throws IOException {
 166  741
         return indexSearcher.doc(documentId);
 167  
     }
 168  
 
 169  
     /**
 170  
      * Creates an Analyzer for searching the CPE Index.
 171  
      *
 172  
      * @return the CPE Analyzer.
 173  
      */
 174  
     @SuppressWarnings("unchecked")
 175  
     private Analyzer createSearchingAnalyzer() {
 176  15
         final Map fieldAnalyzers = new HashMap();
 177  15
         fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
 178  15
         productSearchFieldAnalyzer = new SearchFieldAnalyzer(Version.LUCENE_43);
 179  15
         vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(Version.LUCENE_43);
 180  15
         fieldAnalyzers.put(Fields.PRODUCT, productSearchFieldAnalyzer);
 181  15
         fieldAnalyzers.put(Fields.VENDOR, vendorSearchFieldAnalyzer);
 182  
 
 183  15
         return new PerFieldAnalyzerWrapper(new FieldAnalyzer(Version.LUCENE_43), fieldAnalyzers);
 184  
     }
 185  
 
 186  
     /**
 187  
      * Resets the searching analyzers
 188  
      */
 189  
     private void resetSearchingAnalyzer() {
 190  0
         if (productSearchFieldAnalyzer != null) {
 191  0
             productSearchFieldAnalyzer.clear();
 192  
         }
 193  0
         if (vendorSearchFieldAnalyzer != null) {
 194  0
             vendorSearchFieldAnalyzer.clear();
 195  
         }
 196  0
     }
 197  
 
 198  
     /**
 199  
      * Returns the number of CPE entries stored in the index.
 200  
      *
 201  
      * @return the number of CPE entries stored in the index
 202  
      */
 203  
     public int numDocs() {
 204  3
         if (indexReader == null) {
 205  0
             return -1;
 206  
         }
 207  3
         return indexReader.numDocs();
 208  
     }
 209  
 }