📄 searchservlet.java
字号:
/* -*- mode:java; indent-tabs-mode:nil; c-basic-offset:2 -*- * * $RCSfile: SearchServlet.java,v $ $Revision: 1.225 $ $Date: 2006/02/06 21:26:45 $ * * Copyright 2000-2006 Autonomy Corp. All Rights Reserved. * Permission to use, copy, modify, and distribute this file is hereby * granted without fee, provided that the above copyright notice appear * in all copies. */import java.io.*;import java.net.*;import java.text.DateFormat;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;import com.ultraseek.xpa.ldap.*;import com.ultraseek.xpa.search.*;import com.ultraseek.xpa.server.*;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;/** * A Servlet that provides a full-featured web search interface to any * selection of Searchables. To configure this Servlet for your * installation, all you have to do is specialize the * <code>SearchServlet</code> class, overriding the initSearchMenu() * and initUltraseek() methods with your own code. * <p> * This servlet requires version 2.2 of the HttpServlet specification. * <p> * Differences from the standard Ultraseek search interface. * <ul> * <li>No "help" link on search box. * <li>Ad Top / Ad Bottom not supported * <li>"Score using date" - results may not exactly match Python * search, due to different re-scoring window sizes between XPA * and the Ultraseek server. * <li>Result Icons are not supported * <li>Collections are supported via a drop-down menu, instead of * checkoff boxes. * </ul> * See <code>MyServlet</code>, <code>LDAPServlet</code> * and <code>LoginServlet</code> for * examples of how to customize <code>SearchServlet</code> for your * site. * <p> * Many customizations can be made by use of display styles * introduced in Ultraseek 5.1. * The <code>SearchServlet</code> uses settings and style * sheets defined in the Ultraseek administration interface. * <p> * Ultraseek recommends you customize <code>SearchServlet</code> * first via the Ultraseek style editor, * and then by extending the <code>SearchServlet</code> class * and overriding methods. Your customizations * will then more easily migrate to future revisions * of Ultraseek server and XPA. * <p> * If modification of <code>SearchServlet</code> is necessary to * make your customizations, we recommend you submit * your <code>SearchServlet</code> modifications to Ultraseek * support for possible inclusion in future XPA releases. * * @author Ultraseek Engineering * @version 2.3.0 * @since XPA1.0.6 * @requires Servlet 2.2 * @serial exclude */public class SearchServlet extends HttpServlet { ServletConfig servletConfig; protected UltraseekServer ultraseek = null; // Diagostic logging private static Log diagnosticLog = LogFactory.getLog(SearchServlet.class); /** * Initialization done on first load of the Servlet. */ public void init(ServletConfig config) throws ServletException { super.init(config); servletConfig = config; checkServletEnvironmentVersion(); configuration.update(); } /** * The Major version of the Servlet specification that this * servlet requires for correct functionality. * @see #checkServletEnvironmentVersion * @see #REQUIRED_SERVLET_VERSION_MINOR */ protected static final int REQUIRED_SERVLET_VERSION_MAJOR = 2; /** * The Minor version of the Servlet specification that this * servlet requires for correct functionality. * @see #checkServletEnvironmentVersion * @see #REQUIRED_SERVLET_VERSION_MAJOR */ protected static final int REQUIRED_SERVLET_VERSION_MINOR = 2; /** * Called during init to check the runtime servlet version. * @throws ServletException if the environment does not support the required * servlet version. * @see #REQUIRED_SERVLET_VERSION_MAJOR * @see #REQUIRED_SERVLET_VERSION_MINOR */ protected void checkServletEnvironmentVersion() throws ServletException { ServletConfig sconfig = getServletConfig(); ServletContext scontext = sconfig.getServletContext(); if (scontext.getMajorVersion() > REQUIRED_SERVLET_VERSION_MAJOR) return; if (scontext.getMajorVersion() == REQUIRED_SERVLET_VERSION_MAJOR && scontext.getMinorVersion() >= REQUIRED_SERVLET_VERSION_MINOR) return; throw new ServletException(this.getClass().getName() + " requires Servlet version " + REQUIRED_SERVLET_VERSION_MAJOR + "." + REQUIRED_SERVLET_VERSION_MINOR + " found " + scontext.getMajorVersion() + "." + scontext.getMinorVersion() + " (" + scontext.getServerInfo() + ")" ); } public String getServletInfo() { return SearchServlet.class.getName() + " Version 2.3.0\n" + "Copyright 2000-2006 Autonomy Corp. All Rights Reserved.\n" + "Permission to use, copy, modify, and distribute this file is hereby\n" + "granted without fee, provided that the above copyright notice appear\n" + "in all copies.\n" + "$RCSfile: SearchServlet.java,v $ $Revision: 1.225 $ $Date: 2006/02/06 21:26:45 $\n"; } /** * Amount of time, in millis, that the client browser is allowed to cache * a page of search results. * <p> * Setting to 0 will specify no caching. * While this value is defined in milliseconds, the client browser uses * 1 second resolution for caching. * <p> * Default value is 3000 (3 seconds). * @see SearchRequest#setCaching */ protected long CLIENT_CACHE_INTERVAL = 3000; /** * Specify how often to flush query results to the output stream. * If a large number of hits are being sent (nh >= 25), it's possible * for a long time period to elapse before the browser will start * displaying hits. * <p> * Set to 0 to prevent periodic flushing of the output buffer. * <p> * Default setting is to flush every 30 search results. */ protected int FLUSH_RESULTS_INTERVAL = 30; class Configuration { private long timestamp = -1; private boolean reloading = false; private final boolean needUpdate() { if (reloading) return false; if (ultraseek==null) return true; if (timestamp >= ultraseek.getConfigurationTimestamp()) return false; return true; } public void maybeUpdate() { if (!needUpdate()) return; synchronized (this) { if (!needUpdate()) return; reloading = true; } try { // REMIND: perhaps this should be done in a separate thread log( "Updating configuration from Ultraseek server at " + ultraseek.getURL() ); update(); } catch (ServletException e) { log( "Problem updating configuration", e ); }; } public void reset() { timestamp = -1; } public synchronized void update() throws ServletException { reloading = true; try { // Timestamp of when we started update long newTimestamp = -1; if (ultraseek!=null) newTimestamp = ultraseek.getConfigurationTimestamp(); try { reinitialize(); if (newTimestamp==-1 && ultraseek!=null && ultraseek.getConfigurationTimestamp() > 0) newTimestamp = ultraseek.getConfigurationTimestamp(); // Sucessful load - set the new configuration info timestamp = newTimestamp; } catch (ServletException e) { throw e; } catch (IOException e) { log( "Unable to update configuration", e); // We'll retry configuration.update later } catch (Exception e) { log( "Initialization Error", e ); throw new ServletException(e.getLocalizedMessage(),e); } } finally { reloading = false; } } } protected Configuration configuration = new Configuration(); /** * Return the URL for the Ultraseek search server. * Only the protocol, hostname, and port are used in the URL. * @see #initUltraseek */ protected URL getUltraseekURL() throws ServletException { // This is a sample implementation. // These values are coming from Servlet Context init variables, // set in the web.xml file. // Use your own Servlet Container's approach. String serverName = getServletConfig().getInitParameter("ServerName"); String serverPort = getServletConfig().getInitParameter("ServerPort"); String serverProtocol = getServletConfig().getInitParameter("ServerProtocol"); // For demo purposes, use localhost if no server specified if (serverName==null) serverName = "localhost"; if (serverPort==null) serverPort = "8765"; if (serverProtocol==null) serverProtocol = "http"; String where = serverProtocol+"://"+serverName+":"+serverPort; try { return new URL(where); } catch (MalformedURLException e) { throw new ServletException("Malformed Ultraseek server locator: " + where, e); } } /** * Re-initialize the Ultraseek server used for administration * options. * @throws IOException if unable to contact remote Ultraseek server */ protected void initUltraseek() throws IOException, ServletException { URL ultraseekURL = getUltraseekURL(); if (ultraseekURL==null) throw new ServletException("getUltraseekURL() returned null"); String serverName = ultraseekURL.getHost(); String serverProtocol = ultraseekURL.getProtocol(); int serverPort = ultraseekURL.getPort(); if (serverPort==-1) { // For JDK 1.4 use the following // serverPort = ultraseekURL.getDefaultPort(); // For JDK 1.3 use the following if (serverProtocol.equalsIgnoreCase("http")) serverPort = 80; if (serverProtocol.equalsIgnoreCase("https")) serverPort = 443; } // Get a new UltraseekServer object if the servlet has changed configuration if (ultraseek==null || !serverProtocol.equalsIgnoreCase(ultraseek.getProtocol()) || !serverName.equals(ultraseek.getHost()) || !(serverPort==ultraseek.getPort())) { UltraseekServer s = new UltraseekServer(serverName, serverPort, serverProtocol); // If we don't have a server, the new UltraseekServer is it if (ultraseek==null) { ultraseek = s; configuration.reset(); } // Force a connection to ensure the server is responding try { String version = s.getVersionString(); // Server is accessible, so it becomes the new "ultraseek" ultraseek = s; configuration.reset(); } catch (IOException e) { log("Unable to connect to " + s.toString(), e ); throw e; } } } /** * Returns the <code>QueryLog</code> to use for logging user queries. * <p> * By default, the UltraseekServer instance is used for the query log. * @return the QueryLog to use, or <code>null</code> if no logging to be performed. * @see SearchRequest#postResponseHandling * @since XPA2.2 */ protected QueryLog getQueryLogger() { return ultraseek; } protected class SearchMenuItem { String ID; // Internal ID String displayName; // Visible name SearchServer server; // search server being searched Searchable searchable; // The object to search (may include filtering & processing) SpellServer speller; // may be null if speller not supported Searchable quickLinks; // for Quick Links, may be null SearchMenuItem(String ID) { if (ID == null) throw new IllegalArgumentException("ID must be non-null"); this.ID = ID; } SearchMenuItem(String ID, String displayName, SearchServer server, Searchable searchable, SpellServer speller, Searchable quickLinks) { this(ID); this.displayName = displayName; this.server = server; this.searchable = searchable; this.speller = speller; this.quickLinks = quickLinks; } public String toString() { StringBuffer sb = new StringBuffer(256); sb.append( this.getClass().getName() ); sb.append( "(" ); sb.append( this.ID ); sb.append( "," ); sb.append( this.displayName ); sb.append( "," ); sb.append( ""+this.server ); sb.append( "," );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -