public SearcherResult findRuleMatchesOnIndex(PatternRule rule, Language language) throws IOException, UnsupportedPatternRuleException { // it seems wasteful to re-open the index every time, but I had strange problems (OOM, Array out // of bounds, ...) // when not doing so... open(); try { final PatternRuleQueryBuilder patternRuleQueryBuilder = new PatternRuleQueryBuilder(language); final Query query = patternRuleQueryBuilder.buildRelaxedQuery(rule); if (query == null) { throw new NullPointerException("Cannot search on null query for rule: " + rule.getId()); } final SearchRunnable runnable = new SearchRunnable(indexSearcher, query, language, rule); final Thread searchThread = new Thread(runnable); searchThread.start(); try { // using a TimeLimitingCollector is not enough, as it doesn't cover all time required to // search for a complicated regex, so interrupt the whole thread instead: if (limitSearch) { // FIXME: I don't know a simpler way to achieve this searchThread.join(maxSearchTimeMillis); } else { searchThread.join(Integer.MAX_VALUE); } searchThread.interrupt(); } catch (InterruptedException e) { throw new RuntimeException("Search thread got interrupted for query " + query, e); } if (searchThread.isInterrupted()) { throw new SearchTimeoutException( "Search timeout of " + maxSearchTimeMillis + "ms reached for query " + query); } final Exception exception = runnable.getException(); if (exception != null) { if (exception instanceof SearchTimeoutException) { throw (SearchTimeoutException) exception; } throw new RuntimeException( "Exception during search for query " + query + " on rule " + rule.getId(), exception); } final List<MatchingSentence> matchingSentences = runnable.getMatchingSentences(); final int sentencesChecked = getSentenceCheckCount(query, indexSearcher); final SearcherResult searcherResult = new SearcherResult(matchingSentences, sentencesChecked, query); searcherResult.setHasTooManyLuceneMatches(runnable.hasTooManyLuceneMatches()); searcherResult.setLuceneMatchCount(runnable.getLuceneMatchCount()); if (runnable.hasTooManyLuceneMatches()) { // more potential matches than we can check in an acceptable time :-( searcherResult.setDocCount(maxHits); } else { searcherResult.setDocCount(getDocCount(indexSearcher)); } // TODO: the search itself could also timeout, don't just ignore that: // searcherResult.setResultIsTimeLimited(limitedTopDocs.resultIsTimeLimited); return searcherResult; } finally { close(); } }