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