All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sunlabs.brazil.handler.MultiHostHandler Maven / Gradle / Ivy

The newest version!
/*
 * MultiHostHandler.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 1999-2007 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version 
 * 1.0 (the "License"). You may not use this file except in compliance with 
 * the License. A copy of the License is included as the file "license.terms",
 * and also available at http://www.sun.com/
 * 
 * The Original Code is from:
 *    Brazil project web application toolkit release 2.3.
 * The Initial Developer of the Original Code is: cstevens.
 * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): cstevens, suhler.
 *
 * Version:  2.6
 * Created by cstevens on 99/11/03
 * Last modified by suhler on 07/01/29 15:35:18
 *
 * Version Histories:
 *
 * 2.6 07/01/29-15:35:18 (suhler)
 *   remove unused import
 *
 * 2.5 06/01/06-13:53:33 (suhler)
 *   - remove the "inherit" stuff, it wasn't correct.
 *   - add a "config" option to allow each virtual server to have it's
 *   own configuration file
 *   - integrate properly with PropertyLists, so each request gets (mostly) the
 *   right properties.
 *   - Factor the code so sub-classes can do wierd stuff with servers.
 *
 * 2.4 05/12/22-16:42:35 (suhler)
 *   doc fixes
 *
 * 2.3 05/12/22-16:17:19 (suhler)
 *   add "inherit" flag to allow each virtual host to have its own server properties
 *
 * 2.2 05/12/21-10:25:38 (suhler)
 *   - bug fix: port#'s were being included in host matching (not any more)
 *   - better diagnostics
 *
 * 2.1 02/10/01-16:36:36 (suhler)
 *   version change
 *
 * 1.7.1.1 02/04/18-11:13:41 (suhler)
 *   revert to previous behavior - maybe some other day
 *
 * 1.8 02/02/18-22:34:36 (suhler)
 *   allow virtual hosts to be glob patterns.  Although this implementation
 *   switches from O(0) to O(n) for finding the matching host, the number of
 *   hosts is expected to be small (a score or less).  If this proves not to
 *   be the case, then we'll re-examine this.
 *
 * 1.7 02/02/14-12:36:06 (suhler)
 *   bug introduced by last server.java change
 *
 * 1.6 01/06/13-09:29:02 (suhler)
 *   package move
 *
 * 1.5 00/12/11-13:28:26 (suhler)
 *   add class=props for automatic property extraction
 *
 * 1.4 00/05/24-11:26:06 (suhler)
 *   add docs
 *
 * 1.3 99/11/16-19:07:53 (cstevens)
 *   wildcard imports
 *
 * 1.2 99/11/09-20:23:18 (cstevens)
 *   bugs revealed by writing tests.
 *
 * 1.2 99/11/03-17:51:52 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 1 0 handlers/MultiHostHandler.java
 *
 * 1.1 99/11/03-17:51:51 (cstevens)
 *   date and time created 99/11/03 17:51:51 by cstevens
 *
 */

package sunlabs.brazil.handler;

import java.io.IOException;
import java.io.File;
import java.io.InputStream;
import sunlabs.brazil.server.FileHandler;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.util.Glob;
import sunlabs.brazil.properties.PropertiesList;
import java.util.Vector;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 * The MultiHostHandler allows the user to handle a set
 * of host names that are all running on the same IP address.  This
 * handler looks at the http "Host" header and redispatches the request to the
 * appropriate sub-server.
 * 

* Only the main server is actually listening to the port on the specified IP * address. The sub-servers are not running in separate threads. Indeed, * they are not "running" at all. They exist merely as a convenient bag to * hold each of the server-specific configuration parameters. *

* The respond method of the main handler for the appropriate * sub-server is called directly from the respond method of * this handler. *

* This handler uses the following configuration parameters:

* *
servers *
The list of prefixes for the other servers. Each server will be * initialized from the main server.props with the * specified prefix. In this way, the configuration parameters for * all the sub-servers can be stored in the same Properties * object. * *
prefix.host *
Each server is started with a given prefix. The property * prefix.host specifies a Glob pattern for a virtual hostname * the server * will be expected to handle. If this property is not specified, * the server's virtual hostname will just be prefix. * If multiple host patterns could match a given "Host" header, * the first match in the "servers" list matches first. * *
prefix.handler *
The main handler for the server with the given prefix. If * this property is not specified, it defaults to the * FileHandler. * *
prefix.config *
Read in the file specified by "config" to initialize this sub-server's * server properties. The file is expected to be in java properties * format. If not specified, this sub-server shares a copy * of the main server's properties, otherwise, the main server's properties * are used as the "default". If this property is specified and no * config file is found, then the sub-server isn't started. *

* The property "root", if included in the "config" file, is treated * specially: If it does not represent an absolute path, then it is * resolved relative to the main server's root. *

* *
prefix.log *
The log level for the server with the given prefix. If this * property is not specified, it defaults to the log level of the * parent server. * * * A sample set of configuration parameters illustrating how to use this * handler follows: *
 * handler=host
 * port=8081
 * log=5
 * 
 * host.class=sunlabs.brazil.server.MultiHostHandler
 * host.servers=mars jupiter saturn
 * 
 * mars.host=www.mars.com
 * mars.log=2
 * mars.handler=mars.file
 * mars.file.class=sunlabs.brazil.server.FileHandler
 * mars.file.root=public_html/mars
 * 
 * jupiter.host=jupiter.planet.org
 * jupiter.handler=sunlabs.brazil.server.FileHandler
 * jupiter.root=public_html/jupiter
 * 
 * saturn.host=*.saturn.planet.org
 * saturn.handler=sunlabs.brazil.server.FileHandler
 * saturn.root=public_html/saturn
 * 
* These parameters set up a normal Server on port 8081, * running a MultiHostHandler. The MultiHostHandler * will create three additional servers that respond to the virtual hosts * "www.mars.com", "jupiter.planet.org", and ".saturn.planet.org". The * "mars" server will have a Server.prefix of "mars", * so that all other configuration parameters that the "mars" server * examines can begin with "mars" and be kept distinct from the "jupiter" * and "saturn" parameters. *

* The main server and the three sub-servers will all share the * same properties object, but can use their own individual prefixes to * keep their data separate (because "inherit" is not set). *

* * @author Colin Stevens ([email protected]) * @version 2.6, 07/01/29 */ public class MultiHostHandler implements Handler { String prefix; private Vector servers = new Vector(); /** * Initializes the servers for the virtual hosts. After creating * and initializing each sub-server, the init method of the * main handler for each sub-server is called. * * @param server * The HTTP server that created this handler. * * @param prefix * A prefix to prepend to all of the keys that this * handler uses to extract configuration information. * * @return true if at least one sub-server was found and * could be initialized, false otherwise. * Diagnostic messages are logged for each sub-server started. */ public boolean init(Server server, String prefix) { this.prefix = prefix; Properties props = server.props; String list = props.getProperty(prefix + "servers", ""); StringTokenizer st = new StringTokenizer(list); while (st.hasMoreTokens()) { String name = st.nextToken(); server.log(Server.LOG_DIAGNOSTIC, prefix, "creating subserver " + name); Server sub = subServer(server, name); if (sub!=null && sub.init()) { servers.addElement(new Host(sub.hostName, sub)); } } return (servers.size() > 0); } /* * Create a sub-server. * @param main: The main server * @param name: name of the sub-server */ Server subServer(Server main, String name) { Properties props = main.props; String handler = props.getProperty(name + ".handler", FileHandler.class.getName()); String config = props.getProperty(name + ".config"); if (config != null) { try { InputStream in = ResourceHandler.getResourceStream(props, "", config); props = new Properties(props); props.load(in); in.close(); main.log(Server.LOG_DIAGNOSTIC, name, "Fetching config file: " + config + " for " + name); } catch (IOException e) { main.log(Server.LOG_WARNING, name, "Can't find config (" + config + ") for (" + name + ")"); return null; } // fix up the root String mainroot = main.props.getProperty("root","."); String root = (String)props.get("root"); if (root != null) { File froot = new File(root); if (!froot.isAbsolute()) { froot = new File(mainroot, root); } props.put("root", froot.getPath()); main.log(Server.LOG_DIAGNOSTIC, name, "Setting root for: " + name + " to " + froot.getPath()); } } Server sub = new Server(main.listen, handler, props); sub.hostName = props.getProperty(name + ".host", name); sub.prefix = name; if (!name.endsWith(".")) { sub.prefix += "."; } try { String str = props.getProperty(name + ".log"); sub.logLevel = Integer.decode(str).intValue(); } catch (Exception e) { sub.logLevel = main.logLevel; } sub.maxRequests = main.maxRequests; sub.timeout = main.timeout; return sub; } /** * Responds to an HTTP request by examining the "Host:" request header * and dispatching to the main handler of the server that handles * that virtual host. If the "Host:" request header was not specified, * or named a virtual host that was not initialized in init * from the list of virtual hosts, this method returns without * handling the request. Port numbers are not used for host matching. * * @param request * The HTTP request to be forwarded to one of the sub-servers. * * @return true if the sub-server handled the message, * false if it did not. false is * also returned if the "Host:" was unspecified or unknown. */ public boolean respond(Request request) throws IOException { String host = request.getRequestHeader("Host"); Server orig = request.server; if (host == null) { return false; } int idx = host.indexOf(":"); if (idx > 0) { host = host.substring(0, idx); } for(int i=0;i



© 2015 - 2024 Weber Informatics LLC | Privacy Policy