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