search.jsp revision 947
03831d35f7499c87d51205817c93e9a8d42c4baestevelCDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevelThe contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevelCommon Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevelYou may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevelSee LICENSE.txt included in this distribution for the specific
03831d35f7499c87d51205817c93e9a8d42c4baestevellanguage governing permissions and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevelWhen distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevelfile and include the License file at LICENSE.txt.
03831d35f7499c87d51205817c93e9a8d42c4baestevelIf applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevelfields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevelinformation: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevelCDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevelCopyright 2010 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevelUse is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel--%><%@ page import = "javax.servlet.*,
03831d35f7499c87d51205817c93e9a8d42c4baestevel%><%@ page session="false" %><%@ page errorPage="error.jsp" %><%
03831d35f7499c87d51205817c93e9a8d42c4baestevelDate starttime = new Date();
03831d35f7499c87d51205817c93e9a8d42c4baestevelString q = request.getParameter("q");
03831d35f7499c87d51205817c93e9a8d42c4baestevelString defs = request.getParameter("defs");
03831d35f7499c87d51205817c93e9a8d42c4baestevelString refs = request.getParameter("refs");
03831d35f7499c87d51205817c93e9a8d42c4baestevelString hist = request.getParameter("hist");
03831d35f7499c87d51205817c93e9a8d42c4baestevelString path = request.getParameter("path");
03831d35f7499c87d51205817c93e9a8d42c4baestevel%><%@ include file="projects.jspf" %><%
03831d35f7499c87d51205817c93e9a8d42c4baestevelString sort = null;
03831d35f7499c87d51205817c93e9a8d42c4baestevelfinal String LASTMODTIME = "lastmodtime";
03831d35f7499c87d51205817c93e9a8d42c4baestevelfinal String RELEVANCY = "relevancy";
03831d35f7499c87d51205817c93e9a8d42c4baestevelfinal String BY_PATH = "fullpath";
03831d35f7499c87d51205817c93e9a8d42c4baestevelfinal SortField S_BY_PATH = new SortField(BY_PATH,SortField.STRING);
03831d35f7499c87d51205817c93e9a8d42c4baestevelCookie[] cookies = request.getCookies();
03831d35f7499c87d51205817c93e9a8d42c4baestevelif (cookies != null) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (Cookie cookie : cookies) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!LASTMODTIME.equals(sort) && !RELEVANCY.equals(sort) && !BY_PATH.equals(sort)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sort = RELEVANCY;
03831d35f7499c87d51205817c93e9a8d42c4baestevelString sortParam = request.getParameter("sort");
03831d35f7499c87d51205817c93e9a8d42c4baestevelif (sortParam != null) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (LASTMODTIME.equals(sortParam)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sort = LASTMODTIME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (RELEVANCY.equals(sortParam)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sort = RELEVANCY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (BY_PATH.equals(sortParam)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sort = BY_PATH;
Cookie cookie = new Cookie("OpenGrok/sorting", sort);
response.addCookie(cookie);
//List<org.apache.lucene.document.Document> docs=new ArrayList<org.apache.lucene.document.Document>();
if( q!= null && q.equals("")) q = null;
if( defs != null && defs.equals("")) defs = null;
if( refs != null && refs.equals("")) refs = null;
if( hist != null && hist.equals("")) hist = null;
if( path != null && path.equals("")) path = null;
if (project != null && project.size()<1) project = null;
Searcher searcher = null; //the searcher used to open/search the index
IndexReader ireader = null; //the reader used to open/search the index
int max=RuntimeEnvironment.getInstance().getHitsPerPage();
int hitsPerPage = RuntimeEnvironment.getInstance().getHitsPerPage();
int cachePages= RuntimeEnvironment.getInstance().getCachePages();
int thispage = 0; //used for the for/next either max or
String DATA_ROOT = env.getDataRootPath();
if(DATA_ROOT.equals("")) {
throw new Exception("DATA_ROOT parameter is not configured in web.xml!");
if(!data_root.isDirectory()) {
throw new Exception("DATA_ROOT parameter in web.xml does not exist or is not a directory!");
//String date = request.getParameter("date");
//TODO merge paging hitsPerPage with parameter n (has to reflect the search if changed so proper number is cached first time)
qstr = Util.buildQueryString(q, defs, refs, path, hist);
QueryParser qparser = new QueryParser(SearchEngine.LUCENE_VERSION,"full", analyzer);
query = qparser.parse(qstr); //parse the
File root = new File(RuntimeEnvironment.getInstance().getDataRootFile(),
if (RuntimeEnvironment.getInstance().hasProjects()) {
if (project.size() > 1) { //more projects
IndexSearcher[] searchables = new IndexSearcher[project.size()];
File droot = new File(RuntimeEnvironment.getInstance().getDataRootFile(), "index");
//TODO might need to rewrite to Project instead of String , need changes in projects.jspf too
if (Runtime.getRuntime().availableProcessors() > 1) {
root = new File(root, project.get(0));
//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 ;)
collector = TopScoreDocCollector.create(hitsPerPage*cachePages,docsScoredInOrder);
if (LASTMODTIME.equals(sort)) {
Sort sortf = new Sort(new SortField("date",SortField.STRING,true));
TopFieldDocs fdocs=searcher.search(query, null,hitsPerPage*cachePages, sortf);
totalHits=fdocs.totalHits;
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) {
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 (isSingleDefinitionSearch && hits != null && hits.length == 1) {
Document doc = searcher.doc(hits[0].doc);
byte[] rawTags = doc.getFieldable("tags").getBinaryValue();
Definitions tags = Definitions.deserialize(rawTags);
if (tags.occurrences(symbol) == 1) {
if (uniqueDefinition && request.getServletPath().equals("/s")) {
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"><%
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>
//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"%><%