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); 52*ae1c323bSVladimir Kotal QueryBuilder qb = sh.getBuilder(); 530d40e9d0SAdam Hornáček if (menu) { 540d40e9d0SAdam Hornáček url.append("search?"); 550d40e9d0SAdam Hornáček } else { 56*ae1c323bSVladimir Kotal Util.appendQuery(url, QueryParameters.SORT_PARAM, sh.getOrder().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*ae1c323bSVladimir Kotal if (sh.getProjects() != null && !sh.getProjects().isEmpty()) { 67912cbfdfSAdam Hornacek if (Boolean.parseBoolean(request.getParameter(QueryParameters.ALL_PROJECT_SEARCH))) { 68912cbfdfSAdam Hornacek Util.appendQuery(url, QueryParameters.ALL_PROJECT_SEARCH, Boolean.TRUE.toString()); 69912cbfdfSAdam Hornacek } else { 701c830032SChris Fraire Util.appendQuery(url, QueryParameters.PROJECT_SEARCH_PARAM, 711c830032SChris Fraire PageConfig.get(request).getRequestedProjectsAsString()); 720d40e9d0SAdam Hornáček } 73912cbfdfSAdam 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 88*ae1c323bSVladimir Kotal SuggesterServiceFactory.getDefault().onSearch(cfg.getRequestedProjects(), searchHelper.getQuery()); 89*ae1c323bSVladimir Kotal String redirect = searchHelper.getRedirect(); 90*ae1c323bSVladimir Kotal if (redirect != null) { 91*ae1c323bSVladimir Kotal response.sendRedirect(redirect); 92f045fcbeSChris Fraire return; 930d40e9d0SAdam Hornáček } 94*ae1c323bSVladimir Kotal if (searchHelper.getErrorMsg() != null) { 950d40e9d0SAdam Hornáček cfg.setTitle("Search Error"); 960d40e9d0SAdam Hornáček // Set status to Internal error. This should help to avoid caching 970d40e9d0SAdam Hornáček // the page by some proxies. 980d40e9d0SAdam Hornáček response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 990d40e9d0SAdam Hornáček } else { 1000d40e9d0SAdam Hornáček cfg.setTitle(cfg.getSearchTitle()); 1010d40e9d0SAdam Hornáček } 102*ae1c323bSVladimir Kotal response.addCookie(new Cookie("OpenGrokSorting", 103*ae1c323bSVladimir Kotal URLEncoder.encode(searchHelper.getOrder().toString(), StandardCharsets.UTF_8))); 1040d40e9d0SAdam Hornáček} 1050d40e9d0SAdam Hornáček%><%@ 1060d40e9d0SAdam Hornáček 1070d40e9d0SAdam Hornáčekinclude file="httpheader.jspf" 1080d40e9d0SAdam Hornáček 1090d40e9d0SAdam Hornáček%><body> 1100d40e9d0SAdam Hornáček<div id="page"> 111aa18fa28SAdam Hornacek <header id="whole_header"> 112aa18fa28SAdam Hornacek <%@include file="pageheader.jspf" %> 1130d40e9d0SAdam Hornáček <div id="Masthead"> 1140d40e9d0SAdam Hornáček <a href="<%= request.getContextPath() %>/"><span id="home"></span>Home</a> 1150d40e9d0SAdam Hornáček <%-- TODO: jel: IMHO it should be move to menu.jspf as combobox --%> 1160d40e9d0SAdam Hornáček <div id="sortfield"> 1170d40e9d0SAdam Hornáček <label for="sortby">Sort by</label> 1180d40e9d0SAdam Hornáček <% 1190d40e9d0SAdam Hornáček{ 1200d40e9d0SAdam Hornáček PageConfig cfg = PageConfig.get(request); 1210d40e9d0SAdam Hornáček SearchHelper searchHelper = (SearchHelper) request.getAttribute(SearchHelper.REQUEST_ATTR); 1221c830032SChris Fraire StringBuilder url = createUrl(request, searchHelper, true).append("&"). 1231c830032SChris Fraire append(QueryParameters.SORT_PARAM_EQ); 1240d40e9d0SAdam Hornáček int ordcnt = 0; 1250d40e9d0SAdam Hornáček for (SortOrder o : SortOrder.values()) { 126*ae1c323bSVladimir Kotal if (searchHelper.getOrder() == o) { 1270d40e9d0SAdam Hornáček %><span class="active"><%= o.getDesc() %></span><% 1280d40e9d0SAdam Hornáček } else { 1290d40e9d0SAdam Hornáček %><a href="<%= url %><%= o %>"><%= o.getDesc() %></a><% 1300d40e9d0SAdam Hornáček } 1310d40e9d0SAdam Hornáček ordcnt++; 1320d40e9d0SAdam Hornáček if (ordcnt != (SortOrder.values().length)) { 1330d40e9d0SAdam Hornáček %> | <% 1340d40e9d0SAdam Hornáček } 1350d40e9d0SAdam Hornáček } 1360d40e9d0SAdam Hornáček} 1370d40e9d0SAdam Hornáček %> 1380d40e9d0SAdam Hornáček </div> 1390d40e9d0SAdam Hornáček </div> 1400d40e9d0SAdam Hornáček <div id="bar"> 1410d40e9d0SAdam Hornáček </div> 1420d40e9d0SAdam Hornáček <div id="menu"><%@ 1430d40e9d0SAdam Hornáček 1440d40e9d0SAdam Hornáčekinclude file="menu.jspf" 1450d40e9d0SAdam Hornáček 1460d40e9d0SAdam Hornáček%> 1470d40e9d0SAdam Hornáček </div> 148aa18fa28SAdam Hornacek </header> 1490d40e9d0SAdam Hornáček 1500d40e9d0SAdam Hornáček <div id="results"> <% 1510d40e9d0SAdam Hornáček{ 1520d40e9d0SAdam Hornáček PageConfig cfg = PageConfig.get(request); 1530d40e9d0SAdam Hornáček SearchHelper searchHelper = (SearchHelper) request.getAttribute(SearchHelper.REQUEST_ATTR); 1540d40e9d0SAdam Hornáček // TODO spellchecking cycle below is not that great and we only create 1550d40e9d0SAdam Hornáček // suggest links for every token in query, not for a query as whole 156*ae1c323bSVladimir Kotal String errorMsg = searchHelper.getErrorMsg(); 157*ae1c323bSVladimir Kotal if (errorMsg != null) { 1580d40e9d0SAdam Hornáček %><h3>Error</h3><p class="pagetitle"><% 159*ae1c323bSVladimir Kotal if (searchHelper.getErrorMsg().startsWith((SearchHelper.PARSE_ERROR_MSG))) { 1600d40e9d0SAdam Hornáček %><%= Util.htmlize(SearchHelper.PARSE_ERROR_MSG) %> 1610d40e9d0SAdam Hornáček <br/>You might try to enclose your search term in quotes, 1620d40e9d0SAdam Hornáček <a href="help.jsp#escaping">escape special characters</a> 1630d40e9d0SAdam Hornáček with <b>\</b>, or read the <a href="help.jsp">Help</a> 1640d40e9d0SAdam Hornáček on the query language. Error message from parser:<br/> 165*ae1c323bSVladimir Kotal <%= Util.htmlize(errorMsg.substring(SearchHelper.PARSE_ERROR_MSG.length())) %><% 1660d40e9d0SAdam Hornáček } else { 167*ae1c323bSVladimir Kotal %><%= Util.htmlize(errorMsg) %><% 1680d40e9d0SAdam Hornáček }%></p><% 169*ae1c323bSVladimir Kotal } else if (searchHelper.getHits() == null) { 1700d40e9d0SAdam Hornáček %><p class="pagetitle">No hits</p><% 171*ae1c323bSVladimir Kotal } else if (searchHelper.getHits().length == 0) { 1720d40e9d0SAdam Hornáček List<Suggestion> hints = searchHelper.getSuggestions(); 1730d40e9d0SAdam Hornáček for (Suggestion hint : hints) { 17468076d3cSVladimir Kotal %><p class="suggestions"><font color="#cc0000">Did you mean (for <%= hint.getName() %>)</font>:<% 17568076d3cSVladimir Kotal if (hint.getFreetext() != null) { 17668076d3cSVladimir Kotal for (String word : hint.getFreetext()) { 1771c830032SChris Fraire %> <a href="search?<%= QueryParameters.FULL_SEARCH_PARAM_EQ %> 1781c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%= 1790d40e9d0SAdam Hornáček Util.htmlize(word) %></a> <% 1800d40e9d0SAdam Hornáček } 1810d40e9d0SAdam Hornáček } 18268076d3cSVladimir Kotal if (hint.getRefs() != null) { 18368076d3cSVladimir Kotal for (String word : hint.getRefs()) { 1841c830032SChris Fraire %> <a href="search?<%= QueryParameters.REFS_SEARCH_PARAM_EQ %> 1851c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%= 1860d40e9d0SAdam Hornáček Util.htmlize(word) %></a> <% 1870d40e9d0SAdam Hornáček } 1880d40e9d0SAdam Hornáček } 18968076d3cSVladimir Kotal if (hint.getDefs() != null) { 19068076d3cSVladimir Kotal for (String word : hint.getDefs()) { 1911c830032SChris Fraire %> <a href="search?<%= QueryParameters.DEFS_SEARCH_PARAM_EQ %> 1921c830032SChris Fraire<%= Util.URIEncode(QueryParser.escape(word)) %>"><%= 1930d40e9d0SAdam Hornáček Util.htmlize(word) %></a> <% 1940d40e9d0SAdam Hornáček } 1950d40e9d0SAdam Hornáček } 1960d40e9d0SAdam Hornáček %></p><% 1970d40e9d0SAdam Hornáček } 1980d40e9d0SAdam Hornáček %> 1990d40e9d0SAdam Hornáček <p class="pagetitle"> Your search <b><% 200*ae1c323bSVladimir Kotal Util.htmlize(searchHelper.getQuery().toString(), out); %></b> 2010d40e9d0SAdam Hornáček did not match any files. 2020d40e9d0SAdam Hornáček <br/> Suggestions:<br/> 2030d40e9d0SAdam Hornáček </p> 2040d40e9d0SAdam Hornáček <ul> 2050d40e9d0SAdam Hornáček <li>Make sure all terms are spelled correctly.</li> 2060d40e9d0SAdam Hornáček <li>Try different keywords.</li> 2070d40e9d0SAdam Hornáček <li>Try more general keywords.</li> 2080d40e9d0SAdam Hornáček <li>Use 'wil*' cards if you are looking for partial match.</li> 2090d40e9d0SAdam Hornáček </ul> 2100d40e9d0SAdam Hornáček <% 2110d40e9d0SAdam Hornáček } else { 212*ae1c323bSVladimir Kotal int start = searchHelper.getStart(); 213*ae1c323bSVladimir Kotal int max = searchHelper.getMaxItems(); 214*ae1c323bSVladimir Kotal long totalHits = searchHelper.getTotalHits(); 2150d40e9d0SAdam Hornáček long thispage = Math.min(totalHits - start, max); // number of items to display on the current page 2160d40e9d0SAdam Hornáček // We have a lots of results to show: create a slider for 2170d40e9d0SAdam Hornáček String slider = Util.createSlider(start, max, totalHits, request); 2180d40e9d0SAdam Hornáček %> 2190d40e9d0SAdam Hornáček <p class="pagetitle">Searched <b><% 220*ae1c323bSVladimir Kotal Util.htmlize(searchHelper.getQuery().toString(), out); 221a804b2d7SAdam Hornáček %></b> (Results <b> <%= start + 1 %> – <%= thispage + start 2220d40e9d0SAdam Hornáček %></b> of <b><%= totalHits %></b>) sorted by <%= 223*ae1c323bSVladimir Kotal searchHelper.getOrder().getDesc() %></p><% 2240d40e9d0SAdam Hornáček if (slider.length() > 0) { 2250d40e9d0SAdam Hornáček %> 2260d40e9d0SAdam Hornáček <p class="slider"><%= slider %></p><% 2270d40e9d0SAdam Hornáček } 2280d40e9d0SAdam Hornáček %> 2290d40e9d0SAdam Hornáček <table><% 2300d40e9d0SAdam Hornáček Results.prettyPrint(out, searchHelper, start, start + thispage); 2310d40e9d0SAdam Hornáček %> 2320d40e9d0SAdam Hornáček </table> 2337416c099SVladimir Kotal <% 2340d40e9d0SAdam Hornáček if (slider.length() > 0) { 2350d40e9d0SAdam Hornáček %> 2360d40e9d0SAdam Hornáček <p class="slider"><%= slider %></p><% 2370d40e9d0SAdam Hornáček } 2380d40e9d0SAdam Hornáček %> 2390d40e9d0SAdam Hornáček </div><% 2400d40e9d0SAdam Hornáček } 2410d40e9d0SAdam Hornáček // Note that searchHelper.destroy() is called via WebappListener.requestDestroyed(). 2420d40e9d0SAdam Hornáček} 2430d40e9d0SAdam Hornáček/* ---------------------- search.jsp end --------------------- */ 2440d40e9d0SAdam Hornáček%><%@ 2450d40e9d0SAdam Hornáček 2460d40e9d0SAdam Hornáčekinclude file="foot.jspf" 2470d40e9d0SAdam Hornáček 2480d40e9d0SAdam Hornáček%> 249