/** * Copyright (c) 2009--2014 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package com.redhat.rhn.frontend.action.help; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; import redstone.xmlrpc.XmlRpcClient; import redstone.xmlrpc.XmlRpcFault; import com.redhat.rhn.common.conf.ConfigDefaults; import com.redhat.rhn.common.validator.ValidatorException; import com.redhat.rhn.common.validator.ValidatorWarning; import com.redhat.rhn.frontend.action.BaseSearchAction; import com.redhat.rhn.frontend.context.Context; import com.redhat.rhn.frontend.dto.HelpDocumentOverview; import com.redhat.rhn.frontend.struts.RequestContext; import com.redhat.rhn.frontend.struts.RhnHelper; /** * DocSearchSetupAction * @version $Rev$ */ public class DocSearchSetupAction extends BaseSearchAction { private static Logger log = Logger.getLogger(DocSearchSetupAction.class); protected ActionForward doExecute(HttpServletRequest request, ActionMapping mapping, DynaActionForm form) throws MalformedURLException, XmlRpcFault { RequestContext ctx = new RequestContext(request); String searchString = form.getString(SEARCH_STR); String viewmode = form.getString(VIEW_MODE); List<Map<String, String>> searchOptions = new ArrayList<Map<String, String>>(); addOption(searchOptions, "docsearch.content_title", OPT_CONTENT_TITLE); addOption(searchOptions, "docsearch.free_form", OPT_FREE_FORM); addOption(searchOptions, "docsearch.content", OPT_CONTENT_ONLY); addOption(searchOptions, "docsearch.title", OPT_TITLE_ONLY); request.setAttribute(SEARCH_STR, searchString); request.setAttribute(VIEW_MODE, viewmode); request.setAttribute(SEARCH_OPT, searchOptions); if (!StringUtils.isBlank(searchString)) { List results = performSearch(ctx.getWebSession().getId(), searchString, viewmode, request); log.debug("GET search: " + results); request.setAttribute(RequestContext.PAGE_LIST, results != null ? results : Collections.emptyList()); } else { request.setAttribute(RequestContext.PAGE_LIST, Collections.emptyList()); } return mapping.findForward(RhnHelper.DEFAULT_FORWARD); } private List performSearch(Long sessionId, String searchString, String mode, HttpServletRequest request) throws XmlRpcFault, MalformedURLException { log.debug("Performing doc search"); // call search server XmlRpcClient client = new XmlRpcClient( ConfigDefaults.get().getSearchServerUrl(), true); List args = new ArrayList(); args.add(sessionId); args.add("docs"); args.add(preprocessSearchString(searchString, mode)); // get lang we are searching in Locale l = Context.getCurrentContext().getLocale(); args.add(l.toString()); Boolean searchFreeForm = false; if (OPT_FREE_FORM.equals(mode)) { // adding a boolean of true to signify we want the results to be // constrained to closer matches, this will force the Lucene Queries // to use a "MUST" instead of the default "SHOULD". It will not // allow fuzzy matches as in spelling errors, but it will allow // free form searches to do more advanced options //args.add(true); searchFreeForm = true; } args.add(searchFreeForm); List results = Collections.emptyList(); try { results = (List)client.invoke("index.search", args); } catch (XmlRpcFault e) { if (e.getErrorCode() == 200) { //This is most likely a language error //so lets try the search the default language //removing the 'lang' from the args args.remove(args.size() - 2); results = (List)client.invoke("index.search", args); List<ValidatorWarning> warnings = new LinkedList<ValidatorWarning>(); warnings.add(new ValidatorWarning ("packages.search.index_files_missing_for_docs")); getStrutsDelegate().saveMessages(request, Collections.EMPTY_LIST, warnings); } else { throw e; } } if (log.isDebugEnabled()) { log.debug("results = [" + results + "]"); } if (results.isEmpty()) { return Collections.emptyList(); } List<HelpDocumentOverview> docs = new ArrayList<HelpDocumentOverview>(); for (int x = 0; x < results.size(); x++) { HelpDocumentOverview doc = new HelpDocumentOverview(); Map item = (Map) results.get(x); log.debug("SearchServer sent us item [" + item.get("rank") + "], score = " + item.get("score") + ", summary = " + item.get("summary") + ", title = " + item.get("title") + ", url = " + item.get("url")); doc.setUrl((String)item.get("url")); doc.setTitle((String)item.get("title")); doc.setSummary((String)item.get("summary")); docs.add(doc); } return docs; } private String preprocessSearchString(String searchstring, String mode) { if (!OPT_FREE_FORM.equals(mode) && searchstring.indexOf(':') > 0) { throw new ValidatorException("Can't use free form and field search."); } StringBuilder buf = new StringBuilder(searchstring.length()); String[] tokens = searchstring.split(" "); for (String s : tokens) { if (s.trim().equalsIgnoreCase("AND") || s.trim().equalsIgnoreCase("OR") || s.trim().equalsIgnoreCase("NOT")) { s = s.toUpperCase(); } buf.append(s); buf.append(" "); } String query = buf.toString().trim(); // when searching the name field, we also want to include the filename // field in case the user passed in version number. if (OPT_CONTENT_ONLY.equals(mode)) { return "(content:(" + query + "))"; } else if (OPT_TITLE_ONLY.equals(mode)) { return "(title:(" + query + "))"; } else if (OPT_CONTENT_TITLE.equals(mode)) { return "(content:(" + query + ") title:(" + query + "))"; } // OPT_FREE_FORM send as is. return buf.toString(); } @Override protected void insureFormDefaults(HttpServletRequest request, DynaActionForm form) { String searchString = request.getParameter(SEARCH_STR); String viewmode = request.getParameter(VIEW_MODE); } }