##### 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;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 |  |
     }