search.jsp revision 849
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RCDDL HEADER START
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RThe contents of this file are subject to the terms of the
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RCommon Development and Distribution License (the "License").
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RYou may not use this file except in compliance with the License.
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RSee LICENSE.txt included in this distribution for the specific
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rlanguage governing permissions and limitations under the License.
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RWhen distributing Covered Code, include this CDDL HEADER in each
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rfile and include the License file at LICENSE.txt.
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RIf applicable, add the following below this CDDL HEADER, with the
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rfields enclosed by brackets "[]" replaced with your own identifying
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rinformation: Portions Copyright [yyyy] [name of copyright owner]
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RCDDL HEADER END
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RCopyright 2009 Sun Microsystems, Inc. All rights reserved.
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RUse is subject to license terms.
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rident "%Z%%M% %I% %E% SMI"
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R--%><%@ page import = "javax.servlet.*,
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rorg.apache.lucene.search.spell.LuceneDictionary,
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R%><%@ page session="false" %><%@ page errorPage="error.jsp" %><%
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RDate starttime = new Date();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString defs = request.getParameter("defs");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString refs = request.getParameter("refs");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString hist = request.getParameter("hist");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString path = request.getParameter("path");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R%><%@ include file="projects.jspf" %><%
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString sort = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rfinal String LASTMODTIME = "lastmodtime";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rfinal String RELEVANCY = "relevancy";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rfinal String BY_PATH = "fullpath";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RCookie[] cookies = request.getCookies();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif (cookies != null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R for (Cookie cookie : cookies) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (cookie.getName().equals("OpenGrok/sorting")) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (!LASTMODTIME.equals(sort) && !RELEVANCY.equals(sort) && !BY_PATH.equals(sort)) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R sort = RELEVANCY;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString sortParam = request.getParameter("sort");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif (sortParam != null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (LASTMODTIME.equals(sortParam)) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R sort = LASTMODTIME;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } else if (RELEVANCY.equals(sortParam)) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R sort = RELEVANCY;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } else if (BY_PATH.equals(sortParam)) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R sort = BY_PATH;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (sort != null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R Cookie cookie = new Cookie("OpenGrok/sorting", sort);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R} else { sort = RELEVANCY; }
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R//List<org.apache.lucene.document.Document> docs=new ArrayList<org.apache.lucene.document.Document>();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.RString errorMsg = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif( q!= null && q.equals("")) q = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif( defs != null && defs.equals("")) defs = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif( refs != null && refs.equals("")) refs = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif( hist != null && hist.equals("")) hist = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif( path != null && path.equals("")) path = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif (project != null && project.size()<1) project = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.Rif (q != null || defs != null || refs != null || hist != null || path != null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R Searcher searcher = null; //the searcher used to open/search the index
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R TopDocCollector collector=null; // the collector used
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R ScoreDoc[] hits = null; // list of documents which result from the query
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R IndexReader ireader = null; //the reader used to open/search the index
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R Query query = null, defQuery = null; //the Query created by the QueryParser
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R boolean allCollected=false;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int totalHits=0;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int start = 0; //the first index displayed on this page
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //TODO deprecate max this and merge with paging and param n - TEST needed
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //int max = 25; //the maximum items displayed on this page
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int max=RuntimeEnvironment.getInstance().getHitsPerPage();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int hitsPerPage = RuntimeEnvironment.getInstance().getHitsPerPage();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int cachePages= RuntimeEnvironment.getInstance().getCachePages();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R int thispage = 0; //used for the for/next either max or
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R String moreUrl = null;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R CompatibleAnalyser analyzer = new CompatibleAnalyser();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R String qstr = "";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R String result = "";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R String DATA_ROOT = env.getDataRootPath();
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R throw new Exception("DATA_ROOT parameter is not configured in web.xml!");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R File data_root = new File(DATA_ROOT);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R throw new Exception("DATA_ROOT parameter in web.xml does not exist or is not a directory!");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //String date = request.getParameter("date");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //TODO merge paging hitsPerPage with parameter n (has to reflect the search if changed so proper number is cached first time)
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R start = Integer.parseInt(request.getParameter("start")); //parse the max results first
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R max = Integer.parseInt(request.getParameter("n")); //then the start index
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if(max < 0 || (max % 10 != 0) || max > 50) max = 25;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if(start < 0 ) start = 0;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } catch (Exception e) { }
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R qstr = Util.buildQueryString(q, defs, refs, path, hist);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R QueryParser qparser = new QueryParser("full", analyzer);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R qparser.setDefaultOperator(QueryParser.AND_OPERATOR);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R qparser.setAllowLeadingWildcard(env.isAllowLeadingWildcard());
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R query = qparser.parse(qstr); //parse the
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R File root = new File(RuntimeEnvironment.getInstance().getDataRootFile(),
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (RuntimeEnvironment.getInstance().hasProjects()) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (project == null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R errorMsg = "<b>Error:</b> You must select a project!";
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (project.size() > 1) { //more projects
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R IndexSearcher[] searchables = new IndexSearcher[project.size()];
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R File droot = new File(RuntimeEnvironment.getInstance().getDataRootFile(), "index");
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //TODO might need to rewrite to Project instead of String , need changes in projects.jspf too
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R for (String proj : project) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R ireader = (IndexReader.open(new File(droot, proj)));
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searchables[ii++] = new IndexSearcher(ireader);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (Runtime.getRuntime().availableProcessors() > 1) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searcher = new ParallelMultiSearcher(searchables);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searcher = new MultiSearcher(searchables);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } else { // just 1 project selected
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R root = new File(root, project.get(0));
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R ireader = IndexReader.open(root);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searcher = new IndexSearcher(ireader);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } else { //no project setup
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R ireader = IndexReader.open(root);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searcher = new IndexSearcher(ireader);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R //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 ;)
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (errorMsg == null) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R collector = new TopDocCollector(hitsPerPage*cachePages);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R Sort sortf = new Sort("date", true);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R TopFieldDocs fdocs=searcher.search(query, null,hitsPerPage*cachePages, sortf);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (start>=hitsPerPage*cachePages && !allCollected) { //fetch ALL results only if above cachePages
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R fdocs=searcher.search(query, null, totalHits, sortf);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R allCollected=true;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R } else if (BY_PATH.equals(sort)) {
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R Sort sortf = new Sort(BY_PATH);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R TopFieldDocs fdocs=searcher.search(query, null,hitsPerPage*cachePages, sortf);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (start>=hitsPerPage*cachePages && !allCollected) { //fetch ALL results only if above cachePages
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R fdocs=searcher.search(query, null,totalHits, sortf);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R allCollected=true;
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R searcher.search(query,collector);
ee1e4c0fa7e8a973ecf16b7535664b8f47fc7e75Niranjan M.R if (start>=hitsPerPage*cachePages && !allCollected) { //fetch ALL results only if above cachePages
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) {
errorMsg = "<b>Error parsing your query:</b><br/>" + Util.htmlize(qstr) +
"\"</a><p/> or read the <a href=\"help.jsp\">Help</a> on query language(eventually <a href=\"help.jsp#escaping\">escape special characters</a> with <b>\\</b>)<p/>" +
if (hits != null && hits.length == 1 && request.getServletPath().equals("/s") && (query != null && query instanceof TermQuery)) {
String preFragmentPath = Util.URIEncodePath(context + "/xref" + 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"><%
StringBuffer url = request.getRequestURL();
url.append('?');
String querys = request.getQueryString();
int idx = querys.indexOf("sort=");
url.append(querys);
url.append('&');
url.append("sort=");
if (sort == null || RELEVANCY.equals(sort)) {
%><b>relevance</b> | <a href="<%=url.toString()+LASTMODTIME%>">last modified time</a> | <a href="<%=url.toString()+BY_PATH%>">path</a><%
} else if (LASTMODTIME.equals(sort)) {
%><a href="<%=url.toString()+RELEVANCY%>">relevance</a> | <b>last modified time</b> | <a href="<%=url.toString()+BY_PATH%>">path</a><%
} else if (BY_PATH.equals(sort)) {
%><a href="<%=url.toString()+RELEVANCY%>">relevance</a> | <a href="<%=url.toString()+LASTMODTIME%>">last modified time</a> | <b>path</b><%
%><a href="<%=url.toString()+RELEVANCY%>">relevance</a> | <a href="<%=url.toString()+LASTMODTIME%>">last modified time</a> | <a href="<%=url.toString()+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.getDirectory(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 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)) +
(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=\"search?n=" + max + "&start=" + i + url + "\">"+
%> Searched <b><%=query.toString()%></b> (Results <b><%=start+1%> -
slider.toString(): ""%></p>
//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"%><%