Table of Contents
List of Figures
Abstract
This document is meant for helping mir developers. It is assumed that you have already installed mir and have some basic knowledge on how to use it. However, reading the introduction chapter might also be worthwhile for sysadmins and template designers.Table of Contents
Mir is a fairly large piece of software (over 50.000 lines) written in java. It relies on the tomcat servlet framework for administration and open publishing tasks. However, unlike many other CMS's that generate html on the fly (usually using a cache), Mir writes html pages into a static site. Normally, users that visit the mir site, will only see the static site. Users that want to publish content (open publishing) will contact the dynamic site. Administrators will also contact the dynamic site (see figure).
This architecture is interesting because most page requests will be done on the static site. Static pages are efficiently handled by the web server. It is also interesting because it permits easy mirroring of the static site. Mirrors are simple to set up, since only static pages are involved (see figure).
Here's a list of important terms and concepts used by Mir. Many of these concepts will be further detailed later on in this guide.
As mentioned in the architecture overview, mir
generates a set of static html pages called the static site.
Generating these pages involves using a template engine to
replace variables (representing data) in template files. Template files
are written by web designers.
In many CMS systems, the available variables (data) are hard-coded into the
software. In practice, this is often not flexible enough
for web designers.
Mir allows designers to request the data they need by using
the producer framework, configured in the producers.xml file.
Originally producers were
mostly used to generate pages, but they are now used for a lot of
other tasks. In fact, the producers.xml file provides a
simple, xml-based, programing (scripting) language, so that
site administrators can script their own custom tasks without
changing the java code.
For example, on indymedia.org, producers are used to pull rss
feeds for the global wire.
In the admin web interface, producers appear, for example, on the admin->"Generate manually"->"advanced page": (as Tasks)
Further information on producers may be found at XXX and in the javadoc (classes Producer, NodedProducer, roducerNode...).
Mir uses a postgres database to store it's data.
Currently, the mir.storage, mircoders.storage,
mir.entity, and mir.entity.adapter
packages
are used to access the database in Mir. However, these packages
are obsolete and will be replaced by the
hibernate
object/relational persistence system.
Localizers provide a customization framework that allows different mir sites to behave differently. This is effectively used by various indymedia sites to customize things such open posting mechanisms, open posting validation, data model enhancements, etc.
The MirLocalizer interface describes
the centralized localizer, that may be accessed via the global
MirGlobal.localizer()
function. The central localizer provides accessors to
domain specific localizers
(like MirBasicOpenPostingLocalizer).
Default behavior is provided by the MirBasicLocalizer
and it's associated classes. These classes can be extended to
override default behavior.
A generator is an abstraction for a template engine. Different template engines are supported right now: freemarker (used most often), tal (used by some sites) and velocity (not used at all but supported anyway).
Logging is understood here as "system logs" : information written out to files that may be used to track what is going on in Mir, especially errors and warnings. Mir uses the log4j logging system. This allows us to split logs into different files, making them easier to understand.
Originally, the mircoders packages were meant for local developments, as opposed to the core Mir code. This distinction is now obsolete and these packages will probably be reorganized in future releases.
bundles are key/value pairs in a text file, used for configuration and internationalization
Table of Contents
With Mir, it is now possible to set up arbitrary producers using an xml file.
Producers consist of "nodes". Every node has a specific function. For example, it is possible to use a node to generate a file out of a template. Or it is possible to use a node to enumerate over a collection of articles.
A producer is defined using a Producer tag:
<producer name="content"/>
would define a producer named content.
In a producer, verbs must be defined. Verbs are sub-tasks of a producer.
<producer name="content">
<verbs>
<verb name="new">
</verb>
<verb name="all">
<verb>
</verbs>
<producer name="content"/>
would define a producer with verbs named all and new.
And also the specific nodes and their relationship should be specified:
<producer name="content">
<verbs>
<verb name="new">
</verb>
<verb name="all">
<verb>
</verbs>
<body>
<Generate
generator="/producer/startpage.template"
destination="${config.storageRoot}/index.shtml"/>
</body>
</producer>
we will later learn that this producer generates a single file.
Producers can be made to do different things for different verbs:
<producer name="content">
<verbs>
<verb name="new">
<Set key="count" value="3"/>
</verb>
<verb name="all">
<Set key="count" value="5"/>
<verb>
</verbs>
<body>
<Generate
generator="/producer/startpage.template"
destination="${config.storageRoot}/index.shtml"/>
</body>
</producer>
if a producer is called with a specific verb, first the nodes of that verb
are processed, and only thereafter the body: in our case, if the producer
content is called with verb new, first the variable count
is set to 3, and after that, a file is generated.
Nodes can have arguments. Arguments that amount to integer values can be direct expressions. Arguments that amount to text values can be enriched with expressions between ${}.
Some examples:
<Log message="This article has the following title: ${content.title}"/>
Log has 1 mandatory argument, message. This argument should be text,
but can be enriched with expressions enclosed by ${ and }. In this example,
the title of an article is logged.
<Set key="age" value="34+22*(3+2)"/>
Set has 2 mandatory argument: key and value.
The key arugment is a fixed text,
the value argument is a direct expression, in this case of arithmetic nature.
Expressions, either direct expressions, or expressions between ${}, can contain the following constructions:
| a string literal | 'hello' |
| a numeric literal | 2138 |
| a variable reference | content.title |
| arithmetic operators | 3 + 4 *(2+5-2) |
| string operators | 'hello' ++ ' ' ++ 'Mir' |
| boolean operators | (content.id==3) or (content.id in (5,7,2,8) and (content.title!='hello') |
There are a number of different node types that can be used inside producer definitions. Here an overview:
| Name | Set |
| Purpose | Alter a variable's using a free expression |
| Arguments | |
| key | The variable |
| value | The expression to set the variable to |
| Example |
<Set key="data.result" value="3 + 5 * (5-2)"/>
|
| Name | Define |
| Purpose | Alter a variable's using a string |
| Arguments | |
| key | The variable |
| value | The string to set the variable to |
| Example |
<Define key="filename" value="/var/www/${content.id}.shtml"/>
|
| Name | If |
| Purpose | Create a conditional part of a producer |
| Arguments | |
| condition | The expression to test |
| Sub tags | |
| then | The part to process if the expression evaluates to true |
| false | The part to process if the expression evaluates to false |
| Name | nodedefinition |
| Purpose | Acts as a "funtion" (or "macro") that can be "called" elsewhere in the producer |
| Arguments | |
| name | The name of the newly created node ("function") |
| Sub tags | |
| parameters | a list describing the arguments the "function" must be given |
| definition | the actual body of the function, containing the code that should be executed. Note that this may contain a <sub/> tag that is replaced by the child nodes of the calling node (FIXME is this true???) |
| Name | Log |
| Purpose | Log a message in the producer log |
| Arguments | |
| message | The message to log |
| Name | Enumerate |
| Purpose | Enumerate over the results of a query |
| Arguments | |
| key | The variable name that receives the enumerated record |
| table | The table that is used to enumerate over |
| selection (optional) | The condition (where clause) of the query. |
| order (optional) | The order in which the results of the query are enumerated. |
| skip (optional) | The number of records to skip |
| limit (optional) | The maximum number of records to enumerate |
| Sub tags | |
| This node can have subnodes that will be processed for every enumerated record | |
| Name | List |
| Purpose | Store the results of a query into a variable |
| Arguments | |
| key | The variable name that receives the result list |
| table | The table that is used to select from |
| selection (optional) | The condition (where clause) of the query. |
| order (optional) | The order in which the results of the query are put into the list. |
| skip (optional) | The number of records to skip |
| limit (optional) | The maximum size of the list |
| Name | Batch |
| Purpose | Divide the results of a query into batches |
| Arguments | |
| key | The variable name that receives the batch |
| infokey | The variable name that receives meta information on the batches |
| table | The table that is used to select from |
| batchsize | The size of a batch (the first batch however varies in size) |
| selection (optional) | The condition (where clause) of the query. |
| order (optional) | The order in which the results of the query are put into the list. |
| skip (optional) | The number of records to skip |
| process (optional) | The maximum number of batches to process |
| minbatchsize (optional) | The minimal size of the first batch |
| Sub tags | |
| batches | The part to process for every batch |
| batchlist | The part to process once with the meta info |
| Name | Generate |
| Purpose | Generate a page using a generator (i.e. an abstraction of a template) |
| Arguments | |
| generator | the generator to use |
| destination | the specification of the destination. |
| parameters | Additional configuration info for the generator (for freemarker this now only contains the wanted encoding, empty for the default). |
| Remarks | This node is used to have an actual page generated. The generator parameter usually is the name of a template. The destination is the file to be generated. Variable references are possible in all arguments, and, especially for the destination attribute, widely used. |
| Example |
<Generate generator="/producer/content.template" destination="/var/www/${content.date.formatted.yyyy}/${content.date.formatted.MM}/${content.id}.shtml"/>
|
| Name | DeleteFile |
| Purpose | Delete a file |
| Arguments | |
| filename | The filename of the file to delete |
| Name | SetFileDate |
| Purpose | Set a file's date |
| Arguments | |
| filename | The filename |
| date | The date to use |
| Name | Resource |
| Purpose | Make a message resource bundle available |
| Arguments | |
| key | The variable in which the bundle will be stored |
| bundle | The bundle to use |
| language (optional) | The specific language to use |
| Name | Execute |
| Purpose | Execute a script |
| Arguments | |
| command | The command to execute |
| Name | ModifyContent |
| Purpose | Modify a field of an article |
| Arguments | |
| key | The variable containing the article |
| field | The field to modify |
| value | The value to set the field to |
| Name | MarkContent |
| Purpose | Mark an article as produced |
| Arguments | |
| key | The variable containing the article |
A Producer is a set of tasks, scripted in xml. Producers allow
mir installations to have their own actions that can be called for
instance when a new article is posted. Originally producers were
mostly used to generate pages, but they are used for a lot of
other tasks such as pulling rss feeds for the global wire on
indymedia.org. Producers are added and configured through the
producers.xml file.
The xml nodes contained within a <producer>
tag in the producers.xml file define
a small program.
This program (or script) may contain constructs
such as if clauses, loops and variables... The program is parsed into a
tree of ProducerNodes (figure). The root of this tree is defined in a
NodedProducer (which is the only class that currently implements
the Producer interface). When the Producer is executed, the
produce methods of each node are recursively called, effectively
executing the program as it was scripted.