001// Copyright (C) 1998-2001 by Jason Hunter <jhunter_AT_acm_DOT_org>. 002// All rights reserved. Use of this class is limited. 003// Please see the LICENSE for more information. 004 005package com.oreilly.servlet; 006 007import java.io.*; 008import java.net.*; 009import java.rmi.*; 010import java.rmi.server.*; 011import java.rmi.registry.*; 012import java.util.*; 013import javax.servlet.*; 014import javax.servlet.http.*; 015 016 017/** 018 * A superclass for any HTTP servlet that wishes to act as an RMI server. 019 * RemoteHttpServlet begins listening for RMI calls in its 020 * <tt>init()</tt> method and stops listening in its <tt>destroy()</tt> 021 * method. To register itself it uses the registry on the local machine 022 * on the port determined by <tt>getRegistryPort()</tt>. It registers 023 * under the name determined by <tt>getRegistryName()</tt>. 024 * 025 * @see com.oreilly.servlet.RemoteDaemonHttpServlet 026 * 027 * @author <b>Jason Hunter</b>, Copyright © 1998 028 * @version 1.0, 98/09/18 029 */ 030public abstract class RemoteHttpServlet extends HttpServlet 031 implements Remote { 032 /** 033 * The registry for the servlet 034 */ 035 protected Registry registry; 036 037 /** 038 * Begins the servlet's RMI operations. Causes the servlet to export 039 * itself and then bind itself to the registry. Logs any errors. 040 * Subclasses that override this method must be sure to first call 041 * <tt>super.init(config)</tt>. 042 * 043 * @param config the servlet config 044 * @exception ServletException if a servlet exception occurs 045 */ 046 public void init(ServletConfig config) throws ServletException { 047 super.init(config); 048 try { 049 UnicastRemoteObject.exportObject(this); 050 bind(); 051 } 052 catch (RemoteException e) { 053 log("Problem binding to RMI registry: " + e.getMessage()); 054 } 055 } 056 057 /** 058 * Halts the servlet's RMI operations. Causes the servlet to 059 * unbind itself from the registry. Logs any errors. Subclasses that 060 * override this method must be sure to first call <tt>super.destroy()</tt>. 061 */ 062 public void destroy() { 063 unbind(); 064 } 065 066 /** 067 * Returns the name under which the servlet should be bound in the 068 * registry. By default the name is the servlet's class name. This 069 * can be overridden with the <tt>registryName</tt> init parameter. 070 * 071 * @return the name under which the servlet should be bound in the registry 072 */ 073 protected String getRegistryName() { 074 // First name choice is the "registryName" init parameter 075 String name = getInitParameter("registryName"); 076 if (name != null) return name; 077 078 // Fallback choice is the name of this class 079 return this.getClass().getName(); 080 } 081 082 /** 083 * Returns the port where the registry should be running. By default 084 * the port is the default registry port (1099). This can be 085 * overridden with the <tt>registryPort</tt> init parameter. 086 * 087 * @return the port for the registry 088 */ 089 protected int getRegistryPort() { 090 // First port choice is the "registryPort" init parameter 091 try { return Integer.parseInt(getInitParameter("registryPort")); } 092 093 // Fallback choice is the default registry port (1099) 094 catch (NumberFormatException e) { return Registry.REGISTRY_PORT; } 095 } 096 097 /** 098 * Binds the servlet to the registry. Creates the registry if necessary. 099 * Logs any errors. 100 */ 101 protected void bind() { 102 // Try to find the appropriate registry already running 103 try { 104 registry = LocateRegistry.getRegistry(getRegistryPort()); 105 registry.list(); // Verify it's alive and well 106 } 107 catch (Exception e) { 108 // Couldn't get a valid registry 109 registry = null; 110 } 111 112 // If we couldn't find it, we need to create it. 113 // (Equivalent to running "rmiregistry") 114 if (registry == null) { 115 try { 116 registry = LocateRegistry.createRegistry(getRegistryPort()); 117 } 118 catch (Exception e) { 119 log("Could not get or create RMI registry on port " + 120 getRegistryPort() + ": " + e.getMessage()); 121 return; 122 } 123 } 124 125 // If we get here, we must have a valid registry. 126 // Now register this servlet instance with that registry. 127 try { 128 registry.rebind(getRegistryName(), this); 129 } 130 catch (Exception e) { 131 log("Could not bind to RMI registry: " + e.getMessage()); 132 return; 133 } 134 } 135 136 /** 137 * Unbinds the servlet from the registry. 138 * Logs any errors. 139 */ 140 protected void unbind() { 141 try { 142 if (registry != null) registry.unbind(getRegistryName()); 143 } 144 catch (Exception e) { 145 log("Problem unbinding from RMI registry: " + e.getMessage()); 146 } 147 } 148}