The OLATServlet is the main entry point for user requests from the browser. This
servlet uses Dispatchers to further process a request. This is done by the class
DispatcherAction
. Furthermore, the OLATServlet is responsible
for initializing and configuring OLAT. This is done by calling the
ConfigurationManager
at startup.
DispatcherAction
analyzes the first part of the incoming request
URI and decides which Dispatcher is repsponsible for further dispatching the request.
These Dispatchers are namely:
DMZDispatcher
: Responsible for all requests of users
who are not yet authenticated. DMZDispatcher processess all URIs starting with
/dmz/, namely the login process.
AuthenticatedDispatcher
: Responsible for all requests
of users who have been previousely authenticated. AuthenticatedDispatcher will
check each incoming request if it has an authenticated user associated. If not,
the user is redirected to the login screen. AuthenticatedDispatcher catches all
requests starting with /auth/.
ShibbolethDispatcher
: This Dispatcher catches all
requests comming asynchronuousely from IdentityProviders. Its assigned sub-URI is
"/shib/", please refer to the Shibboleth Protocol for further
infos on Shibboleth.
Besides OLATServlet, there are a few more servlets used within OLAT. Find a brief description of the functionality they provide below:
SecureWebdavServlet
: This is the servlet handling all
WebDAV requests. The servlet is mapped at URI /webdav/. This URI is the same for
every user. The WebDAV contents are assembled for every user after authentication.
StaticsServlet
: This servlet is handling requests for
statics such as imges or CSS and Javascript files. StaticsServlet is mapped to the
sub-URI /secstatic/. This sub-URI is further followed by a handler name (i.e.
/secstatic/HANDLER/. According to the handler name, SecstaticsServlet passess the
request to the handler which registered for the given handler name. Handlers can be
configured in olat_config.xml. A handler must implements
PathHandler
and an alias must be given under which requests
are dispatched. See the configuration of the StaticsModule in olat_config.xml namely
its Path entries for an example.
RSSServlet
: This servlet pretty much does what it says.
It provides RSS feeds for subscribers and is mapped at /rss/.
OLATDevServlet
: This servlet is used for development
purposes. It implements workflows usefuly to the development of OLAT. With this
servlet, developers can edit Velocity pages on the fly by enabling debugging in the
GUI. Furthermore a translation tool helps in translating OLAT to other languages.
The translation tool is accessible through the administration page.
Each User has a UserSession
which stores the windows amongst
other things. The Windows
contains at least one
Window
. A window is the server-side representation of a browser
window. A window has a content-pane (like Swing) to store the "real"
content. Each window is owned by a ChiefController
which is
responsible for the navigation the windows offers, but not for its content. So e.g.
after logging in, the tabs on the top ("home",
"groups", ...) are controlled by the chiefcontroller.
A Controller
is a responsible for a certain business logic /
workflow
Each controller must provide an initialComponent, which is the visual representation of the controller at any given time. The component will be rendered later into a HTML fragment which is part of the whole HTML page. You could think of a Swing Panel which is embedded into some place in the webbrowser window. The code creating a controller and asking for its initialComponent can determine where to visually put the component
Managers within OLAT, by definition, are classes that implement basic services
useful for implementing the actual business logic. The
OLATResourceManager
for instance provides the basic functionality
for handling OLATResources such as creating, reading, updating and deleting. Any
Controller within OLAT that has to deal with an OLATResource should use the
OLATResourceManager and not directly imlement basic functionality. In particular,
Managers wrap all database access.
OLAT provides its own implementation of a filesystem abstraction layer, called Virtual Filesystem (VFS). The VFS represents a tree structure with folders and files within folders much like a regular filesystem. Folders are called containers and files are called leaves. There are different implementations of containers and leaves serving different purposes. These offers the flexibility to change the implementaion of the file and folder classes and may switch to an other storage solution (like database) without rewriting code in the file handling classes.
Both VFSContainer
and VFSLeaf
inherit
from VFSItem
with generic attributes and methods common to both
such as a name, methods to query wether delete or write is allowed and others. The most
important method defined on VFSItem is resolve(String name). This method allows to query
a VFSItem to resolve a path (i.e. /home/user/readme.txt). A path is much the same as a
path on a regular filesystem. Resolve() returns a VFSItem which can be either a
VFSContainer or a VFSLeaf.
The second most important feature of VFSItem is its
VFSSecurityCallback
. A security callback defines what operations
are allowed on the item. VFSSecurityCallback defines whether read/write/list/copy and
delete operations are allowed. If a specific item has no VFSSecurityCallback defined,
all operations are allowed by default. VFSSecurityCallbacks get inherited by all
children attached to an item. So for example, if a container has a security callback set
that denies write operations, the container itself and all of its children would not be
writable. VFSSecurityCallback also allows to define quotas on a object. The
VFSSecurityCallback is checked by the VFS implementation. I.e. if you perform a write
operation, the security callback is checked and an exception is thrown if the security
callback denies write opertaions on the specific item.
There are various implementations of VFSContainer
and
VFSLeaf
already in place. The most handy probably are
LocalFolderImpl
and LocalFileImpl
which
are an abstraction of a local filesystem. These are probably the place of start for all
your VFS tasks. Simply create a LocalFolderImpl with a File pointing to a local folder
as constructor asgument. You can then resolve any file or folder within this local
folder through the resolve() method as described above. You can create new folder or
files through the respective methods of VFSContainer (createChildContainer and
createChildLeaf).
A special type of implementation are all implementations based on AbstractVirtualContainer. Those will be described briefly below.
NamedContainerImpl
: This is useful if you want a given container to show up under a
different name. Note that this name will also be used to resolve the container.
This works much like a symlink on a regular fielsystem.
MergeSource
: This is a powerful but maybe a bit difficult to
understand type of virtual container. It is also the
reason why we chose to do our own implementation of
a virtual filesystem instead of using for example
Apache commons VFS. A MergeSource combines several
containers or leaves into a single container. To
give you an equivalent on a local filesystem, you
would create a new folder, and then symlink folders
or files into this folder to get the same effect. A
MergeSource can merge containers in two different
ways provided by two different methods.
addContainer
will show the given container as a child of the
MergeSource.
addContainersChildren
will show the given container's children as
children of the MergeSource. To avoid naming
conflicts, only one container can be addad via
addContainersChildren
. Furthermore you must define whether it is allowed
to write to this container. If someone wants to
write to a MergeSource, this is only possible, if a
container was previousely added via
addContainersChildren
with the write flag set to true. This feature is
manly used in the WebDavProvider to show folders of
different courses a user is owner in one place which
makes it handy to upload files for different
ressources. This folders are spread on the local filesystem and the MergeSource allow us to see them in one place.
See
StreamedImpl
: This is useful, if you just want to decide on the fly, what the
contents of a file is. StreamedImpl simply directs its InputStream and
OutputStream to whatever you provide at construction time.
With these implementations, you are quite flexible in presenting a filesystem the way you want. Note that you may also combine different implementations of VFSContainer or VFSLeaf. The WebDAV implementation in OLAT makes use of most of the features provided by VFS. At its root there is a merge source. The merge source combines VFSContainers which themselves are wrapped by NamedContainerImpls. This way, the different types of directories exposed by WebDAV can be presented in a sensible way to the user.
See javadoc of the package org.olat.core.util.vfs to get some code examples on the general usage
See VFS javadoc for more information.
OLAT uses the hibernate relational persistence framework to map objects to relational database tables. See the hibernate documentation to learn how to use this framework.
Every persitable class in OLAT inherits from or extends
org.olat.persistence.PersistentObject
. This guarantees that
every class has the following common attributes:
private Long key = null
private Date creationDate
private Date lastModified
To make a class persistable by the hibernate layer one needs to implement getter and setter methods for every attribute added to the class; this is a hibernate convention. Getters and setters can be private if they should not be used by code outside the class.
Every class must also have an interface if it wants to use the lazy initialization options. See the hibernate documentation for more information on this. These are the naming conventions when using interfaces:
Interface:
ClassName.java
Implementation:
ClassNameImpl.java
Every persistable class must have a hibernate mapping description. This mapping file (an XML file) must be stored in the same package as the mapped class. See the hibernate documentation to learn how to write the mapping file. There are several strategies how to write the mapping.