A UCW server sits in a tight loop waiting for incoming HTTP requests, elaborating them and then sending out the HTTP responses. This loop is called the "RERL" (Request-Eval-Response Loop) and the objects, methods are variables involved is the RERL are described here.
(defclass component () () (:documentation "The generic super class of all components."))
(defgeneric (setf component.calling-component) (caller component))
(defgeneric component.continuation (component) (:documentation "Accessor for COMPONENT's continuation. The continuation is implemented as a 1 arg lambda which is called with the value COMPONENT answers. and continues whatever was stopped when control was transfered to the component."))
(defgeneric (setf component.continuation) (k component))
(defgeneric call-component (caller callee) (:documentation "Transfer control from the component CALLER, to the component CALLEE. CALLEE should replace CALLER in the user interface (by setting itself in CALLER's place). CALLEE can return control to CALLER by calling answer-component. call-component can be called by user code even though it will generally be called through the CALL macro."))
(defgeneric answer-component (callee value) (:documentation "Return control to CALLEE's CALLER, continuing with the value VALUE. answer-component can be called by user code though it will generally be called through the ANSWER macro."))
(defvar *current-component* :unbound "When rendering this is bound to the current component (the second argument passed to render-on).")
(defgeneric parent (component) (:documentation "Returns the parent of COMPONENT. Only window components and detached components may return NIL from this function."))
(defgeneric render-on (response component) (:documentation "The generic entry point for rendering components to the user.") (:method-combination wrapping-standard))
(defgeneric compute-url (component &key action-id) (:documentation "Return a URL with the proper session, frame and action-id parameters."))
(defgeneric update-url (component url) (:documentation "Prepare URL for rendering as action urls."))
(defvar *default-server* nil "The server object to use when none is explicitly specified.")
(defclass server () () (:documentation "A single UCW server. Within the RERL server objects provide the following functionality: * Take request and response objects as provided by the backend via the handle-request method and run one iteration of the RERL. * Call the generic function associated-application to determine the application object which should handle the request. * Create a request-context object (via a call to make-request-context on the application) and initialize it. * Call the application's service method passing it the request-context. * Shutdown the request and response when the application's service method returns. The server object should also attempt to deal with all conditions signalled during the service'ing of the request. Servers are responsible for managing multiple applications within the same UCW instance and dealing with, possibly, multiple backends."))
(defgeneric server.applications (server) (:documentation "Return a list of all the application objects SERVER manages."))
(defgeneric startup-server (server) (:documentation "Make SERVER start responding to requests."))
(defgeneric shutdown-server (server) (:documentation "Make SERVER stop responding to requests and close/release and resources."))
(defgeneric associated-application (server request) (:documentation "Return the application object which will handle REQUEST."))
(defgeneric handle-request (server request response) (:documentation "Perform one iteration of the RERL on REQUEST and RESPONSE. Methods defined on this generic function must be built from the methods associated-application and service and should, as much as possible, handle all conditions signalled by calls to service."))
(defvar *default-application* nil "The application object to use when none is explicitly specified.")
(defmacro in-application (application) `(setf *default-application* ,application))
(defclass application () () (:documentation "A UCW application. Application objects are responsible for: - Managing a collection of sessions and finding the right session for a given request. - Managing session life time (session creation and expiration). - Creating request contexts. - Managing entry-points and associating them to request objects. - Creating http query paths which subsequently (when requested) call action lambdas. Since application objects are used to create sessions (via make-new-session) they are also important when customizing the functionality of the RERL."))
(defgeneric application.url-prefix (application) (:documentation "Returns the url prefix (a string) for APPLICATION. The URL prefix is that string which, when used as the prefix of an incoming http query path, identifies an application."))
(defgeneric make-request-context (application request response) (:documentation "Create a new request-context form REQUEST and RESPONSE. The returned context will have its application, request and response slots set to APPLICATION, REQUEST and RESPONSE. This method need not neccessarily return a new object each time but may reuse previouly created objects in which case a call to clear-context must be made before returning the object."))
(defgeneric find-session (application context) (:documentation "Return the session object in CONTEXT or NIL if there's no session."))
(defgeneric make-new-session (application) (:documentation "Return a new session object."))
(defgeneric find-entry-point (application context) (:documentation "Returns the entry-point object for CONTEXT's request. If no such entry-point exists return NIL."))
(defgeneric remove-expired-sessions (application) (:documentation "Remove all the expired sessions in APPLICATION. Implementations of this method must use the generic function EXPIREDP to determine if a session is expired or not, and must call DELETE-SESSION on the session objects."))
(defgeneric delete-session (application session &optional expire) (:documentation "Remove the session SESSION from APPLICATION. If EXPIRE is T then EXPIRE-SESSION MUST be called on the session."))
(defgeneric startup-application (application) (:documentation "Start the application's request-eval-response loop."))
(defgeneric shutdown-application (application) (:documentation "Terminate the application's life cycle. Release any and all resources held by APPLICATION. The value returned by the generic function is unspecified."))
(defclass request-context () () (:documentation "The generic super class of all request contexts. A request-context object contains all the information associated with one particular request/response loop. The request context is usually accessed via the special variable *context* and contains the currently relevant application, session, session-frame, request and response object."))
(defgeneric context.request (context) (:documentation "Accessor for the request object in CONTEXT."))
(defgeneric (setf context.request) (request context))
(defgeneric context.response (context) (:documentation "Accessor for the response object in CONTEXT."))
(defgeneric (setf context.response) (response context))
(defgeneric context.application (context) (:documentation "Accessor for the application object in CONTEXT."))
(defgeneric (setf context.application) (application context))
(defgeneric context.session (context) (:documentation "Accessor for the session object in CONTEXT."))
(defgeneric (setf context.session) (session context))
(defgeneric context.current-frame (context) (:documentation "Return the \"current\" (most recent) session-frame in CONTEXT's session.") (:method ((context request-context)) "Simply call session.current-frame on context's session object." (session.current-frame (context.session context))))
(defgeneric context.window-component (context) (:documentation "Return the \"current\" (most recenct) window component in CONTEXT's session."))
(defgeneric (setf context.window-component) (component context))
(defgeneric call-callbacks (context) (:documentation "Call all the request callbacks in CONTEXT's request. Methods defined on this generic function must be built up from calls to map-parameters (part of the backend protocol) and call-callback."))
(defgeneric find-session-id (context) (:documentation "Returns the client supplied session-id in CONTEXT. Methods should inspect the context's request object and return a string specifying the session-id. No guarantee on the validity (well-formedness or existence) of the returned session-id is made. If no session-id is supplied NIL must be returned."))
(defgeneric find-frame-id (context) (:documentation "Same as find-session-id but looks for the frame id."))
(defgeneric find-action-id (context) (:documentation "Same as find-action-id but looks for the action id."))
(defgeneric clear-context (context) (:documentation "Prepare REQUEST-CONTEXT for re-use. This method must destructivly modify CONTEXT so that it becomes indistinguishable from a freshly created object as returned by make-request-context."))
Service method and various constants and variables used while serving a request.
(defgeneric service (relevant-object context) (:documentation "The core request handling generic function. The service protocol consists of 4 passes: application -> session -> session-frame -> action. At each phase the appropriate object is passed to service with the current request object (which is also bound to *context*). The appropiate object must perform whatever it needs and then explicitly call service again passing it the next object in the chain."))
(defvar *context* :unbound "The current request-context object.")
(defclass session () ())
(defgeneric session.id (session) (:documentation "Returns the id of SESSION. An ID is a unique (within the same application) object identifying SESSION."))
(defgeneric expiredp (session) (:documentation "Returns true if SESSION has expired."))
(defgeneric expire-session (session) (:documentation "Causes this session to cease to exist."))
(defgeneric make-new-frame (session) (:documentation "Adds a new session-frame object to SESSION."))
(defgeneric session.current-frame (session) (:documentation "Return the current active frame in the session."))
(defgeneric session.value (key session &optional default) (:documentation "Fetch the value with key KEY in the session SESSION. DEFAULT is returned should KEY not be found in SESSION's session-table. Keys are compared using EQL."))
(defgeneric (setf session.value) (value key session &optional default) (:documentation "Sets the value of KEY in SESSION to VALUE. The DEFAULT argument is required to maintain the gethash-ish interface and to allow for the use of this function in incf and push macros. As with session.value keys are compared with EQL."))
(defun get-session-value (key &optional (default nil) (session (context.session *context*))) "Convenience wrapper around session.value. SESSION defaults to the current session." (session.value key session default))
(defun (setf get-session-value) (value key &optional (default nil) (session (context.session *context*))) "Convience wrapper around (setf session.value). SESSION defaults to the current session." (setf (session.value key session default) value))
(defclass session-frame () () (:documentation "Super class of all session frame. A session frame represents a single request/response interaction with a client. Session frames know what actions they've generated and what the component tree was when the response was sent."))
(defgeneric frame.id (session-frame))
(defgeneric frame.window-component (session-frame) (:documentation "Accessor for SESSION-FRAME's window component."))
(defgeneric (setf frame.window-component) (component session-frame))
(defgeneric call-callback (session-frame param-name value) (:documentation "Call the parameter callback in SESSION-FRAME with name PARAM-NAME passing it VALUE. PARAM-NAME is always a string, VALUE is either a string or a list of strings depending on how many values where under the name PARAM-NAME."))
(defgeneric find-action (session-frame action-id) (:documentation "Return the action (a function) associated with ACTION-ID."))
(defgeneric make-next-frame (frame new-frame-id) (:documentation "Create the \"next\" frame object with id NEW-FRAME-ID. The new frame object must build its history (component, backtracks, etc.) assuming that FRAME is the previous (in chronological order) frame."))
NB: actions are just regular methods and so don't explicitly appear in this protocol.
(defclass entry-point () () (:documentation "Generic super class of all entry-points. Entry points are the means by which a user begins their interaction with a UCW application. An entry point is an action (a function) associated to a particular URL in an application."))
(defgeneric register-entry-point (object url entry-point) (:documentation "Inform OBJECT (either an application, a server or a backend) to start handling requests for ENTRY-POINT at URL."))
(defgeneric unregister-entry-point (object url entry-point))
(defgeneric entry-point.url (entry-point) (:documentation "Returns the query path associated with ENTRY-POINT. The returned query-path will need to be combined with the application's url-prefix to produce a complete query-path."))
(defgeneric entry-point.action (entry-point) (:documentation "Returns the function which should handle requests for the entry point."))