xref: /OpenGrok/opengrok-web/src/main/webapp/search.jsp (revision 912cbfdf480a7d5e004f3f4fc465ec8adc1ab0e5)
10d40e9d0SAdam Hornáček<%--
20d40e9d0SAdam HornáčekCDDL HEADER START
30d40e9d0SAdam Hornáček
40d40e9d0SAdam HornáčekThe contents of this file are subject to the terms of the
50d40e9d0SAdam HornáčekCommon Development and Distribution License (the "License").
60d40e9d0SAdam HornáčekYou may not use this file except in compliance with the License.
70d40e9d0SAdam Hornáček
80d40e9d0SAdam HornáčekSee LICENSE.txt included in this distribution for the specific
90d40e9d0SAdam Hornáčeklanguage governing permissions and limitations under the License.
100d40e9d0SAdam Hornáček
110d40e9d0SAdam HornáčekWhen distributing Covered Code, include this CDDL HEADER in each
120d40e9d0SAdam Hornáčekfile and include the License file at LICENSE.txt.
130d40e9d0SAdam HornáčekIf applicable, add the following below this CDDL HEADER, with the
140d40e9d0SAdam Hornáčekfields enclosed by brackets "[]" replaced with your own identifying
150d40e9d0SAdam Hornáčekinformation: Portions Copyright [yyyy] [name of copyright owner]
160d40e9d0SAdam Hornáček
170d40e9d0SAdam HornáčekCDDL HEADER END
180d40e9d0SAdam Hornáček
19c6f0939bSAdam HornacekCopyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
200d40e9d0SAdam HornáčekPortions Copyright 2011 Jens Elkner.
211c830032SChris FrairePortions Copyright (c) 2017-2018, 2020, Chris Fraire <cfraire@me.com>.
220d40e9d0SAdam Hornáček
230d40e9d0SAdam Hornáček--%>
24a804b2d7SAdam Hornáček<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
25aa6abf42SAdam Hornacek<%@page import="jakarta.servlet.http.HttpServletResponse"%>
260d40e9d0SAdam Hornáček<%@page session="false" errorPage="error.jsp" import="
27a5cf78b2SChris Fraireorg.apache.lucene.queryparser.classic.QueryParser,
28686556f2SAdam Hornáčekorg.opengrok.indexer.search.Results,
291c830032SChris Fraireorg.opengrok.web.api.v1.suggester.provider.service.SuggesterServiceFactory,
301c830032SChris Fraireorg.opengrok.indexer.web.QueryParameters,
31686556f2SAdam Hornáčekorg.opengrok.indexer.web.SearchHelper,
32686556f2SAdam Hornáčekorg.opengrok.indexer.web.SortOrder,
331c830032SChris Fraireorg.opengrok.indexer.web.Suggestion,
341c830032SChris Fraire
351c830032SChris Frairejava.util.List"
36a55b429eSAdam Hornáček%>
37aa6abf42SAdam Hornacek<%@ page import="jakarta.servlet.http.HttpServletRequest" %>
38aa6abf42SAdam Hornacek<%@ page import="jakarta.servlet.http.Cookie" %>
39c6f0939bSAdam Hornacek<%@ page import="java.nio.charset.StandardCharsets" %>
40a55b429eSAdam Hornáček<%
410d40e9d0SAdam Hornáček{
420d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
430d40e9d0SAdam Hornáček    cfg.checkSourceRootExistence();
440d40e9d0SAdam Hornáček}
450d40e9d0SAdam Hornáček%><%@
460d40e9d0SAdam Hornáček
470d40e9d0SAdam Hornáčekinclude file="projects.jspf"
480d40e9d0SAdam Hornáček
490d40e9d0SAdam Hornáček%><%!
500d40e9d0SAdam Hornáček    private StringBuilder createUrl(HttpServletRequest request, SearchHelper sh, boolean menu) {
510d40e9d0SAdam Hornáček        StringBuilder url = new StringBuilder(64);
520d40e9d0SAdam Hornáček        QueryBuilder qb = sh.builder;
530d40e9d0SAdam Hornáček        if (menu) {
540d40e9d0SAdam Hornáček            url.append("search?");
550d40e9d0SAdam Hornáček        } else {
561c830032SChris Fraire            Util.appendQuery(url, QueryParameters.SORT_PARAM, sh.order.toString());
570d40e9d0SAdam Hornáček        }
580d40e9d0SAdam Hornáček        if (qb != null) {
591c830032SChris Fraire            Util.appendQuery(url, QueryParameters.FULL_SEARCH_PARAM, qb.getFreetext());
601c830032SChris Fraire            Util.appendQuery(url, QueryParameters.DEFS_SEARCH_PARAM, qb.getDefs());
611c830032SChris Fraire            Util.appendQuery(url, QueryParameters.REFS_SEARCH_PARAM, qb.getRefs());
621c830032SChris Fraire            Util.appendQuery(url, QueryParameters.PATH_SEARCH_PARAM, qb.getPath());
631c830032SChris Fraire            Util.appendQuery(url, QueryParameters.HIST_SEARCH_PARAM, qb.getHist());
641c830032SChris Fraire            Util.appendQuery(url, QueryParameters.TYPE_SEARCH_PARAM, qb.getType());
650d40e9d0SAdam Hornáček        }
66*912cbfdfSAdam Hornacek        if (sh.projects != null && !sh.projects.isEmpty()) {
67*912cbfdfSAdam Hornacek            if (Boolean.parseBoolean(request.getParameter(QueryParameters.ALL_PROJECT_SEARCH))) {
68*912cbfdfSAdam Hornacek                Util.appendQuery(url, QueryParameters.ALL_PROJECT_SEARCH, Boolean.TRUE.toString());
69*912cbfdfSAdam Hornacek            } else {
701c830032SChris Fraire                Util.appendQuery(url, QueryParameters.PROJECT_SEARCH_PARAM,
711c830032SChris Fraire                        PageConfig.get(request).getRequestedProjectsAsString());
720d40e9d0SAdam Hornáček            }
73*912cbfdfSAdam Hornacek        }
740d40e9d0SAdam Hornáček        return url;
750d40e9d0SAdam Hornáček    }
760d40e9d0SAdam Hornáček%><%
770d40e9d0SAdam Hornáček/* ---------------------- search.jsp start --------------------- */
780d40e9d0SAdam Hornáček{
790d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
800d40e9d0SAdam Hornáček
810d40e9d0SAdam Hornáček    SearchHelper searchHelper = cfg.prepareSearch();
820d40e9d0SAdam Hornáček    // N.b. searchHelper.destroy() is called via
830d40e9d0SAdam Hornáček    // WebappListener.requestDestroyed() on presence of the following
840d40e9d0SAdam Hornáček    // REQUEST_ATTR.
850d40e9d0SAdam Hornáček    request.setAttribute(SearchHelper.REQUEST_ATTR, searchHelper);
860d40e9d0SAdam Hornáček    searchHelper.prepareExec(cfg.getRequestedProjects()).executeQuery().prepareSummary();
87a55b429eSAdam Hornáček    // notify suggester that query was searched
88a55b429eSAdam Hornáček    SuggesterServiceFactory.getDefault().onSearch(cfg.getRequestedProjects(), searchHelper.query);
890d40e9d0SAdam Hornáček    if (searchHelper.redirect != null) {
900d40e9d0SAdam Hornáček        response.sendRedirect(searchHelper.redirect);
91f045fcbeSChris Fraire        return;
920d40e9d0SAdam Hornáček    }
930d40e9d0SAdam Hornáček    if (searchHelper.errorMsg != null) {
940d40e9d0SAdam Hornáček        cfg.setTitle("Search Error");
950d40e9d0SAdam Hornáček        // Set status to Internal error. This should help to avoid caching
960d40e9d0SAdam Hornáček        // the page by some proxies.
970d40e9d0SAdam Hornáček        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
980d40e9d0SAdam Hornáček    } else {
990d40e9d0SAdam Hornáček        cfg.setTitle(cfg.getSearchTitle());
1000d40e9d0SAdam Hornáček    }
101c6f0939bSAdam Hornacek    response.addCookie(new Cookie("OpenGrokSorting", URLEncoder.encode(searchHelper.order.toString(), StandardCharsets.UTF_8)));
1020d40e9d0SAdam Hornáček}
1030d40e9d0SAdam Hornáček%><%@
1040d40e9d0SAdam Hornáček
1050d40e9d0SAdam Hornáčekinclude file="httpheader.jspf"
1060d40e9d0SAdam Hornáček
1070d40e9d0SAdam Hornáček%><body>
1080d40e9d0SAdam Hornáček<div id="page">
1090d40e9d0SAdam Hornáček    <div id="whole_header">
1100d40e9d0SAdam Hornáček        <div id="header"><%@
1110d40e9d0SAdam Hornáček
1120d40e9d0SAdam Hornáčekinclude file="pageheader.jspf"
1130d40e9d0SAdam Hornáček
1140d40e9d0SAdam Hornáček%>
1150d40e9d0SAdam Hornáček        </div>
1160d40e9d0SAdam Hornáček        <div id="Masthead">
1170d40e9d0SAdam Hornáček            <a href="<%= request.getContextPath() %>/"><span id="home"></span>Home</a>
1180d40e9d0SAdam Hornáček            <%-- TODO: jel: IMHO it should be move to menu.jspf as combobox --%>
1190d40e9d0SAdam Hornáček            <div id="sortfield">
1200d40e9d0SAdam Hornáček                <label for="sortby">Sort by</label>
1210d40e9d0SAdam Hornáček                <%
1220d40e9d0SAdam Hornáček{
1230d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
1240d40e9d0SAdam Hornáček    SearchHelper searchHelper = (SearchHelper) request.getAttribute(SearchHelper.REQUEST_ATTR);
1251c830032SChris Fraire    StringBuilder url = createUrl(request, searchHelper, true).append("&amp;").
1261c830032SChris Fraire            append(QueryParameters.SORT_PARAM_EQ);
1270d40e9d0SAdam Hornáček    int ordcnt = 0;
1280d40e9d0SAdam Hornáček    for (SortOrder o : SortOrder.values()) {
1290d40e9d0SAdam Hornáček        if (searchHelper.order == o) {
1300d40e9d0SAdam Hornáček                    %><span class="active"><%= o.getDesc() %></span><%
1310d40e9d0SAdam Hornáček        } else {
1320d40e9d0SAdam Hornáček                    %><a href="<%= url %><%= o %>"><%= o.getDesc() %></a><%
1330d40e9d0SAdam Hornáček        }
1340d40e9d0SAdam Hornáček        ordcnt++;
1350d40e9d0SAdam Hornáček        if (ordcnt != (SortOrder.values().length)) {
1360d40e9d0SAdam Hornáček            %> | <%
1370d40e9d0SAdam Hornáček        }
1380d40e9d0SAdam Hornáček    }
1390d40e9d0SAdam Hornáček}
1400d40e9d0SAdam Hornáček                %>
1410d40e9d0SAdam Hornáček            </div>
1420d40e9d0SAdam Hornáček        </div>
1430d40e9d0SAdam Hornáček        <div id="bar">
1440d40e9d0SAdam Hornáček        </div>
1450d40e9d0SAdam Hornáček        <div id="menu"><%@
1460d40e9d0SAdam Hornáček
1470d40e9d0SAdam Hornáčekinclude file="menu.jspf"
1480d40e9d0SAdam Hornáček
1490d40e9d0SAdam Hornáček%>
1500d40e9d0SAdam Hornáček        </div>
1510d40e9d0SAdam Hornáček    </div>
1520d40e9d0SAdam Hornáček
1530d40e9d0SAdam Hornáček    <div id="results"> <%
1540d40e9d0SAdam Hornáček{
1550d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
1560d40e9d0SAdam Hornáček    SearchHelper searchHelper = (SearchHelper) request.getAttribute(SearchHelper.REQUEST_ATTR);
1570d40e9d0SAdam Hornáček    // TODO spellchecking cycle below is not that great and we only create
1580d40e9d0SAdam Hornáček    // suggest links for every token in query, not for a query as whole
1590d40e9d0SAdam Hornáček    if (searchHelper.errorMsg != null) {
1600d40e9d0SAdam Hornáček        %><h3>Error</h3><p class="pagetitle"><%
1610d40e9d0SAdam Hornáček        if (searchHelper.errorMsg.startsWith((SearchHelper.PARSE_ERROR_MSG))) {
1620d40e9d0SAdam Hornáček            %><%= Util.htmlize(SearchHelper.PARSE_ERROR_MSG) %>
1630d40e9d0SAdam Hornáček            <br/>You might try to enclose your search term in quotes,
1640d40e9d0SAdam Hornáček            <a href="help.jsp#escaping">escape special characters</a>
1650d40e9d0SAdam Hornáček            with <b>\</b>, or read the <a href="help.jsp">Help</a>
1660d40e9d0SAdam Hornáček            on the query language. Error message from parser:<br/>
1670d40e9d0SAdam Hornáček            <%= Util.htmlize(searchHelper.errorMsg.substring(
1680d40e9d0SAdam Hornáček                        SearchHelper.PARSE_ERROR_MSG.length())) %><%
1690d40e9d0SAdam Hornáček        } else {
1700d40e9d0SAdam Hornáček            %><%= Util.htmlize(searchHelper.errorMsg) %><%
1710d40e9d0SAdam Hornáček        }%></p><%
1720d40e9d0SAdam Hornáček    } else if (searchHelper.hits == null) {
1730d40e9d0SAdam Hornáček        %><p class="pagetitle">No hits</p><%
1740d40e9d0SAdam Hornáček    } else if (searchHelper.hits.length == 0) {
1750d40e9d0SAdam Hornáček        List<Suggestion> hints = searchHelper.getSuggestions();
1760d40e9d0SAdam Hornáček        for (Suggestion hint : hints) {
1770d40e9d0SAdam Hornáček        %><p class="suggestions"><font color="#cc0000">Did you mean (for <%= hint.name %>)</font>:<%
1780d40e9d0SAdam Hornáček	  if (hint.freetext!=null) {
1790d40e9d0SAdam Hornáček	    for (String word : hint.freetext) {
1801c830032SChris Fraire            %> <a href="search?<%= QueryParameters.FULL_SEARCH_PARAM_EQ %>
1811c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%=
1820d40e9d0SAdam Hornáček                Util.htmlize(word) %></a> &nbsp; <%
1830d40e9d0SAdam Hornáček	    }
1840d40e9d0SAdam Hornáček	  }
1850d40e9d0SAdam Hornáček	  if (hint.refs!=null)  {
1860d40e9d0SAdam Hornáček	    for (String word : hint.refs) {
1871c830032SChris Fraire            %> <a href="search?<%= QueryParameters.REFS_SEARCH_PARAM_EQ %>
1881c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%=
1890d40e9d0SAdam Hornáček                Util.htmlize(word) %></a> &nbsp; <%
1900d40e9d0SAdam Hornáček	    }
1910d40e9d0SAdam Hornáček	  }
1920d40e9d0SAdam Hornáček	  if (hint.defs!=null) {
1930d40e9d0SAdam Hornáček	    for (String word : hint.defs) {
1941c830032SChris Fraire            %> <a href="search?<%= QueryParameters.DEFS_SEARCH_PARAM_EQ %>
1951c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%=
1960d40e9d0SAdam Hornáček                Util.htmlize(word) %></a> &nbsp; <%
1970d40e9d0SAdam Hornáček            }
1980d40e9d0SAdam Hornáček	  }
1990d40e9d0SAdam Hornáček        %></p><%
2000d40e9d0SAdam Hornáček        }
2010d40e9d0SAdam Hornáček        %>
2020d40e9d0SAdam Hornáček        <p class="pagetitle"> Your search <b><%
2030d40e9d0SAdam Hornáček            Util.htmlize(searchHelper.query.toString(), out); %></b>
2040d40e9d0SAdam Hornáček            did not match any files.
2050d40e9d0SAdam Hornáček            <br/> Suggestions:<br/>
2060d40e9d0SAdam Hornáček        </p>
2070d40e9d0SAdam Hornáček        <ul>
2080d40e9d0SAdam Hornáček            <li>Make sure all terms are spelled correctly.</li>
2090d40e9d0SAdam Hornáček            <li>Try different keywords.</li>
2100d40e9d0SAdam Hornáček            <li>Try more general keywords.</li>
2110d40e9d0SAdam Hornáček            <li>Use 'wil*' cards if you are looking for partial match.</li>
2120d40e9d0SAdam Hornáček        </ul>
2130d40e9d0SAdam Hornáček	<%
2140d40e9d0SAdam Hornáček    } else {
2150d40e9d0SAdam Hornáček        int start = searchHelper.start;
2160d40e9d0SAdam Hornáček        int max = searchHelper.maxItems;
2170d40e9d0SAdam Hornáček        long totalHits = searchHelper.totalHits;
2180d40e9d0SAdam Hornáček        long thispage = Math.min(totalHits - start, max);  // number of items to display on the current page
2190d40e9d0SAdam Hornáček        // We have a lots of results to show: create a slider for
2200d40e9d0SAdam Hornáček        String slider = Util.createSlider(start, max, totalHits, request);
2210d40e9d0SAdam Hornáček        %>
2220d40e9d0SAdam Hornáček        <p class="pagetitle">Searched <b><%
2230d40e9d0SAdam Hornáček            Util.htmlize(searchHelper.query.toString(), out);
224a804b2d7SAdam Hornáček            %></b> (Results <b> <%= start + 1 %> – <%= thispage + start
2250d40e9d0SAdam Hornáček            %></b> of <b><%= totalHits %></b>) sorted by <%=
2260d40e9d0SAdam Hornáček            searchHelper.order.getDesc() %></p><%
2270d40e9d0SAdam Hornáček        if (slider.length() > 0) {
2280d40e9d0SAdam Hornáček        %>
2290d40e9d0SAdam Hornáček        <p class="slider"><%= slider %></p><%
2300d40e9d0SAdam Hornáček        }
2310d40e9d0SAdam Hornáček        %>
2320d40e9d0SAdam Hornáček        <table><%
2330d40e9d0SAdam Hornáček        Results.prettyPrint(out, searchHelper, start, start + thispage);
2340d40e9d0SAdam Hornáček        %>
2350d40e9d0SAdam Hornáček        </table>
2367416c099SVladimir Kotal        <%
2370d40e9d0SAdam Hornáček        if (slider.length() > 0) {
2380d40e9d0SAdam Hornáček        %>
2390d40e9d0SAdam Hornáček        <p class="slider"><%= slider %></p><%
2400d40e9d0SAdam Hornáček        }
2410d40e9d0SAdam Hornáček        %>
2420d40e9d0SAdam Hornáček    </div><%
2430d40e9d0SAdam Hornáček    }
2440d40e9d0SAdam Hornáček    // Note that searchHelper.destroy() is called via WebappListener.requestDestroyed().
2450d40e9d0SAdam Hornáček}
2460d40e9d0SAdam Hornáček/* ---------------------- search.jsp end --------------------- */
2470d40e9d0SAdam Hornáček%><%@
2480d40e9d0SAdam Hornáček
2490d40e9d0SAdam Hornáčekinclude file="foot.jspf"
2500d40e9d0SAdam Hornáček
2510d40e9d0SAdam Hornáček%>
252