The base server framework provides a generic set of classes for implementing connection-oriented servers which manage multiple threads for handling client connections. There is one server acceptor thread that continually sits in a tight loop accepting the connections, keeping the backlog to minimum. Once it gets a connection, it dispatches it to one of the server handler threads from the worker pool. The size of the worker pool is dynamically configurable, as are a variety of additional server parameters.
The server begins by creating worker threads for handling new connections. The server then repeatedly accepts new connections and places them on a connection queue for subsequent retrieval by the handler threads. Before a new connection is dispatched to the pool of handler threads, the server checks to make sure that at least one handler thread is waiting for a connection. This ensures that new connections will not be accepted unless there is an available handler. If no handlers are currently available, then a new handler thread will be forked, as long as the limit on the number of such handlers is not exceeded. If that limit would be exceeded, the server will block until a new connection is available. Additionally, if a handler thread has been waiting a "long" time for a new connection, and more than the minimum number of handler threads are currently running, that handler thread will expire.
Servlets are java objects that conform to a specific interface. Servlets are similar to applets in that they are object bytecodes that can be dynamically loaded off the net. However, they differ from applets in that they are faceless objects (without graphical interface of their own). Like applets, servlets are also identified by a URL address. Local servlets in the server can be identified by just the class name. Users can also supply a virtual name to a servlet at the time the servlet is loaded. This is useful if you want to run multiple instances of the same servlet in the server. Once a servlet has been loaded and initialized, the client can directly invoke the servlet by entering a URL of the form:
http://server_host/servlet/<servlet name>?arguments
Clients can also indirectly use the servlet by asking for a dynamically generated .html file.
Servlets are started when the server starts up, or just before they are used. There is an administered list of servlets to be started when the server starts. Servlets are also activated on demand, when a client's request needs to be handled by one. Once activated, any given servlet handles requests until the server dies or until the server calls the destroy method on that servlet. For more details, see the Java Servlet Application Programming Interface White Paper.
Servlets can be invoked by a client when a client asks for a document that is served by the servlet. Alternatively, servlets can be invoked directly by giving a URL of the form:
http://server_host/servlet/<servlet name>?arguments
There are some core servlets that the http server uses to provide standard http functionality. For example FileServlet is used to respond to the file requests, and CgiServlet provides the base cgi functionality. There is also a core InvokerServlet that acts as a meta-servlet responsible for loading, invoking, and shutting down the servlets. Currently, uploading and shutting down servlets is only enabled under privileged conditions. Any client can invoke a servlet using the URL syntax:
http://server_host/servlet/<servlet name>?arguments
The InvokerServlet acts as a dispatcher for client invocation.
Note that the servlet interface does not provide protection against concurrent access. This matters, because several handler threads may be using the same servlet concurrently; per-request data is held in arguments to a servlet, rather than to the servlet itself. If a servlet has some shared state that it needs to protect, than it should do so by marking appropriate blocks and variables synchronized. For example, if multiple http requests for files come in simultaneously, multiple handler threads will execute in the file servlet. Hence the file servlet needs to internally ensure thread-safety.
When a request is dispatched to the handler thread, it first picks the servlet to which the request will be delivered by applying the name translation rules. Then it calls the service routine of the destination servlet. Thus for (trusted) local servlets, the cost of servicing a request is equivalent to the cost of a procedure call.
For untrusted servlets, i.e, servlets loaded from the network, the code is run in a thread in a seperate thread group. As shown in the figure, there is a stub servlet for every untrusted servlet. The handler thread sends the request to the thread running in the untrusted servlet and waits in the stub servlet. Thus, for untrusted servlets, because there is one additional thread in the picture, the cost of servicing a request is more than in local servlet case.
Access to files is controlled using access control lists, which are a general and extensible framework.
Authentication and Authorization in the server and servlets is done on two levels. There is a server wide access control file, under the control of the web-administrator. Separate Access Control Lists can also be specified for any file or directory in the document tree. Additionally, ACLs can also be specified for a servlet. If a specific ACL is not specified for the requested file, directory or servlet, default server wide access control is applied. All the user information is passed to the servlet as part of the http request in the service routine. So if needed, servlets can implement their own authorization as a part of the service() method.