search.jsp revision 144
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber<%--
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberCDDL HEADER START
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberThe contents of this file are subject to the terms of the
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberCommon Development and Distribution License (the "License").
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberYou may not use this file except in compliance with the License.
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberSee LICENSE.txt included in this distribution for the specific
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberlanguage governing permissions and limitations under the License.
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberWhen distributing Covered Code, include this CDDL HEADER in each
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberfile and include the License file at LICENSE.txt.
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberIf applicable, add the following below this CDDL HEADER, with the
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberfields enclosed by brackets "[]" replaced with your own identifying
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberinformation: Portions Copyright [yyyy] [name of copyright owner]
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberCDDL HEADER END
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberCopyright 2005 Sun Microsystems, Inc. All rights reserved.
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberUse is subject to license terms.
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberident "%Z%%M% %I% %E% SMI"
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber--%><%@ page import = "javax.servlet.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.lang.Integer,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjavax.servlet.http.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.util.Hashtable,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.util.Vector,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.util.Date,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.util.ArrayList,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.util.List,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.lang.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.io.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberjava.io.StringReader,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.opensolaris.opengrok.analysis.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.opensolaris.opengrok.search.*,
afeecbba0359d2b4404cdf896e6b6d0b5a8443b0Serge Hallynorg.opensolaris.opengrok.web.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.opensolaris.opengrok.web.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.opensolaris.opengrok.search.context.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.opensolaris.opengrok.configuration.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.search.spell.LuceneDictionary,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.search.spell.SpellChecker,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.store.FSDirectory,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.analysis.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.document.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.index.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.search.*,
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberorg.apache.lucene.queryParser.*"
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber%><%@ page session="false" %><%@ page errorPage="error.jsp" %><%
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberDate starttime = new Date();
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString q = request.getParameter("q");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString defs = request.getParameter("defs");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString refs = request.getParameter("refs");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString hist = request.getParameter("hist");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString path = request.getParameter("path");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber%>
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber<%@ include file="projects.jspf" %>
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber<%
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString sort = null;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberfinal String LASTMODTIME = "lastmodtime";
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberfinal String RELEVANCY = "relevancy";
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberCookie[] cookies = request.getCookies();
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberif (cookies != null) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber for (Cookie cookie : cookies) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber if (cookie.getName().equals("OpenGrok/sorting")) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber sort = cookie.getValue();
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber if (!LASTMODTIME.equals(sort) && !RELEVANCY.equals(sort)) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber sort = null;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber }
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber break;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber }
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber }
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber}
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString sortParam = request.getParameter("sort");
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graberif (sortParam != null) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber if (LASTMODTIME.equals(sortParam)) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber sort = LASTMODTIME;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber } else if (RELEVANCY.equals(sortParam)) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber sort = RELEVANCY;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber }
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber if (sort != null) {
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber Cookie cookie = new Cookie("OpenGrok/sorting", sort);
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber response.addCookie(cookie);
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber }
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber}
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberHits hits = null;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane GraberString errorMsg = null;
72d0e1cb2facaa4b8ba2f15e311d6bb9491badb7Stéphane Graber
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.equals("")) project = null;
if (q != null || defs != null || refs != null || hist != null || path != null) {
Searcher searcher = null; //the searcher used to open/search the index
IndexReader ireader = null; //the reader used to open/search the index
Query query = null, defQuery = null; //the Query created by the QueryParser
int start = 0; //the first index displayed on this page
int max = 25; //the maximum items displayed on this page
int thispage = 0; //used for the for/next either max or
String moreUrl = null;
CompatibleAnalyser analyzer = new CompatibleAnalyser();
String qstr = "";
String result = "";
try {
String DATA_ROOT = env.getDataRootPath();
if(DATA_ROOT.equals("")) {
throw new Exception("DATA_ROOT parameter is not configured in web.xml!");
}
File data_root = new File(DATA_ROOT);
if(!data_root.isDirectory()) {
throw new Exception("DATA_ROOT parameter in web.xml does not exist or is not a directory!");
}
ireader = IndexReader.open(DATA_ROOT + "/index");
searcher = new IndexSearcher(ireader);
//String date = request.getParameter("date");
try {
start = Integer.parseInt(request.getParameter("start")); //parse the max results first
max = Integer.parseInt(request.getParameter("n")); //then the start index
if(max < 0 || (max % 10 != 0) || max > 50) max = 25;
if(start < 0 ) start = 0;
} catch (Exception e) { }
StringBuilder sb = new StringBuilder();
if (q != null) {
sb.append(q);
}
if (defs != null) {
sb.append(" defs:(");
sb.append(defs);
sb.append(")");
}
if (refs != null) {
sb.append(" refs:(");
sb.append(refs);
sb.append(")");
}
if (path != null) {
sb.append(" path:(");
sb.append(path);
sb.append(")");
}
if (hist != null) {
sb.append(" hist:(");
sb.append(hist);
sb.append(")");
}
if (project != null) {
sb.append(" (");
boolean first = true;
for (String s : project.split(" ")) {
if (first) {
first = false;
} else {
sb.append(" OR ");
}
sb.append("project:(");
sb.append(s);
sb.append(")");
}
sb.append(")");
}
qstr = sb.toString();
QueryParser qparser = new QueryParser("full", analyzer);
qparser.setDefaultOperator(QueryParser.AND_OPERATOR);
qparser.setAllowLeadingWildcard(env.isAllowLeadingWildcard());
query = qparser.parse(qstr); //parse the
if ("lastmodtime".equals(sort)) {
hits = searcher.search(query, new Sort("date", true));
} else {
hits = searcher.search(query);
}
thispage = max;
} catch (BooleanQuery.TooManyClauses e) {
errorMsg = "<b>Error:</b> Too many results for wildcard!";
} catch (ParseException e) {
errorMsg = "<b>Error:</b><br/>" + Util.Htmlize(qstr) + "<br/>" + Util.Htmlize(e.getMessage());
} catch (FileNotFoundException e) {
errorMsg = "<b>Error:</b> Index database not found";
} catch (Exception e) {
errorMsg = "<b>Error:</b> " + Util.Htmlize(e.getMessage());
}
// @TODO fix me. I should try to figure out where the exact hit is instead
// of returning a page with just _one_ entry in....
if (hits != null && hits.length() == 1 && request.getServletPath().equals("/s") && (query != null && query instanceof TermQuery)) {
response.sendRedirect(context + "/xref" + hits.doc(0).get("path")
+ "#" + ((TermQuery)query).getTerm().text());
} else {
String pageTitle = "Search";
%><%@ include file="httpheader.jspf" %>
<body>
<div id="page">
<div id="header"><%@ include file="pageheader.jspf" %></div>
<div id="Masthead"></div>
<div id="bar">
<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();
if (querys != null) {
int idx = querys.indexOf("sort=");
if (idx == -1) {
url.append(querys);
url.append('&');
} else {
url.append(querys.substring(0, idx));
}
}
url.append("sort=");
if (sort == null || RELEVANCY.equals(sort)) {
url.append(LASTMODTIME);
%><b>Sort by relevance</b> <a href="<%=url.toString()%>">Sort by last modified time</a><%
} else {
url.append(RELEVANCY);
%><a href="<%=url.toString()%>">Sort by relevance</a> <b>Sort by last modified time</b><%
}
} %></td></tr></table>
</div>
<div id="menu">
<%@ include file="menu.jspf"%>
</div>
<div id="results">
<%
if( hits == null || errorMsg != null) {
%><%=errorMsg%><%
} else if (hits.length() == 0) {
File spellIndex = new File(env.getDataRootPath(), "spellIndex");
if (spellIndex.exists()) {
FSDirectory spellDirectory = FSDirectory.getDirectory(spellIndex);
SpellChecker checker = new SpellChecker(spellDirectory);
Date sstart = new Date();
%><p><font color="#cc0000">Did you mean</font>:<%
String[] toks;
if(q != null) {
toks = q.split("[\t ]+");
if(toks != null){
for(int j=0; j<toks.length; j++) {
if(toks[j].length() > 3) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 3);
for(int i = 0;i < ret.length; i++) {
%> <a href=search?q=<%=ret[i]%>><%=ret[i]%></a> &nbsp; <%
}
}
}
}
}
if(refs != null) {
toks = refs.split("[\t ]+");
if(toks != null){
for(int j=0; j<toks.length; j++) {
if(toks[j].length() > 3) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 3);
for(int i = 0;i < ret.length; i++) {
%> <a href=search?q=<%=ret[i]%>><%=ret[i]%></a> &nbsp; <%
}
}
}
}
}
if(defs != null) {
toks = defs.split("[\t ]+");
if(toks != null){
for(int j=0; j<toks.length; j++) {
if(toks[j].length() > 3) {
String[] ret = checker.suggestSimilar(toks[j].toLowerCase(), 3);
for(int i = 0;i < ret.length; i++) {
%> <a href=search?q=<%=ret[i]%>><%=ret[i]%></a> &nbsp; <%
}
}
}
}
}
spellDirectory.close();
%></p><%
}
%><p> Your search <b><%=query.toString()%></b> did not match any files.
<br />
Suggestions:<br/><blockquote>- Make sure all terms are spelled correctly.<br/>
- Try different keywords.<br/>
- Try more general keywords.<br/>
- Use 'wil*' cards if you are looking for partial match.
</blockquote>
</p><%
} else { // We have a lots of results to show
StringBuilder slider = null;
if ( max < hits.length()) {
if((start + max) < hits.length()) {
thispage = max;
} else {
thispage = hits.length() - start;
}
String url = (q == null ? "" : "&amp;q=" + Util.URIEncode(q) ) +
(defs == null ? "" : "&amp;defs=" + Util.URIEncode(defs)) +
(refs == null ? "" : "&amp;refs=" + Util.URIEncode(refs)) +
(path == null ? "" : "&amp;path=" + Util.URIEncode(path)) +
(hist == null ? "" : "&amp;hist=" + Util.URIEncode(hist)) +
(sort == null ? "" : "&amp;sort=" + Util.URIEncode(sort));
slider = new StringBuilder();
int labelStart =1;
int sstart = start - max* (start / max % 10 + 1) ;
if(sstart < 0) {
sstart = 0;
labelStart = 1;
} else {
labelStart = sstart/max + 1;
}
int label = labelStart;
int labelEnd = label + 11;
String arr;
for(int i=sstart; i<hits.length() && label <= labelEnd; i+= max) {
if (i <= start && start < i+ max) {
slider.append("<span class=\"sel\">" + label + "</span>");
} else {
if(label == labelStart && label != 1) {
arr = "&lt;&lt";
} else if(label == labelEnd && i < hits.length()) {
arr = "&gt;&gt;";
} else {
arr = label < 10 ? " " + label : String.valueOf(label);
}
slider.append("<a class=\"more\" href=\"search?n=" + max + "&amp;start=" + i + url + "\">"+
arr + "</a>");
}
label++;
}
} else {
thispage = hits.length() - start; // set the max index to max or last
}
%>&nbsp; &nbsp; Searched <b><%=query.toString()%></b> (Results <b><%=start+1%> -
<%=thispage+start%></b> of <b><%=hits.length()%></b>) sorted by <%=sort%> <p><%=slider != null ?
slider.toString(): ""%></p>
<table width="100%" cellpadding="3" cellspacing="0" border="0"><%
Context sourceContext = null;
Summarizer summer = null;
if (query != null) {
try{
sourceContext = new Context(query);
if(sourceContext != null)
summer = new Summarizer(query, analyzer);
} catch (Exception e) {
}
}
HistoryContext historyContext = null;
try {
historyContext = new HistoryContext(query);
} catch (Exception e) {
}
EftarFileReader ef = null;
try{
ef = new EftarFileReader(env.getDataRootPath() + "/index/dtags.eftar");
} catch (Exception e) {
}
Results.prettyPrintHTML(hits, start, start+thispage,
out,
sourceContext, historyContext, summer,
context + "/xref",
context + "/more",
env.getSourceRootPath(),
env.getDataRootPath(),
ef);
if(ef != null) {
try{
ef.close();
} catch (IOException e) {
}
}
%></table><br/>
<b> Completed in <%=(new Date()).getTime() - starttime.getTime()%> milliseconds </b> <br/>
<%=slider != null ? "<p>" + slider + "</p>" : ""%>
<%
}
%><br/></div><%@include file="foot.jspf"%><%
}
if (ireader != null)
ireader.close();
} else { // Entry page show the map
response.sendRedirect(context + "/index.jsp");
}
%>