Copyright © 2005-2007 Alessandro Colomba
This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
The source code refers to the DocBook XML source files. The object code refers to the generated HTML, PostScript, PDF, and other forms.
This documentation is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License (in Appendix A, GNU General Public License) along with this documentation; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Table of Contents
List of Tables
Table of Contents
SISCweb is a framework to facilitate writing stateful Scheme web applications in J2EE environments.
SISCweb sports an interactive, REPL-based web application development style. Developers can write applications interactively, without ever restarting the context, and, insofar as it is desirable, without ever losing application state. (In fact, save for the Java portion, SISCweb itself is developed interactively in its own REPL.)
Through the use of continuations, SISCweb does away with the page-centric execution model typical of web applications (see [1].) Every time a response is sent to the browser, the program execution flow is suspended, to be then resumed from that exact point when the browser submits a request. Some consequences of this approach are:
SISCweb is based on SISC (http://sisc.sourceforge.net/), a Scheme interpreter for the JVM with full continuations, and is heavily influenced by other Lisp web frameworks:
A couple of initial design decisions were also lifted from Matthias Radestock's servlet code in the contrib section of the SISC CVS tree.
Also special thanks to Anton van Straaten, Dominique Boucher, Ben Simon, Dan Muresan, Felix Klock and Tony Garnock-Jones for bug reports, suggestions, and/or work in support of SISCweb.
Comments, ideas, and bug reports are welcome at:
<acolomba@users.sourceforge.net>
[1] Christian Queinnec. "Inverting back the inversion of control or, continuations versus page-centric programming". Technical Report 7, LIP6. May 2001. ( http://www-spi.lip6.fr/~queinnec/Papers/www.ps.gz )
Table of Contents
Using SISCweb in web applications is simple matter of including
its components in the classpath and making some entries in the
web.xml
deployment descriptor.
First-time users may want to check out the example WAR file (siscweb-examples-[v].war). It can be deployed by simply dropping it into the deployment folder of a J2EE appserver, and can also be used as the starting point for developing a new application.
While the server-side REPL is disabled in the SISCweb examples WAR file available from sourceforge.net, if you build it from sources, a REPL will be bound to the localhost:5156 socket. This is a security vulnerability. You should make sure to disable this feature if you are concerned about other people on the same host gaining access to a full-fledged REPL.
SISCweb requires a J2EE 1.3 application server (Servlet spec. 2.3), Java 1.4 or later, and SISC version 1.15.x or later. SISC version 1.16.x or later is recommended.
SISCweb is divided into different components:
siscweb.jar
. The desired components should be
placed in the context's WEB-INF/lib
.
The SISC libraries, including the
sisc-heap.jar
file, should be also added to
the load path. They are found in the SISC binary distribution.
Starting from SISCweb v0.5, the SISC libraries can be placed in a classpath common to multiple contexts (e.g. in an EAR root or in the application server's path).
The core siscweb.jar
instead MUST be placed
in the context's WEB-INF/lib
. While
SISCweb's critical data (e.g. the continuation table) is
per-context, the logger and the configuration settings
detailed below are (for now) in the Java static scope.
SISCweb requires a couple of context parameters and a listener
in order to initialize. Besides that, the
SISCAdapterServlet
should be associated to
the context path under which sisclets
(SISC servlets) should be published.
Optionally, a number of environment entries are used to control various aspects of SISCweb's behavior and performance.
Beside SISCweb-specific settings, it is also possible to specify SISC parameters.
Two servlet context parameters,
siscweb.on-init-sexp
and
siscweb.on-destroy-sexp
, contain Scheme
code executed respectively when the context is initialized and
destroyed (i.e. during application server startup and
shutdown, as well as during context restarts.)
The siscweb.on-init-sexp
must contain a line to load the
siscweb/sisclet
module in the Scheme
toplevel. While SISCweb could well do this implicitly, the
current setup allows advanced users to substitute the module
with an equivalent one.
The context parameters are read by a the SISCweb J2EE listener, which must also be specified. The example below shows a typical configuration.
<context-param> <param-name>siscweb.on-init-sexp</param-name> <param-value> <![CDATA[ (require-extension (lib siscweb/sisclet)) ;; replace round parentheses below with square ones in real life ))> </param-value> </context-param> <context-param> <param-name>siscweb.on-destroy-sexp</param-name> <param-value> <![CDATA[ ;; generally nothing to do ;; replace round parentheses below with square ones in real life ))> </param-value> </context-param> <listener> <listener-class>siscweb.web.SISCInitializer</listener-class> </listener>
A Java adapter servlet allows the mapping of context paths to groups of sisclets. Sisclets are simply Scheme procedures associated through the publish mechanism (see Chapter 5, Publishing Procedures) to paths below that of the adapter servlet.
The adapter servlet accepts two parameters,
on-init-sexp
and
on-destroy-sexp
, which are invoked when the
servlet is initialized and destroyed. As the example below
shows, they are typically used to respectively publish and
unpublish sisclets.
<servlet> <servlet-name>examples</servlet-name> <description>siscweb examples</description> <servlet-class>siscweb.web.SISCAdapterServlet</servlet-class> <init-param> <param-name>on-init-sexp</param-name> <param-value> <![CDATA[ ;; NOTE: scm/ is not generally a good place, since it is browsable (class-path-extension-append! '("scm/" "WEB-INF/scm/")) (require-extension (lib siscweb/publish)) (require-extension (lib examples/hello-world)) (publish "/hello/*" 'hello-world) ;; replace round parentheses below with square ones in real life ))> </param-value> </init-param> <init-param> <param-name>on-destroy-sexp</param-name> <param-value> <![CDATA[ (require-extension (lib siscweb/publish)) (unpublish "/hello/*") ;; replace round parentheses with square in real life ))> </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>examples</servlet-name> <url-pattern>/sisclets/*</url-pattern> </servlet-mapping>
SISCweb will initialize the SISC interpreter with
parameters loaded from the file
WEB-INF/sisc.properties
if present. This
is particularly useful for static parameters, but also
convenient for dynamic parameters that are not changed by the
application. Some often-used settings are:
; max stack trace in case of errors sisc.maxStackTraceDepth = 16 ; web prompt sisc.replPrompt = "W;> " ; disable in production sisc.stackTraceOnError = true
Some aspects of SISCweb's inner workings can be controlled via a number of environment entries. The advantage of environment entries over Java properties or context parameters is that they can be usually changed through the application server's administrative console. This is especially useful because new values for a select environment entries are dynamically picked up within about one minute.
Applications using SISCweb can optionally provide a network-accessible Scheme REPL. This is particularly useful during development, and with precautions it can be an invaluable feature in the deployment environment as well.
The server-side REPL amounts to a no-login shell into a server, therefore it is highly advisable to at least bind it to the local interface only (i.e. localhost).
The REPL can then be made remotely accessible in a secure manner by establishing an SSH tunnel.
Table 2.1. REPL-related environment entries
Name | Values;Type | Description |
---|---|---|
siscweb/repl-p |
true |false ;
java.lang.Boolean
|
Whether or not SISCweb should bind a REPL to a
network socket. Static, defaults to
false .
|
siscweb/repl-host |
IP address (e.g. 127.0.0.1 );
java.lang.String
|
The network address to which the REPL should be
bound. Static, defaults to null .
|
siscweb/repl-port |
Port number (e.g. 5156 );
java.lang.Integer
|
The port to which the REPL should be bound. Static,
defaults to 0 .
|
SISCweb logs its internal operations in order to aid troubleshooting.
Table 2.2. Log-related environment entries
Name | Values;Type | Description |
---|---|---|
siscweb/logging-level |
SEVERE | WARNING |
INFO | CONFIG |
FINE | FINER |
FINEST ;
java.lang.String
|
The Java logging level that SISCweb should adopt.
Static, defaults to INFO .
|
siscweb/logging-file |
File path (e.g. %t/siscweb.log );
java.lang.String
|
A file path where SISCweb should log its messages.
Static, defaults to null , i.e. it
logs to the application server's location.
|
siscweb/logging-limit |
java.lang.Integer
|
The maximum number of bytes to write to the log
file. Static, defaults to 5000000 .
|
siscweb/logging-count |
java.lang.Integer
|
The maximum number of log files to rotate. Static,
defaults to 1 .
|
SISCweb stores and manages the lifecycle of the continuations corresponding to URLs through a pluggable class. This allows storing continuations in the Session object (recommended), databases, flat files, or user-defined storage.
Table 2.3. Continuation management environment entries
Name | Domain | Description |
---|---|---|
siscweb/continuation-ttl |
seconds; java.lang.Long
|
New continuations will have the indicated time-to-live
unless overridden via the
adjust-timeout! procedure.
Dynamic, defaults to 1200 seconds.
|
siscweb/continuation-cleanup-interval |
milliseconds; java.lang.Long
|
SISCweb will remove expired continuations
periodically according to the indicated
interval. Dynamic, defaults to
30000 ms.
|
siscweb/continuation-group-creation-interval |
milliseconds; java.lang.Long
|
This parameter can be used to limit the rate at which
new continuation groups -- each group corresponds to a
request --, are created for each session. A reasonable
value will go unnoticed by human users, but assist
against basic DoS attacks. Dynamic, defaults to
500 ms.
|
siscweb/user-history-size |
java.lang.Integer
|
Technically the maximum number of continuation groups
stored per user at any given time, in practice it
amounts to the number of pages/requests in the user
history for which continuations are still stored. If
the maximum number is reached, the continuation group
expiring the soonest is removed to make room for a new
group. This parameter can be used to roughly bound the
amount of resources devoted to each user. Dynamic,
defaults to 50 .
|
siscweb/user-history-size-serialized |
java.lang.Integer
|
When a user session is passified, only the indicated
number of continuation groups is maintained. Dynamic,
defaults to 10 .
|
Table of Contents
SISCweb programs can generate HTTP responses of a variety of data types -- HTML/XML/XHTML represented in SXML notation, images --, or they can forward requests to standard JSPs/Servlet components. Procedures to generate HTTP errors are also available. Other response types can be easily plugged on top of a basic set of response procedures.
The procedures that produce HTTP responses are in the form
send-*/*
, with the first pattern indicating
the type of response, and the latter determining whether or not to
save the execution state, and whether or not to clear previously
saved states.
All the procedures accept an optional association list of HTTP
response headers as the first, optional argument. The association
list is in the form ((name value)
...)
. This can be used to override the default
Content-Type, to set caching options, etc.
SISCweb provides a number of modules with an uniform API to produce HTML, XHTML and XML markup. Their procedures accept documents in SXML syntax, and in the case of HTML and XHTML, a few extra elements and attributes are used to assist with continuation-based programming (see the section called “Extended HTML markup”.)
Requires:
(import siscweb/html)
Requires:
(import siscweb/xhtml)
Located in:
siscweb-sxml.jar
The core procedures to send (X)HTML content follow the basic
send-html/*
and
send-xhtml/*
patterns. They differ in
whether or not they clear the continuation table, and whether
or not they return after the user interacts with the page.
The XHTML and HTML modules serialize SXML differently, with the former producing pure XML, and the latter producing markup tweaked to display properly in known browsers. When producing XHTML for common user agents, it is advisable to keep the HTML Compatibility Guidelines in mind.
Also, while the XHTML module implements the complete SXML
specification, the HTML module is more limited in that only
understands DTD declarations,
*VERBATIM*
and
*COMMENT*
elements besides the basic
element+attribute syntax. Also, while the XHTML module
considers the *TOP*
element functional,
the HTML module silently ignores it.
procedure:
(send-html/suspend [header-alist] (lambda (k-url) <sxml>)) => request
procedure:(send-xhtml/suspend [header-alist] (lambda (k-url) <sxml>)) => request
Sends the given SXML to the browser in the form of (X)HTML and suspends the execution flow. The
k-url
will contain a hash used to resume the program's execution, and should therefore be used in forms and links as needed. When the browser submits a request to thek-url
, said request will become the return value of the procedure.
(let loop ((n 0)) (send-html/suspend (lambda (k-url) `(html (body (a (@ (href ,k-url)) ,n))))) (loop (+ n 1)))
procedure:
(send-html/forward [header-alist] (lambda (k-url) <sxml>)) => request
procedure:(send-xhtml/forward [header-alist] (lambda (k-url) <sxml>)) => request
These procedures behave like
send-html/suspend
andsend-xhtml/suspend
, except that they clear the continuation table first. This will prevent the client from using the back button to resume the program flow from earlier points.
procedure:
(send-html/back [header-alist] <sxml>) => does not return
procedure:(send-xhtml/back [header-alist] <sxml>) => does not return
These procedures send the provided SXML to the browser and stop.
(send-html/back `(html (body (a (@ (href "http://www.w3.org")) "w3c"))))
Requires:
(import siscweb/xml)
Located in:
siscweb-sxml.jar
This module provides functions to send XML responses with the
same features as those in the HTML and XHTML modules. This
enables clients to conduct a stateful conversation with the
server. The same features available through the extended
(X)HTML can be reproduced in any XML element by using the
store/forward!
procedure described in
the section called “Forwarding Requests”.
procedure:
(send-xml/suspend [header-alist] (lambda (k-url) <sxml>)) => request
procedure:(send-xml/forward [header-alist] (lambda (k-url) <sxml>)) => request
procedure:(send-xml/back [header-alist] <sxml>) => does not return
procedure:(send-xml/finish [header-alist] <sxml>) => does not return
These functions are analogous to those in the HTML and XHTML modules.
SISCweb's send-[html/xhtml/xml]/*
procedures accept a slightly extended version of the SXML
syntax.
The send-html/*
procedures transform
symbols in the markup into entities. This usage is now
deprecated, and the form (& name)
should be used instead for HTML, XHTML and XML.
(send-html/back `(html (body (p "Can't" (& nbsp) "wrap" (& nbsp) "me.") (p "Nor" (& |#160|) "me."))))
Numbers in attributes and text nodes are automatically
converted to strings using pretty-print
.
(send-html/back `(html (body (table (@ (width 42)) (tr (td 42))))))
The value #f as an element or attribute value is ignored. This comes handy when generating dynamic content.
;; equivalent to (html (body (p))) (send-html/back `(html (body (p (@ (align #f)) ,(hashtable/get ht 'para)))))
The element *VERBATIM* can be used to produce non-escaped text.
(send-html/back `(*VERBATIM* "<html><body><p>Hello, "world"</p></body></html>))
The elements *DTD-INFO* and *DTD-INFO/PUBLIC* can be used to generate DTD declarations. For XML/XHTML only, the *PI* element should be used to generate the XML declaration.
(send-xhtml/back `(*TOP* (*PI* xml "version=\"1.0\"") (*DTD-INFO/PUBLIC* "html" "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd") (html (@ (xmlns "http://www.w3.org/1999/xhtml") (xml:lang "en") (lang "en")) (head (title "Hello")) (body (p "Hello")))))
The HTML and XHTML modules support a number of extra attributes to support continuation-centric programming and interaction with the J2EE environment.
attribute:
`(a (@ (bindings ,binding-alist [(anchor name)]...) ...)
attribute:`(form (@ (bindings ,binding-alist) [(anchor name)] ...) ...)
attribute:`(iframe (@ (bindings ,binding-alist) [(anchor name)] ...) ...)
attribute:`(img (@ (bindings ,binding-alist) ...) ...)
attribute:`(link (@ (bindings ,binding-alist) ...) ...)
attribute:`(object (@ (bindings ,binding-alist) [(anchor name)] ...) ...)
attribute:`(script (@ (bindings ,binding-alist) ...) ...)
This syntax is only usable from the
*/suspend
and*/forward
procedures. It will produce a link that, when followed, will bind the given bindings to the request object returned by these two functions. Thebinding-alist
is in the format specified in Chapter 6, Request Bindings.The optional
anchor
attribute allowed by some of the elements is made part of the generated URL.
attribute:
`(a (@ (href-p ,proc) [(bindings ,binding-alist)] [(anchor ,name)] ...) ...)
attribute:`(form (@ (action-p ,proc) [(bindings ,binding-alist)] [(anchor ,name)] ...) ...)
attribute:`(iframe (@ (src-p ,proc) [(bindings ,binding-alist)] [(anchor ,name)] ...) ...)
attribute:`(img (@ (src-p ,proc) [(bindings ,binding-alist)] ...))
attribute:`(link (@ (href-p ,proc) [(bindings ,binding-alist)] ...))
attribute:`(object (@ (data-p ,proc) [(bindings ,binding-alist)] [(anchor ,name) ...) ...)
attribute:`(script (@ (src-p ,proc) [(bindings ,binding-alist)] ...) ...)
These attributes produce links that invoke the given procedure
proc
when followed. The HTTP request object will be passed as the only parameter to the procedure, and will contain the bindings specified inbinding-alist
, if present.In the case of
@action-p
, the form field values and the specified bindings will be merged, with the latter taking precedence over the former.The optional
anchor
attribute allowed by some of the elements is made part of the generated URL.
attribute:
`(a (@ (href-c ,c-url) [(bindings ,binding-alist)] ...) ...)
attribute:`(form (@ (action-c ,c-url) [(bindings ,binding-alist)] ...) ...)
attribute:`(iframe (@ (src-c ,c-url) [(bindings ,binding-alist)] ...))
attribute:`(img (@ (src-c ,c-url) [(bindings ,binding-alist)] ...))
attribute:`(link (@ (href-c ,c-url) [(bindings ,binding-alist)] ...))
attribute:`(object (@ (data-c ,c-url) [(bindings ,binding-alist)] ...) ...)
attribute:`(script (@ (src-c ,c-url) [(bindings ,binding-alist)] ...) ...)
These attributes allow specifying URLs relative to the context in which the SISCweb application is running. They are useful to reference plain HTML files or JSPs that co-exist in the same context. If any bindings are specified, they will be included in the request associated to the
c-url
.The
anchor
attribute is not allowed, as it can be directly specified in thec-url
parameter.
attribute:
`(a (@ (href-e ,url) ...) ...)
attribute:`(form (@ (action-e ,url) ...) ...)
attribute:`(iframe (@ (src-e ,url) ...))
attribute:`(img (@ (src-e ,url) ...))
attribute:`(link (@ (href-e ,url) ...))
attribute:`(object (@ (data-e ,url) ...) ...)
attribute:`(script (@ (src-e ,url) ...) ...)
These attributes encode the given
url
as per the the JavaHttpServletResponse.encodeURL()
method. This is useful to support cookie-less interaction, as it will encode the session ID in theurl
as needed.The
anchor
attribute is not allowed, as it can be directly specified in the <attribute>c-url</attribute>.
attribute:
`(object (@ (type "graphviz") (layout ,layout) (format ,format) ...) (graph (@ (id ,id) ...))
If the attribute
type "graphviz"
is specified for theobject
element, a Graphviz graph will be embedded in the document.The
layout
andformat
attributes are analogous to the omonymous parameters to thesend-graphviz/*
functions (see the section called “Graphviz Procedures”.) However, the value offormat
determines how the content is included:
gif, jpg, png
: The graph is embedded as animg
tag, and a corresponding image map is generated. Links associated to nodes, edges and records will be mapped appropriately. Just as for other document elements, the@href[-[p|c|e]]
and@bindings
attributes are available, and behave as described in the section called “Extended HTML markup”.ps, svg, etc.
: The graph is embedded as anobject
tag. The appropriate mime type is automatically set, and needs not be specified explicitely.In both cases, any attribute specified for the
object
tag will be applied toward the generatedobject
orimg
tag.
(send-html/suspend (lambda (k-url) `(html (head (title "Embedded Graphviz") (body (h3 "Embedded Graphviz") (object (@ (type "graphviz") (layout dot) (format png)) (graph (@ (id "G")) (node (@ (id "c") (label "scissors") (href "http://www.google.com/search?q=scissors"))) (node (@ (id "p") (label "paper") (href "http://www.google.com/search?q=paper"))) (node (@ (id "s") (label "stone") (href "http://www.google.com/search?q=stone"))) (edge (@ (from "c") (to "p") (label "cut") (href-p ,cut))) (edge (@ (from "p") (to "s") (label "wraps") (href-c "/"))) (edge (@ (from "s") (to "c") (label "breaks") (href-e ,k-url))))))))))
Requires:
(import siscweb/text)
Located in:
siscweb.jar
This module provides functions to send plain text responses.
procedure:
(send-text/suspend [header-alist] (lambda (k-url) <text>)) => request
procedure:(send-text/forward [header-alist] (lambda (k-url) <text>)) => request
procedure:(send-text/back [header-alist] <text>) => does not return
procedure:(send-text/finish [header-alist] <text>) => does not return
These functions are analogous to those in the HTML and XHTML modules.
Requires:
(import siscweb/forward)
Located in:
siscweb.jar
Since SISCweb lives in a J2EE environment, it is sometimes convenient to generate content using traditional techniques such as JSPs and servlets rather than SXML.
The send-forward/*
procedures dispatch the
request to the indicated context-relative URL. Bindings can be
attached in the form of <bindings> objects or a-lists. The
forward/store!
function can also be used to
pass URLs mapped to closures in the style of the
@[action|data|href|src]-p
tags. Coupled
with the URL corresponding to the current-continuation being set
in the siscweb.kURL
request attribute,
this enables one to use SISCweb for control and JSP/Servlets
for presentation without losing too many features.
See the section called “Extracting Bindings from Java” for details on how to access bindings from Java.
procedure:
(send-forward/suspend context-url [bindings]) => request
Forwards the current request and suspends. The
context-url
is relative to the context in which the SISCweb application is running. The optionalbindings
parameter is either a <bindings> object or an a-list as specified in Chapter 6, Request Bindings. The continuation URL will be set in thesiscweb.kURL
request attribute.
procedure:
(send-forward/forward context-url [bindings]) => request
This function behaves like
send-forward/suspend
, except that it clears the continuation table first. This will prevent the client from using the back button and resume the program flow from earlier points.
procedure:
(send-forward/back context-url [bindings]) => does not return
Forwards the current request to the provided
context-url
and stops.
procedure:
(send-forward/finish context-url [bindings]) => does not return
Like
send-forward/back
, this function forwards the current request to the providedcontext-url
and stops, but clears the continuation table first.
procedure:
(forward/store! proc [bindings]) => k-url
procedure:(forward/store! c-url [bindings]) => k-url
In the first form, stores a closure
proc
in the continuation table, and returns the url that will invoke it. Theproc
procedure should accept a request object as its only argument. Ifbindings
are specified, either as an a-list or a <bindings> object,will see them as bindings in its request.In the second form
forward/store!
stores a closure that forwards the request to the given context-relativec-url
, including any specified bindings, if any.This function is especially useful when passing bindings through the
send-forward/*
functions, as it allows to embed links to closures in JSPs and the such, and can thus be used to implement the same style of page navigation afforded by the tags@*-c
+@bindings
and@*-c
+@bindings
in the extended (X)HTML described in the section called “Extended HTML markup” Notably missing is the equivalent of the plain@bindings
.
procedure:
(forward/store! proc [bindings]) => k-url
This procedure is similar to the first form of
forward/store!
, except that whenproc
is executed, it will run in the dynamic context in effect whenforward/dynenv/store!
is invoked.The main reason to use this procedure is that
proc
will see the same SRFI-39 parameter bindings established at the timeforward/dynenv/store!
was called.
Requires:
(import siscweb/image)
Located in:
siscweb.jar
This module provides procedures to send images from
java.awt.image.RenderedImage
or files.
procedure:
(send-image/back [header-alist] format java.awt.image.RenderedImage) => does not return
Sends the given image to the browser in the specified
format
.
procedure:
(send-image/finish [header-alist] format java.awt.image.RenderedImage) => does not return
This procedure behaves like
send-image/back
, except that it clears the continuation table. This will prevent the user from using the back button to resume the program flow from earlier points.
Requires:
(import siscweb/graphviz)
Located in:
siscweb-sxml.jar
This module provides procedures to send graphs in various formats as generated by Graphviz (http://www.graphviz.org). Most of the functions accept a markup representation of DOT, the GraphViz language, in the form of DotML (see the section called “DotML”.)
The GraphViz programs (dot, neato, etc.) should be installed
somewhere in the system path. This is usually the case in
UNIX. Alternatively, it is possible to set the absolute paths to
the GraphViz programs by using the
graphiz/put-layout-command!
function.
Graphs can be generated either using the
send-graphviz/*
functions, or by embedding
the @type="graphviz"
attribute
in the (X)HTML object
tag (see the section called “Extended HTML markup”.)
Both send-graphviz/*
procedures accept
the same three parameters:
layout
: This is a string specifying
which Graphviz layout engine to use. The current choices are
dot, neato, twopi, circo, and fdp.
format
: This is a string specifying
the output format. The most useful choices currently are
gif, jpg, 'png, 'ps, and 'svg.
<dotml>
: This is an sxml
representation of the DotML language. See the section called “DotML”.
procedure:
(send-graphviz/back layout format <dotml>) => does not return
Sends the given
dotml
graph in the specifiedformat
to the browser after laying the graph out using the indicatedlayout
engine.
(send-graphviz/back 'dot 'png `(graph (@ (id "G")) (node (@ (id "c") (label "scissors"))) (node (@ (id "p") (label "paper"))) (node (@ (id "s") (label "stone"))) (edge (@ (from "c") (to "p") (label "cut"))) (edge (@ (from "p") (to "s") (label "wraps"))) (edge (@ (from "s") (to "c") (label "breaks")))))
procedure:
(send-graphviz/finish layout format <dotml>) => does not return
This procedure behaves like
send-graphviz/back
, except that it clears the continuation table. This will prevent the user from using the back button to resume the program flow from earlier points.
procedure:
(graphviz/put-layout-command! layoutcommand) => undefined
Associates a given
layout
to the specifiedcommand
. This function can be used to add Graphviz layout engines, or to specify absolute paths for existing engines. The latter is likely to be an issue in Windows.
(graphviz/put-layout-command "dot" "d:/bin/dot.exe")
The send-graphviz/*
procedures accept a
graph description expressed in DotML. DotML was created by
Martin Loetzsch, and an exhaustive description rich with
excellent examples is at http://www.martin-loetzsch.de/DOTML.
SISCweb does not use code from the DotML project, but it implements the same markup syntax in sxml form. There are a few differences between SISCweb's implementation and the original:
graph
,
sub-graph
, cluster
and node
elements must always specify
an id
attribute.
id
attribute values at the moment
are limited to strings of alphanumeric characters and
underscore.
record
elements must
specify an id
attribute, but nested
record
and node
elements do not have to.
Requires:
(import siscweb/error)
Located in:
siscweb.jar
HTTP error responses can be generated using two functions, which differ in how the affect the continuation table. Neither function returns. The error codes should abide to the RFC2616 specifications.
Table of Contents
Introductions to web programming often mention the statelessness of the HTTP protocol, to then describe how cookies and sessions solve the problem. This is not a complete solution however: being "sessionful" is not the same as being "stateful."
Cookies and sessions are mechanisms laid on top of the HTTP protocol respectively to: a) allow an application to recognize two requests coming from the same browser as such, and b) to store data common to such requests.
Neither cookies nor sessions completely address the issue of statelesness because, while programs have the means to associate two requests to a given user (as they contain the same cookie), they have no means by which to associate two requests as being part of the same navigation flow. It is in fact possible to manually place requests out of sync with program state, and often trigger incorrect behavior. Traditional web applications are thus less like a program with a GUI interface and more like an API open to the world. Forced browsing, or even using the back button, can cause an application to misbehave in ways that are not easily foreseeable as application complexity increases.
Aside from state, the Session object is common to all requests from the same browser, so simply using a web application from two windows can produce concurrency problems such as loss of consistency or race conditions. Moreover, since the session is a global scope for the application, in fact the only scope that traditionally persists from request to request, developers are unable to take advantage of the finer scoping mechanisms available in modern programming languages.
One last major issue with traditional web applications is that they are made of short-lived code snippets which, after parsing the request in the context of the session, generate a response and exit. Because their state is lost, it is impossible to use structured programming techniques in code spanning multiple requests. Even the simplest for-loop must be expressed in terms of a (global) session variable increment and a GOTO (HREF).
Continuations afford a truly stateful approach. When a program generates a response, it suspends its execution instead of exiting. This suspended state is a continuation, and it includes stack and variables in scope. When the execution is resumed by the subsequent request, stack and variables are as they were left -- no manual storage in the session is needed.
SISCweb, like other similar frameworks, is able to determine which requests are associated with which continuations by branding each request and its corresponding continuation with a unique, cryptographically strong hash.
Branding reduces the issue of the back button because any request originating from a page in the browser history is associated with a unique continuation. Re-submitting the same request results in the same code being run, with the same local variables and stack it had at the time it was suspended. A program written in functional style (i.e. with no side effects) will be completely immune to the back button.
Saving the local state means that a for-loop can be written at the language level. (The Polyglot Hello World example included with SISCweb demonstrates this feature.) Saving the stack also means that an entire navigation flow can be represented as a subroutine returning a value, rather than as a sequence of code snippets connected by GOTOs (HREFs) finally depositing a value in the global scope.
Most complex applications will require a finer amount of control over state. For instance, a shopping cart should reflect the most recent operations even if the user were to backtrack by a few pages and resume shopping from a point in the navigation history. SRFI-39 or plain session variables can be used in such cases.
In other cases state is more closely dependent to the specific page, such as in the case of sorting a table in the browser. The sorting order should behave consistently in the presence of backtracking, cloning, and concurrent requests.
A possible solution for these cases is state-passing style, where a structure is passed from continuation to continuation and updated non-destructively. This can be somewhat inconvenient though, so instead SISCweb implements Web Cells, a dynamic scoping mechanism that follows the page flow and branches with backtracking and cloning.
Requires: (import srfi-39)
A complete treatment of parameters is available in SRFI-39. This section is concerned with the use of the dynamic environment to maintain state shared by all requests for the same user in the same execution flow.
SRFI-39 parameters are essentially dynamically-scoped
variables. They can be defined in the global or the module scope
and then bound to the dynamic scope -- the scope of the
execution flow -- in the application entry point through the
parameterize
form.
When using send-*/[suspend|forward]
, the
parameters, being part of the dynamic environment, are captured
in the suspended state -- the suspension of the program
execution is transparent to parameter bindings.
However procedures stored with
@href-p
-style attributes or the
forward/store!
procedure will run in the
base dynamic environment, and thus will see fresh values of the
parameters. In those cases on can use
forward/dynenv/store!
, which instead
preserves the dynamic environment.
The Counter with SRFI-39 Parameters example demonstrates this technique.
Requires: (import siscweb/webcells)
Web Cells are a way to track program state according to the navigation flow. They are described in full in the paper Interaction-Safe State for the Web.
In essence, cells establish a dynamic scope over the navigation path of a user. Successive pages can overshadow values of bindings set in previous pages, but do not destroy them.
If a user backtracks the browser window, previous values are again visible. If the user clones the window and proceeds through two different navigation branches, each branch sees the values it overshadows.
The Counter with Webcells example demonstrates this technique.
procedure:
(webcell/make [name] default-value) => <cell>
Creates a cell with the given
default-value
with the specified name. Please note thatwebcell/make
is a macro, soname
is an identifier, not a symbol.If
name
is omitted, a random name is generated. Omitting a specific name is useful to avoid name collisions (since cells are dynamically, not lexically, scoped). However if it is expected that sessions be serialized across context or server restarts, it may be important to guarantee that cells defined in the toplevel or int the module scope carry the same name.
procedure:
(webcell/make-parameter [name] default-value) => cell-parameter-proc
Creates a parameter procedure in the sense of SRFI-39. As in the case of
webcell/make
, thename
parameter is optional, but recommended if maintaining the same name across context or server restarts is important.
procedure:
(webcell/set! cell value) => undefined
Sets the content of the given
cell
to the specifiedvalue
.Of course the specified value is only accessible to the current and successive request.
procedure:
(webcell/ref cell) => value
Returns the value of the specified
cell
in the context of the current request.If the current request did not set a value already, the value will be looked up from the previous request (leading to the current), and then the previous again.
If no value can be found through the history of requests, then the cell's default value is returned.
Requires:
(import siscweb/session)
Located in:
siscweb.jar
In some situations a global, per-user scope may be desirable. This approach is more prone to concurrency problems, but its semantics is very straightforward.
The Session object can be accessed via a syntax similar to that
of SRFI-39
parameters, or via Scheme wrappers around the
Session.get/setAttribute()
calls. While the
former is appropriate for storing Scheme values, the latter is
provided as a means to store and retrieve Java objects (or
java-wrap
ped Scheme values.)
procedure:
(session/make-parameter name) => proc
Returns a procedure
proc
that, when invoked, sets or retrieves a Scheme value to/from the a Session attribute namedname
, depending on whether a value is passed or not to. Ifproc
is passed the #f value, the attribute is removed from the Session object altogether.(module security (define auth-token (session/make-parameter "auth-key")) ;; sets an auth token in the session object (define (login usr pwd) (auth-token (make-token usr pwd))))
procedure:
(session/get-java-attribute name) => jobject
procedure:(session/get-java-attribute-names) => list
procedure:(session/set-java-attribute! name jobject) => #!void
procedure:(session/set-java-attribute! name jobject) => #!void
These functions access Java attributes as session objects. Complete descriptions are given in the section called “Session Procedures”.
Table of Contents
Procedures can be published to virtual paths of an application server within the hierarchy of a siscweb application. Publishing can be done both interactively at the server-side REPL during development, and in the web.xml file at deployment time. (See the section called “The Adapter Servlet”.)
Requires:
(import siscweb/publish)
Located in:
siscweb.jar
This module provides simple procedures to publish procedures to URL patterns. Patterns can be expressed either as wildcards or regular expressions.
Published procedures accept a single parameter in the form of a request object.
Since the Java HttpServletRequest object is not serializable, it is a good practice to clear any reference to it as soon as possible.
Wildcard patterns can use wildcards and double-wildcards between slashes, such as in "/hello/*" or "/hello/**/world". The first pattern matches requests such as "/hello/there", "/hello/", or even "/hello"; the second pattern matches "/hello/world" as well as "hello/what/a/wonderful/world/".
procedure:
(publish/wildcard url-wildcard-pattern (lambda (request) ...)) => undefined
procedure:(publish/wildcard url-wildcard-pattern symbol) => undefined
Publishes the given procedure
proc
orsymbol
aturl-wildcard-pattern
. Thesymbol
will be looked up at run time every time. This is especially useful during development, since it allows one to redefine the procedure associated tosymbol
without having to republish.When a request is received, the path-info section of the request URL is matched against each published pattern. If a match is found, the corresponding procedure is invoked. The procedure will receive the HTTP request as its only argument.
(publish/wildcard "/hello-world/*" (lambda (request) (set! request #f) (send-html/back `(html (head (title "Hello, world!")) (body (p "Hello, world!"))))))
procedure:
(publish/regexp url-regexp-pattern (lambda (request) ...)) => undefined
procedure:(publish/regexp url-regexp-pattern symbol) => undefined
This function is equivalent to
publish/wildcard
, save for the fact that it accepts a regular expression as a pattern.
procedure:
(publish url-wildcard-pattern (lambda (request) ...)) => undefined
procedure:(publish url-wildcard-pattern symbol) => undefined
This function is equivalent to
publish/wildcard
, and is present both for backwards compatibility and to offer a convenient shorthand.
procedure:
(unpublish url-pattern) => undefined
Removes a previously published procedure at the given pattern. The
url-pattern
passed tounpublish
must be identical to the one used to publish.
procedure:
(get-published url-pattern) => procedure/#f
Returns the procedure published at the given
url-pattern
or #f if none is found.
procedure:
(get-all-published) => alist
Returns an association list made of (
pattern
procedure
notation
) elements or '() if no procedures are published.
procedure:
(publish-bulk ((url-pattern [procedure|symbol] notation) ...)) => undefined
Given an association list of (
url-pattern
procedure
notation
), publishes all the given procedures or symbols to the provided patterns.Depending on whether
notation
is the symbol'wildcard
or'regexp
, the givenurl-pattern
should be either a wildcard or regular expression pattern.
Bindings associated with the request returned by the
send-*/(suspend|forward)
functions, or passed
as parameters to procedures that are either published or the
target of a dispatch, can be extracted and associated to
language-level variables.
Bindings, as returned by the function
get-bindings
are contained in an opaque
object. This object can be converted to an association list via
bindings->alist
, or queried in constant time
using the extract-bindings
or
extract-single-binding
functions. The object
is guaranteed to be serializable, but code should not rely on its
specific implementation.
Requires:
(import siscweb/bindings)
Located in:
siscweb.jar
This module assists developers in obtaining values of parameters passed in a request.
procedure:
(get-bindings [char-set] request) => bindings
Given a request object, this procedure returns an opaque object representing the request parameters as key-value(s) pairs.
The optional
char-set
parameter can be used to override the character encoding of the request.
procedure:
(exists-binding? name bindings) => #t/#f
Returns a boolean indicating whether a parameter with the given
name
contained in the request object.name
can be either a string or a symbol.
procedure:
(extract-single-binding name bindings) => string/#f
Returns the value associated to the given
name
or #f ifname
is not present in the request object. If more than one value is bound toname
, only the first one is returned.
procedure:
(extract-bindings name bindings) => list
Returns the values bound to the given
name
in a list. Even if only one value is bound to the request parametername
, a list will still be returned.
procedure:
(bindings->alist bindings) => ((name . value) ...)
Returns an association list corresponding to the bindings. The
name
returned is always a string to maintain its casing, while thevalue
returned is an atom or a list ifname
is associated to multiple values.
syntax:
(let-bindings ((variable name) ... ) bindings body ...)) => value
Behaves like (let ...), but
variable
s are set to the values corresponding to thename
s in thebindings
object. Thevalue
returned is that of the last expression in thebody
. A typical usage scenario could be:(let-bindings ((name "name")) (get-bindings (send-html/suspend (lambda (k-url) `(html (body (form (@ (action ,k-url)) (input (@ (type "text") (name "name"))))))))) (send-html/back `(html (body (p "You typed: " ,name)))))
Bindings specified in the send-forward/*
functions are assigned to request attributes. This method
supercedes the previous request.getBinding*()
API, which is now deprecated and will be removed in the
next release.
Multi-valued bindings, as in '((messages "hello"
"there"))
, are turned into a
java.util.List
and can be easily scanned
using such tools as JSTL's
<c:forEach>
. Single-valued bindings,
such as '((message . "hello"))
are simply
assigned to the attribute.
Multi-valued bindings originating from a Scheme list are also
marked as such, so that they can be converted back to a list of
values rather than to an object of type
java.util.List
.
A minimal amount of type conversion is performed. Scheme values are passed as SISC objects, except for Scheme strings, which are converted to Java strings. Java objects are left untouched. This also applies to the individual values of multi-valued bindings.
For instance, below is the Polyglot Hello World example using JSP/JSTL as the presentation layer. This example is not included in the distribution because of its external dependencies on the JSTL libraries.
;; file: hello.scm (require-library 'siscweb/forward) (module examples/hello-world (hello-world) (import siscweb/forward) (define messages '("Hello, world!" "Salve, mundo!" "Hallo, Welt!" "Salve, mondo!" "Bonjour, monde!" "Hola, mundo!")) (define (hello-world req) (let loop () (for-each (lambda (message) (send-forward/suspend "/jsp/hello.jsp" `((message . ,message)))) messages) (loop))) ) <%-- File: jsp/hello.jsp --%><%@ page contentType="text/html" %><%-- --%><%@ page isELIgnored="false" %><%-- just for servlet v2.3 containers --%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%-- --%><%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml"%><%-- --%><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%><%-- --%><%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%><%-- --%><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%><%-- --%><?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title><c:out value="${requestScope.message}"/></title> <c:url var="cssUrl" value="/css/default.css"/> <link href="${cssUrl}" rel="stylesheet" type="text/css"/> </head> <body> <h3>Polyglot hello world</h3> <p>${requestScope.message}</p> <p><a href="${requestScope["siscweb.kURL"]}">Next language ></a></p> <p><a href="${requestScope["siscweb.kURL"]}" target="_blank">Next language in new window</a></p> <c:url var="homeUrl" value="/"/> <p><a href="${homeUrl}">^ Home</a></p> </body> </html>
At the lower level, bindings are looked up in the request scope first (i.e. from request attributes) and then from request parameters. This behavior allows a more natural integration with standard J2EE components such as JSPs, but can be unsafe during forwards.
Specifically, if the application performs a server-side forward to Scheme code that relies on the absence of a binding to determine a course of action, a malicious user can inject a parameter by the same name into the request (provided they can guess the name), and upset the application's behavior. The best options in this case are:
When forwarding from Scheme, pass bindings to the
forward/*
and
send-forward/*
functions even if they
are #f or the empty list. SISCweb will add the name to a
per-request blacklist, and will not look up the binding
among the request parameters.
When forwarding from Java to Scheme, set the attributes to
null
. Again, the name will be
blacklisted.
If the Java code that forwards to the Scheme code cannot be
trusted or modified for some reason, the Scheme side can
always use the java/get-request-attribute
function described in the section called “Request Procedures”.
Table of Contents
The SQL library performs automatic conversion between scheme and database types. Since the exact conversion table depends on the vendor, a mechanism is provided to add support for other vendors though vendor-specific modules.
Requires:
(import sql/jdbc)
Located in:
siscweb-sql.jar
This module provides functions to load drivers, obtain connections, and execute procedures within a transactional context.
procedure:
(jdbc/load-driver name) => #t/#f
Loads the JDBC driver specified by
name
. It is not necessary to use this function when obtaining a connection from a JDBC DataSource, or when using a plug-in, vendor-specific module. Returns a boolean representing the success of the operation.(jdbc/load-driver "org.hsqldb.jdbcDriver")
procedure:
(jdbc/get-connection datasource) => connection
Obtains a connection from the specified JDBC
datasource
.(import util/jndi) (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS"))
procedure:
(jdbc/open-connection url username password) => connection
Opens and returns a connection to the database specified by the
url
parameter, logging in with the givenusername
andpassword
. Theurl
is in the samejdbc:subprotocol:subname
format as in the Java JDBC API.(jdbc/open-connection "jdbc:hsqldb:file:/tmp/my-db" "sa" "")
procedure:
(jdbc/get-vendor connection) => vendor-name
Returns the vendor name, in lowercase, of the database to which
connection
points.
procedure:
(jdbc/call-with-connection connection proc) => value
procedure:(jdbc/call/conn connection procedure) => value
Invokes
procedure
with the givenconnection
. When the procedure terminates or fails, the connection is automaticallyclose()
ed. The passedprocedure
must accept aconnection
as its only argument. The value returned will be that returned byprocedure
.(jdbc/call/conn (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS")) (lambda (conn) (sql/execute conn "SELECT SYSDATE FROM DUAL")))
procedure:
(jdbc/call-with-transaction connection proc) => value
procedure:(jdbc/call/tran connection procedure) => value
Invokes
procedure
within a transactional context. The transaction is committed ifprocedure
returns normally, and rolled back in case of failure or invocation of an escape continuation. The passedprocedure
must acceptconnection
as its only argument. The value returned will be that returned byprocedure
.(jdbc/call/conn (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS")) (lambda (conn) (jdbc/call/tran conn (lambda (conn) (sql/execute-update conn "UPDATE my_table SET my_field = 0")))))
Requires:
(import sql/query)
Located in:
siscweb-sql.jar
This module provides functions to execute queries and map through result sets.
jdbc/call/conn
context, intentional or not, the JDBC ResultSet and Statement
are closed only upon garbage collection. This can be a
particularly insidious problem when using pooled connections,
and will be fixed in the future.
procedure:
(sql/execute connection sql-query [value] ...) => number/resultset
Executes
sql-query
through the givenconnection
.A number of optional
value
s can be specified; these will be bound in order to the placeholders in the query. Date, time and timestamps from srfi-19 can be used to bind to SQL DATE, TIME and TIMESTAMP types.Returns the number of rows updated in case of an INSERT/UPDATE/DELETE query statement, and a result set in case of a SELECT statement. Result sets are lazy lists in the sense of srfi-45. Each element of the list is a hashtable
(field-name => value)
. Multiple result sets are not supported.(sql/execute conn "SELECT * FROM my_table WHERE id = ?" 12345)
procedure:
(sql/execute-query connection sql-query [value] ...) => resultset
Runs
sql-query
and returns a result set.
procedure:
(sql/execute-update connection sql-query [value] ...) => number
Runs
sql-query
and returns the number of updated rows.
syntax:
(sql/map-row procedure ((variable field-name) ...) body) => list
syntax:(sql/for-each-row procedure ((variable field-name) ...) body) => undefined
These two macros facilitate writing code that loops through a resultset. Like their correspectives
map
andfor-each
, the former collects results into a list, while the latter is to be used for side-effects.For each row in the
resultset
, a Schemevariable
is bound to the value of the indicatedfield-name
in the resultset, wherefield-name
is either a string or a symbol.In the case of
sql/map-row
, the value returned by the last expression inbody
is collected into the returnedlist
.(sql/for-each-row (sql/execute-query conn "SELECT id, name FROM person") ((id 'id) (name 'name)) (display (format "~a:~a\n" id name)))
SISCweb includes a number of vendor-specific modules that map Scheme data types onto SQL types and provide extra functionalities, usually in the area of BLOB handling.
Adding support for new vendors is described in the section called “Adding Support for Other Vendors”
Requires:
(import sql/hsqldb)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between HSQLDB and Scheme. Currently only numbers, strings, time types and Java objects are supported.
Requires:
(import sql/mssql)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between Microsoft SQL Server and Scheme. At this time bits, numbers, strings, and time types are supported.
Requires:
(import sql/oracle)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between Oracle and Scheme. At this time numbers, strings (but not CLOBs), and time types are supported. BLOBs are returned as such, but two functions are provided to use them as containers of Java objects.
procedure:
(oracle/read-blob blob) => |java.lang.Object|
Deserializes a Java object from
blob
.;; returns an alist (id => object) (sql/map-row (sql/execute-query "SELECT id, obj FROM my_table") ((id 'id) (blob 'obj)) `(,id . ,(oracle/read-blob blob)))
procedure:
(oracle/write-blob blob java-object) => undefined
Serializes
java-object
intoblob
. Complex Scheme values can also be serialized byjava-wrap
ping them. The blob has to be first inserted using the Oracle EMPTY_BLOB() function, and then read back with a SELECT query.(sql/for-each-row (sql/execute-query "SELECT id, obj FROM my_table WHERE id = ?" 12345) ((blob 'obj)) (oracle/write-blob blob (java-wrap (lambda (x) (* x x)))))
Requires:
(import sql/postgresql)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between PostgreSQL and Scheme. At this time bits, numbers, strings, time types and vectors are supported.
It is possible to add support for other database vendors. The existing modules (such as sql/hsqldb.scm) can be used as base and reference.
At this stage, supporting a new vendor is simply a matter of
defining an association list between SQL types and conversion
procedures. Each conversion procedure accepts the object as
read by the Java Statement.getObject(n)
method, a ResultSetMetaData object, and the column number.
The function should return a Scheme type. If that is not possible (such as it is the case with BLOBs), the function can return a raw Java type, as long as the module provides other functions to transform the Java type into a Scheme type.
Even though SISCweb applies an abstraction layer over characteristics of the HTTP protocol, it is still at times convenient to access the details of requests, responses, sessions and the servlet context in which they live.
For this reason SISCweb provides wrappers around all the methods
of the Request
,
Response
, Session
and
ServletContext
objects. All the procedures
operate on the instances current at the time of invocation.
Requires:
(import siscweb/request)
Located in:
siscweb.jar
This module provides wrappers around the Request object current at the time of invocation.
Because of the large number of methods, they are here sorted in alphabetical order. The descriptions are adapted from the J2EE 1.3 javadoc.
procedure:
(current-request) => javax.servlet.http.HttpServletRequest
Returns the current Request object. Since complete wrappers are provided by this module, this is normally useful to either create Request adapters, or to use the the procedure returned by
request/get-dispatcher
.
procedure:
(request/get-auth-type) => string
Returns the name of the authentication scheme used to protect the URL of the published procedure, or #f if the URL does not require authentication.
procedure:
(request/get-character-encoding) => string
Returns the name of the character encoding used in the body of this request, or #f if the request does not specify a character encoding.
procedure:
(request/get-content-length) => number
Returns the length, in bytes, of the request body and made available by the input stream, or -1 if the length is not known.
procedure:
(request/get-content-type) => string
Returns the MIME type of the body of the request, or #f if the type is not known.
procedure:
(request/get-cookies) => list
Returns a list containing all of the
javax.servlet.http.Cookie
objects the client sent with this request. This method returns the empty list if no cookies were sent.
procedure:
(request/get-date-header name) => time
Returns the value of the specified request header as a SRFI-19 time structure. Use this method with headers that contain dates, such as If-Modified-Since.
If the request did not have a header of the specified name, this method returns #f. If the header can't be converted to a date, the method throws a Java
IllegalArgumentException
.
procedure:
(request/get-dispatcher c-url) => proc
Returns a procedure
proc
that, when invoked with the parametersrequest
andresponse
, will forward the request to the resource located at the givenc-url
. The resource can be dynamic or static.The specified
c-url
may be relative to the path of the published procedure, although it cannot extend outside the current servlet context. If the path begins with a "/" it is interpreted as relative to the current context root. This method returns #f if the servlet container cannot return a RequestDispatcher.
procedure:
(request/get-header name) => string
Returns the value of the specified request header as a string. If the request did not include a header of the specified
name
, this procedure returns #f. The headername
is case insensitive. You can use this procedure with any request header.
procedure:
(request/get-header-alist) => alist
Returns a
(name . value)
association list of all the header names. All the headervalue
s are returned as strings.
procedure:
(request/get-header-hashtable) => hashtable
Returns all the request headers as a hashtable of
name
-value
associations. All the headervalue
s are returned as strings.
procedure:
(request/get-header-names) => list
Returns list of all the header names this request contains. If the request has no headers, this method returns an empty list.
Some servlet containers do not allow do not allow servlets to access headers using this method, in which case this procedure returns #f.
procedure:
(request/get-header-names) => list
Returns list of all the header names this request contains. If the request has no headers, this method returns an empty list.
Some servlet containers do not allow do not allow servlets to access headers using this method, in which case this procedure returns #f.
procedure:
(request/get-int-header name) => integer
Returns the value of the specified request header as an integer. If the request does not have a header of the specified name, this procedure returns #f. If the header cannot be converted to an integer, this method throws a Java
NumberFormatException
.The header name is case insensitive.
procedure:
(request/get-java-attribute name) => jobject
Returns the value of the
name
d attribute as a Java object, ornull
if no attribute of the givenname
exists.
procedure:
(request/get-java-attribute-names) => list
Returns a list of names of the attributes available to this request. This method returns an empty list if the request has no attributes available to it.
procedure:
(request/get-locale) => java.util.Locale
Returns a Java
java.util.Locale
object representing the preferred locale that the client will accept content in, based on the Accept-Language header. If the client request doesn't provide an Accept-Language header, this method returns the default locale for the server.
procedure:
(request/get-locales) => list
Returns a list of
java.util.Locale
objects indicating, in decreasing order starting with the preferred locale, the locales that are acceptable to the client based on the Accept-Language header. If the client request doesn't provide an Accept-Language header, this method returns an Enumeration containing onejava.util.Locale
, the default locale for the server.
procedure:
(request/get-method) => string
Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
procedure:
(request/get-parameter name) => string
Returns the value of a request parameter as a string, or #f if the parameter does not exist.
You should only use this method when you are sure the parameter has only one value. If the parameter might have more than one value, use
request/get-parameter-values
. If you use this method with a multivalued parameter, the value returned is equal to the first value in the list returned byrequest/get-parameter-values
.If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via
request/open-binary-input-port
orrequest/open-input-port
can interfere with the execution of this procedure.
procedure:
(request/get-parameter-alist) => alist
Returns a
(name . (value1 ...))
association list of all parameters and their values.
procedure:
(request/get-parameter-hashtable) => hashtable
Returns a hashtable containing the association between parameter names and lists of the parameter values.
procedure:
(request/get-parameter-names) => list
Returns a list of names of the parameters contained in this request. If the request has no parameters, the procedure returns an empty list.
procedure:
(request/get-parameter-values name) => list
Returns a list of values of the given request parameter, or the empty list if the parameter does not exist.
If the parameter has a single value, the list has a length of 1.
procedure:
(request/get-path-info) => string
Returns any extra path information associated with the URL the client sent when it made this request. The extra path information follows the path of the
SISCAdapterServlet
but precedes the query string. This procedure returns #f if there was no extra path information.
procedure:
(request/get-path-translated) => string
Returns any extra path information after the servlet name but before the query string, and translates it to a real path.
If the URL does not have any extra path information, this method returns #f. The web container does not decode thins string.
procedure:
(request/get-protocol) => string
Returns the name and version of the protocol the request uses in the form protocol/majorVersion.minorVersion, for example, HTTP/1.1.
procedure:
(request/get-query-string) => string
Returns the query string that is contained in the request URL after the path. This procedure returns #f if the URL does not have a query string.
procedure:
(request/get-remote-addr) => string
Returns the Internet Protocol (IP) address of the client that sent the request.
procedure:
(request/get-remote-host) => string
Returns the fully qualified name of the client that sent the request. If the engine cannot or chooses not to resolve the hostname (to improve performance), this procedure returns the dotted-string form of the IP address.
procedure:
(request/get-remote-user) => string
Returns the login of the user making this request, if the user has been authenticated, or #f if the user has not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication.
procedure:
(request/get-requested-session-id) => string
Returns the session ID specified by the client. This may not be the same as the ID of the actual session in use. For example, if the request specified an old (expired) session ID and the server has started a new session, this method gets a new session with a new ID. If the request did not specify a session ID, this method returns #f.
procedure:
(request/get-server-name) => string
Returns the host name of the server that received the request.
procedure:
(request/get-server-port) => integer
Returns the port number on which this request was received.
procedure:
(request/get-servlet-path) => string
Returns the part of this request's URL that calls the
SISCAdapterServlet
. This includes either the servlet name or a path to the servlet, but does not include any extra path information or a query string.
procedure:
(request/get-session [create?]) => javax.servlet.http.HttpSession
Returns the current HttpSession associated with this request or, if if there is no current session and the
create?
is #t or absent, returns a new session.If
create
is #f and the request has no validHttpSession
, this method returnsnull
.To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, a Java
IllegalStateException
is thrown.
procedure:
(request/get-uri) => string
Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. The web container does not decode this String.
procedure:
(request/get-url) => string
Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and server path, but it does not include query string parameters.
procedure:
(request/get-user-principal) => java.security.Principal
Returns a
java.security.Principal
object containing the name of the current authenticated user. If the user has not been authenticated, the method returnsnull
.
procedure:
(request/open-binary-input-port) => binary-input-port
Retrieves the body of the request as binary data using a binary input port. Either this procedure or
request/open-input-port
may be called to read the body, not both.
procedure:
(request/open-input-port) => character-input-port
Retrieves the body of the request as character data using a character input port. The port translates the character data according to the character encoding used on the body. Either this procedure or
request/open-binary-input-port
may be called to read the body, not both.
procedure:
(request/remove-java-attribute! name) => #!void
Removes an attribute from this request. This method is not generally needed as attributes only persist as long as the request is being handled.
procedure:
(request/session-id-from-cookie?) => #t/#f
Checks whether the requested session ID came in as a cookie.
procedure:
(request/session-id-from-url?) => #t/#f
Checks whether the requested session ID came in as part of the request URL.
procedure:
(request/requested-session-id-valid?) => #t/#f
Checks whether the requested session ID is still valid.
procedure:
(request/secure?) => #t/#f
Checks whether this request was made using a secure channel, such as HTTPS.
procedure:
(request/set-character-encoding! encoding) => #!void
Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using
request/open-input-port
.
Requires:
(import siscweb/response)
Located in:
siscweb.jar
This module provides wrappers around the Response object current at the time of invocation.
Because of the large number of methods, they are here sorted in alphabetical order. The descriptions are adapted from the J2EE 1.3 javadoc.
procedure:
(current-response) => javax.servlet.http.HttpServletResponse
Returns the current Response object. Since complete wrappers are provided by this module, this is normally useful to either create Request adapters, or to use the the procedure returned by
request/get-dispatcher
.
procedure:
(response/add-cookie! javax.servlet.http.Cookie) => #!void
Adds the specified cookie to the response. This method can be called multiple times to set more than one cookie.
procedure:
(response/add-header! name value) => #!void
Adds a response header with the given name and value. This method allows response headers to have multiple values.
The
value
parameter can either be a string, an integer number or an SRFI-19 date or time structure.
procedure:
(response/add-headers! alist) => #!void
Adds multiple headers, one for each (
name
.value
) element of thealist
, withvalue
being either a string, an integer number or an SRFI-19 time structure.
procedure:
(response/commit!) => #!void
Commits the response, forcing any content in the buffer to be written to the client, including the status code and headers.
procedure:
(response/committed?) => #t/#f
Checks if the response has been committed. A commited response has already had its status code and headers written.
procedure:
(response/contains-header? name) => #t/#f
Checks whether the
name
d response header has already been set.
procedure:
(response/encode-redirect-url url) => string
Encodes the specified
url
for use in theresponse/send-redirect
procedure or, if encoding is not needed, returns theurl
unchanged. The implementation of this method includes the logic to determine whether the session ID needs to be encoded in the URL. Because the rules for making this determination can differ from those used to decide whether to encode a normal link, this procedure is separate fromresponse/encode-url
.All URLs sent to the
response/send-redirect
procedure should be run through this method. Otherwise, URL rewriting cannot be used with browsers which do not support cookies.
procedure:
(response/encode-url url) => string
Encodes the specified
url
by including the session ID in it, or, if encoding is not needed, returns theurl
unchanged. The implementation of this method includes the logic to determine whether the session ID needs to be encoded in the URL. For example, if the browser supports cookies, or if session tracking is turned off, URL encoding is unnecessary.For robust session tracking, all URLs emitted by a servlet should be run through this method. Otherwise, URL rewriting cannot be used with browsers which do not support cookies.
procedure:
(response/get-buffer-size) => integer
Returns the actual buffer size used for the response. If no buffering is used, this procedure returns 0.
procedure:
(response/get-character-encoding) => encoding
Returns the name of the charset used for the MIME body sent in this response. If no charset has been assigned, it is implicitly set to ISO-8859-1 (Latin-1).
procedure:
(response/open-binary-output-port) => binary-output-port
Returns a binary output port suitable for writing binary data in the response. The servlet container does not encode the binary data.
Flushing the port commits the response. Either this method or
response/open-output-port
may be called to write the body, not both.
procedure:
(response/open-output-port) => character-output-port
Returns a character output port that can send character text to the client. The character encoding used is the one specified in the charset= property of the
response/set-content-type!
procedure, which must be called before calling this procedure for the charset to take effect.If necessary, the MIME type of the response is modified to reflect the character encoding used.
Flushing the port commits the response. Either this method or
response/open-binary-output-port
may be called to write the body, not both.
procedure:
(response/reset!) => #!void
Clears any data that exists in the buffer as well as the status code and headers. If the response has been committed, this method throws a Java
IllegalStateException
.
procedure:
(response/reset-buffer!) => #!void
Clears the content of the underlying buffer in the response without clearing headers or status code. If the response has been committed, this method throws a Java
IllegalStateException
.
procedure:
(request/send-error status-code [message]) => #!void
Sends an error response to the client using the specified status clearing the buffer. The server defaults to creating the response to look like an HTML-formatted server error page containing the specified message, setting the content type to "text/html", leaving cookies and other headers unmodified. If an error-page declaration has been made for the web application corresponding to the status code passed in, it will be served back in preference to the suggested msg parameter.
If the response has already been committed, this method throws a Java
IllegalStateException
. After using this method, the response should be considered to be committed and should not be written to.
procedure:
(request/send-redirect url) => #!void
Sends a temporary redirect response to the client using the specified redirect
url
. This method can accept relative URLs; the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI. If the location is relative with a leading '/' the container interprets it as relative to the servlet container root.If the response has already been committed, this method throws a Java
IllegalStateException
. After using this method, the response should be considered to be committed and should not be written to.
procedure:
(request/set-buffer-size! bufsize) => #!void
Sets the preferred buffer size for the body of the response. The servlet container will use a buffer at least as large as the size requested. The actual buffer size used can be found using
response/get-buffer-size
.This method must be called before any response body content is written; if content has been written, this method throws a Java
IllegalStateException
.
procedure:
(request/set-content-length! length) => #!void
Sets the length of the content body in the response In HTTP servlets, this method sets the HTTP Content-Length header.
procedure:
(request/set-content-type! type) => #!void
Sets the content type of the response being sent to the client. The content type may include the type of character encoding used, for example, text/html; charset=ISO-8859-4.
If obtaining a character output port, this method should be called first.
procedure:
(response/set-header! name value) => #!void
Sets a response header with the given
name
andvalue
. If the header had already been set, the new value overwrites the previous one. Theresponse/contains-header?
procedure can be used to test for the presence of a header before setting its value.The
value
parameter can either be a string, an integer number or an SRFI-19 date or time structure.
procedure:
(response/set-locale! java.util.Locale) => #!void
Sets the locale of the response, setting the headers (including the Content-Type's charset) as appropriate. This method should be called before a call to
reponse/open-output-port
. By default, the response locale is the default locale for the server.
procedure:
(response/set-status! status-code) => #!void
Sets the status code for this response. This method is used to set the return status code when there is no error (for example, for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, and the caller wishes to invoke an defined in the web applicaion, the
response/send-error
procedure should be used instead.The container clears the buffer and sets the Location header, preserving cookies and other headers.
Requires:
(import siscweb/session)
Located in:
siscweb.jar
This module provides wrappers around the Response object current at the time of invocation.
The procedures are sorted in alphabetical order. The descriptions are adapted from the J2EE 1.3 javadoc.
procedure:
(current-session) => javax.servlet.HttpSession
Returns the current Session, or creates a new one if one is not defined yet. Also see the procedure
request/get-session
.
procedure:
(session/get-creation-time) => time
Returns the time when this session was created as an SRFI-19 time structure.
procedure:
(session/get-id) => string
Returns a string containing the unique identifier assigned to this session. The identifier is assigned by the servlet container and is implementation dependent.
procedure:
(session/get-java-attribute name) => jobject
Returns the Java object bound with the specified name in this session, or
null
if no object is bound under the name.
procedure:
(session/get-java-attribute-names) => list
Returns an list of names of all the objects bound to this session.
procedure:
(session/get-last-accessed-time) => time
Returns the last time the client sent a request associated with this session, as an SRFI-19 time structure, and marked by the time the container received the request.
Actions that your application takes, such as getting or setting a value associated with the session, do not affect the access time.
procedure:
(session/get-max-inactive-interval) => seconds
Returns the maximum time interval, in seconds, that the servlet container will keep this session open between client accesses. After this interval, the servlet container will invalidate the session. The maximum time interval can be set with the setMaxInactiveInterval method. A negative time indicates the session should never timeout.
procedure:
(session/get-servlet-context) => javax.servlet.ServletContext
Returns the
javax.servlet.ServletContext
object to which this session belongs.
procedure:
(session/invalidate!) => #!void
Invalidates this session then unbinds any objects bound to it.
procedure:
(session/make-parameter name) => proc
Returns a procedure
proc
that, when invoked, sets or retrieves a Scheme value to/from the a Session attribute namedname
, depending on whether a value is passed or not to. Ifproc
is passed the #f value, the attribute is removed from the Session object altogether.
procedure:
(session/new?) => #t/#f
Returns #t if the client does not yet know about the session or if the client chooses not to join the session. For example, if the server used only cookie-based sessions, and the client had disabled the use of cookies, then a session would be new on each request.
procedure:
(session/remove-java-attribute! name) => #!void
Removes the object bound with the specified
name
from this session. If the session does not have an object bound with the specified name, this method does nothing.
procedure:
(session/set-java-attribute! name jobject) => #!void
Binds a Java object
jobject
to this session, using the specifiedname
. If an object of the same name is already bound to the session, that object is replaced.If the value passed in is
jnull
, this has the same effect as callingsession/remove-java-attribute!
.
Requires:
(import siscweb/context)
Located in:
siscweb.jar
This module provides wrappers around the ServletContext object.
The procedures are sorted in alphabetical order. The descriptions are adapted from the J2EE 1.3 javadoc.
procedure:
(current-context) => javax.servlet.ServletContext
Returns the current ServletContext. Also see the procedure
context/get
.
procedure:
(context/get uripath) => javax.servlet.ServletContext
Returns a ServletContext object that corresponds to a specified URL on the server.
This method allows servlets to gain access to the context for various parts of the server, and as needed obtain RequestDispatcher objects from the context. The given path must be begin with "/", is interpreted relative to the server's document root and is matched against the context roots of other web applications hosted on this container.
In a security conscious environment, the servlet container may return
for a given URL.
procedure:
(context/get-dispatcher c-url) => proc
procedure:(context/get-named-dispatcher servlet-name) => proc
Returns a procedure
proc
that, when invoked with the parametersrequest
andresponse
, will forward the request to the resource located at the givenc-url
. The resource can be dynamic or static.In the first form, the specified
c-url
may be relative to the path of the published procedure, although it cannot extend outside the current servlet context. If the path begins with a "/" it is interpreted as relative to the current context root. This method returns #f if the servlet container cannot return a RequestDispatcher.In the second form, the specified
servlet-name
indicates a Servlet or JSP page named either via server administration or via a web application deployment descriptor.This method returns #f if the ServletContext cannot return a dispatcher for any reason.
procedure:
(context/get-init-parameter name) => string
Returns the value of the
named
d context-wide initialization parameter as a string, or #f if the parameter does not exist.This method can make available configuration information useful to an entire "web application". For example, it can provide a webmaster's email address or the name of a system that holds critical data.
procedure:
(context/get-init-parameter-alist) => alist
Returns a
(name . value)
association list of all the context's initialization parameter names and their values.
procedure:
(context/get-init-parameter-hashtable) => hashtable
Returns a hashtable containing the association between all the context's initialization parameter names and their values.
procedure:
(request/get-init-parameter-names) => list
Returns a list of names of the context' s initialization parameters. If the has no initialization parameters, the procedure returns an empty list.
procedure:
(context/get-java-attribute name) => jobject
Returns the servlet container attribute with the given name, or null if there is no attribute by that name. An attribute allows a servlet container to give the servlet additional information not already provided by this interface. See your server documentation for information about its attributes. A list of supported attributes can be retrieved using
context/get-java-attribute-names
.
procedure:
(context/get-java-attribute-names) => list
Returns a list containing the attribute names available within this servlet context. Use the
context/get-java-attribute
procedure with an attribute name to get the value of an attribute.
procedure:
(context/get-major-version) => integer
procedure:(context/get-minor-version) => integer
These procedures return the major and minor versions of the Java Servlet API that this servlet container supports. All implementations that comply with Version 2.3 must have this methods respectively return the integers 2 and 3.
procedure:
(context/get-mime-type file-path) => string
Returns the MIME type of the specified file, or #f if the MIME type is not known. The MIME type is determined by the configuration of the servlet container, and may be specified in a web application deployment descriptor. Common MIME types are "text/html" and "image/gif".
procedure:
(context/get-name) => string
Returns the name of this web application correponding to this servlet context as specified in the deployment descriptor for this web application by the
display-name
element.
procedure:
(context/get-real-path c-url) => path
Returns a string containing the real path for a given virtual path. For example, the path "/index.html" returns the absolute file path on the server's filesystem would be served by a request for "http://host/contextPath/index.html", where contextPath is the context path of this servlet context.
The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive).
procedure:
(context/get-real-path c-url) => path
Returns a string containing the real path for a given virtual path. For example, the path "/index.html" returns the absolute file path on the server's filesystem would be served by a request for "http://host/contextPath/index.html", where contextPath is the context path of this servlet context.
The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive).
procedure:
(context/get-resource file-path) => url
Returns a string representing a URL to the resource that is mapped to a specified path. The path must begin with a "/" and is interpreted as relative to the current context root.
This procedure allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file.
This procedure returns #f if no resource is mapped to the pathname.
procedure:
(context/get-resource-paths file-path) => list
Returns a directory-like list of all the paths to resources within the web application whose longest sub-path matches the supplied path argument. Paths indicating subdirectory paths end with a "/". The returned paths are all relative to the root of the web application and have a leading "/".
procedure:
(context/get-resource-paths) => string
Returns the name and version of the servlet container on which the servlet is running.
The form of the returned string is servername/versionnumber. For example, the JavaServer Web Development Kit may return the string JavaServer Web Dev Kit/1.0.
The servlet container may return other optional information after the primary string in parentheses, for example, JavaServer Web Dev Kit/1.0 (JDK 1.1.6; Windows NT 4.0 x86).
procedure:
(context/make-parameter name) => proc
Returns a procedure
proc
that, when invoked, sets or retrieves a Scheme value to/from the a servlet context attribute namedname
, depending on whether a value is passed or not to. Ifproc
is passed the #f value, the attribute is removed from the servlet context altogether.
procedure:
(context/open-resource-binary-input-port file-path) => binary-input-port
Returns a binary input port that reads from the resource located at the named
file-path
as an InputStream object.The data in file can be of any type or length. The
file-path
must be specified according to the rules given incontext/get-resource
. This procedure returns #f if no resource exists at the specified path.Meta-information such as content length and content type that is available via
context/get-resource
method is lost when using this method.
procedure:
(context/remove-java-attribute! name) => #!void
Removes the attribute with the given name from the servlet context. After removal, subsequent calls to
context/get-java-attribute
to retrieve the attribute's value will return #f.If listeners are configured on the ServletContext the container notifies them accordingly.
procedure:
(context/set-java-attribute! name jobject) => #!void
Binds an object to a given attribute
name
in this servlet context. If the name specified is already used for an attribute, this method will replace the attribute with the new to the new attribute.If listeners are configured on the ServletContext the container notifies them accordingly.
If a
jnull
value is passed, the effect is the same as callingcontext/remove-java-attribute!
.
procedure:
(context/get-dispatcher c-url) => proc
procedure:(context/get-named-dispatcher servlet-name) => proc
Returns a procedure
proc
that, when invoked with the parametersrequest
andresponse
, will forward the request to the resource located at the givenc-url
. The resource can be dynamic or static.In the first form, the specified
c-url
may be relative to the path of the published procedure, although it cannot extend outside the current servlet context. If the path begins with a "/" it is interpreted as relative to the current context root. This method returns #f if the servlet container cannot return a RequestDispatcher.In the second form, the specified
servlet-name
indicates a Servlet or JSP page named either via server administration or via a web application deployment descriptor.This method returns #f if the ServletContext cannot return a dispatcher for any reason.
Version 2, June 1991
Copyright © 1989, 1991 Free Software Foundation, Inc.
Version 2, June 1991
Table of Contents
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software - to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps:
copyright the software, and
offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a “work based on the Program ” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term “modification ”.) Each licensee is addressed as “you”.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License.
If the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
You may copy and distribute the Program (or a work based on it, under Section 2 in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.