search.jsp revision 1111
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonCDDL HEADER START
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonThe contents of this file are subject to the terms of the
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonCommon Development and Distribution License (the "License").
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonYou may not use this file except in compliance with the License.
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonSee LICENSE.txt included in this distribution for the specific
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonlanguage governing permissions and limitations under the License.
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonWhen distributing Covered Code, include this CDDL HEADER in each
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfile and include the License file at LICENSE.txt.
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonIf applicable, add the following below this CDDL HEADER, with the
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfields enclosed by brackets "[]" replaced with your own identifying
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsoninformation: Portions Copyright [yyyy] [name of copyright owner]
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonCDDL HEADER END
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonCopyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson--%><%@ page import = "javax.servlet.*,
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonorg.apache.lucene.search.spell.LuceneDictionary,
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson%><%@ page session="false" %><%@ page errorPage="error.jsp" %><%
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonDate starttime = new Date();
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString defs = request.getParameter("defs");
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString refs = request.getParameter("refs");
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString hist = request.getParameter("hist");
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString path = request.getParameter("path");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson%><%@ include file="projects.jspf" %><%
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString sort = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfinal String LASTMODTIME = "lastmodtime";
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfinal String RELEVANCY = "relevancy";
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfinal String BY_PATH = "fullpath";
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonfinal SortField S_BY_PATH = new SortField(BY_PATH,SortField.STRING);
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonCookie[] cookies = request.getCookies();
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif (cookies != null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson for (Cookie cookie : cookies) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (cookie.getName().equals("OpenGrok/sorting")) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (!LASTMODTIME.equals(sort) && !RELEVANCY.equals(sort) && !BY_PATH.equals(sort)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson sort = RELEVANCY;
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString sortParam = request.getParameter("sort");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif (sortParam != null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (LASTMODTIME.equals(sortParam)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson sort = LASTMODTIME;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson } else if (RELEVANCY.equals(sortParam)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson sort = RELEVANCY;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson } else if (BY_PATH.equals(sortParam)) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson sort = BY_PATH;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (sort != null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson Cookie cookie = new Cookie("OpenGrok/sorting", sort);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson} else { sort = RELEVANCY; }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson//List<org.apache.lucene.document.Document> docs=new ArrayList<org.apache.lucene.document.Document>();
7eea693d6b672899726e75993fddc4e95b52647fMark JohnsonString errorMsg = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif( q!= null && q.equals("")) q = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif( defs != null && defs.equals("")) defs = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif( refs != null && refs.equals("")) refs = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif( hist != null && hist.equals("")) hist = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif( path != null && path.equals("")) path = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif (project != null && project.size()<1) project = null;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnsonif (q != null || defs != null || refs != null || hist != null || path != null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson Searcher searcher = null; //the searcher used to open/search the index
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson TopScoreDocCollector collector=null; // the collector used
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson ScoreDoc[] hits = null; // list of documents which result from the query
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson Query query = null; //the Query created by the QueryBuilder
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson boolean allCollected=false;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int totalHits=0;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int start = 0; //the first index displayed on this page
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //TODO deprecate max this and merge with paging and param n - TEST needed
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //int max = 25; //the maximum items displayed on this page
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int max=RuntimeEnvironment.getInstance().getHitsPerPage();
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int hitsPerPage = RuntimeEnvironment.getInstance().getHitsPerPage();
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int cachePages= RuntimeEnvironment.getInstance().getCachePages();
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson final boolean docsScoredInOrder=false;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson int thispage = 0; //used for the for/next either max or
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson QueryBuilder queryBuilder =
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson new QueryBuilder()
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson .setFreetext(q).setDefs(defs).setRefs(refs)
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson .setPath(path).setHist(hist);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson String DATA_ROOT = env.getDataRootPath();
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson throw new Exception("DATA_ROOT parameter is not configured in web.xml!");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson File data_root = new File(DATA_ROOT);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson throw new Exception("DATA_ROOT parameter in web.xml does not exist or is not a directory!");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //String date = request.getParameter("date");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //TODO merge paging hitsPerPage with parameter n (has to reflect the search if changed so proper number is cached first time)
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson start = Integer.parseInt(request.getParameter("start")); //parse the max results first
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson max = Integer.parseInt(request.getParameter("n")); //then the start index
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if(max < 0 || (max % 10 != 0) || max > 50) max = 25;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if(start < 0 ) start = 0;
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson } catch (Exception e) { }
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson File root = new File(RuntimeEnvironment.getInstance().getDataRootFile(),
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (RuntimeEnvironment.getInstance().hasProjects()) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (project == null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson errorMsg = "<b>Error:</b> You must select a project!";
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (project.size() > 1) { //more projects
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson IndexSearcher[] searchables = new IndexSearcher[project.size()];
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson File droot = new File(RuntimeEnvironment.getInstance().getDataRootFile(), "index");
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //TODO might need to rewrite to Project instead of String , need changes in projects.jspf too
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson for (String proj : project) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson FSDirectory dir = FSDirectory.open(new File(droot, proj));
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson searchables[ii++] = new IndexSearcher(dir);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (Runtime.getRuntime().availableProcessors() > 1) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson searcher = new ParallelMultiSearcher(searchables);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson searcher = new MultiSearcher(searchables);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson } else { // just 1 project selected
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson root = new File(root, project.get(0));
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson FSDirectory dir = FSDirectory.open(root);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson searcher = new IndexSearcher(dir);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson } else { //no project setup
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson FSDirectory dir = FSDirectory.open(root);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson searcher = new IndexSearcher(dir);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson //TODO check if below is somehow reusing sessions so we don't requery again and again, I guess 2min timeout sessions could be usefull, since you click on the next page within 2mins, if not, then wait ;)
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (errorMsg == null) {
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson collector = TopScoreDocCollector.create(hitsPerPage*cachePages,docsScoredInOrder);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson Sort sortf = new Sort(new SortField("date",SortField.STRING,true));
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson TopFieldDocs fdocs=searcher.search(query, null,hitsPerPage*cachePages, sortf);
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson if (start>=hitsPerPage*cachePages && !allCollected) { //fetch ALL results only if above cachePages
7eea693d6b672899726e75993fddc4e95b52647fMark Johnson fdocs=searcher.search(query, null, totalHits, sortf);
hits = fdocs.scoreDocs;
} else if (BY_PATH.equals(sort)) {
TopFieldDocs fdocs=searcher.search(query, null,hitsPerPage*cachePages, sortf);
totalHits=fdocs.totalHits;
fdocs=searcher.search(query, null,totalHits, sortf);
hits = fdocs.scoreDocs;
searcher.search(query,collector);
totalHits=collector.getTotalHits();
collector = TopScoreDocCollector.create(totalHits,docsScoredInOrder);
searcher.search(query,collector);
hits=collector.topDocs().scoreDocs;
// for (int i = 0; i < hits.length; i++) {
// Document d = searcher.doc(docId);
// docs.add(d);
} catch (BooleanQuery.TooManyClauses e) {
"<a href=\"help.jsp#escaping\">escape special characters</a> " +
"with <b>\\</b>, or read the <a href=\"help.jsp\">Help</a> " +
if (isSingleDefinitionSearch && hits != null && hits.length == 1) {
Document doc = searcher.doc(hits[0].doc);
if (doc.getFieldable("tags")!=null) {
byte[] rawTags = doc.getFieldable("tags").getBinaryValue();
Definitions tags = Definitions.deserialize(rawTags);
if (tags.occurrences(symbol) == 1) {
String preFragmentPath = Util.URIEncodePath(context + Constants.xrefP + searcher.doc(hits[0].doc).get("path"));
String fragment = Util.URIEncode(((TermQuery)query).getTerm().text());
url.append("#");
url.append(fragment);
RuntimeEnvironment environment = RuntimeEnvironment.getInstance();
%><%@ include file="httpheader.jspf" %>
<div id="header"><%@ include file="pageheader.jspf" %></div>
<table border="0" width="100%"><tr><td><a href="<%=context%>/" id="home">Home</a></td><td align="right"><%
url = url + (q == null ? "" : "&q=" + Util.URIEncode(q)) +
(defs == null ? "" : "&defs=" + Util.URIEncode(defs)) +
(refs == null ? "" : "&refs=" + Util.URIEncode(refs)) +
(path == null ? "" : "&path=" + Util.URIEncode(path)) +
(hist == null ? "" : "&hist=" + Util.URIEncode(hist));
if (sort == null || RELEVANCY.equals(sort)) {
%><b>relevance</b> | <a href="<%=url+LASTMODTIME%>">last modified time</a> | <a href="<%=url+BY_PATH%>">path</a><%
} else if (LASTMODTIME.equals(sort)) {
%><a href="<%=url+RELEVANCY%>">relevance</a> | <b>last modified time</b> | <a href="<%=url+BY_PATH%>">path</a><%
} else if (BY_PATH.equals(sort)) {
%><a href="<%=url+RELEVANCY%>">relevance</a> | <a href="<%=url+LASTMODTIME%>">last modified time</a> | <b>path</b><%
%><a href="<%=url+RELEVANCY%>">relevance</a> | <a href="<%=url+LASTMODTIME%>">last modified time</a> | <a href="<%=url+BY_PATH%>">path</a><%
<%@ include file="menu.jspf"%>
//TODO spellchecking cycle below is not that great and we only create suggest links for every token in query, not for a query as whole
} else if (hits.length == 0) {
File spellIndex = new File(env.getDataRootPath(), "spellIndex");
if (RuntimeEnvironment.getInstance().hasProjects()) {
if (project.size() > 1) { //more projects
spellIndexes = new File[project.size()];
//TODO might need to rewrite to Project instead of String , need changes in projects.jspf too
spellIndex = new File(spellIndex, project.get(0));
if (spellIndexes!=null) {count=spellIndexes.length;}
if (spellIndex.exists()) {
FSDirectory spellDirectory = FSDirectory.open(spellIndex);
toks = q.split("[\t ]+");
for(int j=0; j<toks.length; j++) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 5);
for(int i = 0;i < ret.length; i++) {
%><p><font color="#cc0000">Did you mean(for <%=spellIndex.getName()%>)</font>:<%
toks = refs.split("[\t ]+");
for(int j=0; j<toks.length; j++) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 5);
for(int i = 0;i < ret.length; i++) {
%><p><font color="#cc0000">Did you mean(for <%=spellIndex.getName()%>)</font>:<%
//TODO it seems the only true spellchecker is for below field, see IndexDatabase createspellingsuggestions ...
toks = defs.split("[\t ]+");
for(int j=0; j<toks.length; j++) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 5);
for(int i = 0;i < ret.length; i++) {
%><p><font color="#cc0000">Did you mean(for <%=spellIndex.getName()%>)</font>:<%
%><p> Your search <b><%=query.toString()%></b> did not match any files.
String urlp = (q == null ? "" : "&q=" + Util.URIEncode(q)) +
(defs == null ? "" : "&defs=" + Util.URIEncode(defs)) +
(refs == null ? "" : "&refs=" + Util.URIEncode(refs)) +
(path == null ? "" : "&path=" + Util.URIEncode(path)) +
(hist == null ? "" : "&hist=" + Util.URIEncode(hist)) +
(sort == null ? "" : "&sort=" + Util.URIEncode(sort));
labelStart = sstart/max + 1;
slider.append("<span class=\"sel\">" + label + "</span>");
arr = label < 10 ? " " + label : String.valueOf(label);
slider.append("<a class=\"more\" href=\"s?n=" + max + "&start=" + i + urlp + "\">"+
%> Searched <b><%=query.toString()%></b> (Results <b><%=start+1%> -
slider.toString(): ""%></p>
new Context(query, queryBuilder.getQueries());
//TODO also fix the way what and how it is passed to prettyprint, can improve performance! SearchEngine integration is really needed here.
Results.prettyPrintHTML(searcher,hits, start, start+thispage,
ef.close();
<b> Completed in <%=(new Date()).getTime() - starttime.getTime()%> milliseconds </b> <br/>
%><br/></div><%@include file="foot.jspf"%><%