CoW: Users and Developers Guide

1. Introduction
Files and directories, documents and folders, disks and memory sticks, laptops
and games machines, TV time-shifters and corporate IT systems. Data data
everywhere, and never a drop to drink, as the Ancient Mariner could not have
dreamt of saying. Wouldn't it be nice to be able to view your filesystem as a
website, to be able to edit from multiple machines with and without network
connections, to be able to have your own local copy and also share it with
friends and colleagues, and to not have to worry about merging it all back
together?
CoW is a "Controllable Wiki" and CMS that supports collaborative document
creation with asynchonous off-line editing. CoW is desiged to make it easy to
add interaction to static websites, and to support concurrent editing and
off-line working with straightforward synchronisation (using Subversion). The
system also serves as a test-bed for experiments in controlled languages for
round-trip ontology engineering (from the GATE project:
http://gate.ac.uk/).
CoW is based on Grails, Groovy, Subversion, Canoo and
J2EE, and is hosted on SourceForge in the
GATEWiki project.
Currently CoW includes:
- a wiki language with a JavaCC parser
- a CMS persistence and versioning backend using Subversion
- simple display and edit of wiki pages and other static content using
Grails
- a version of the Grails Spring Security (Acegi) plugin that includes editing
of the user data and assigns permissions to wiki areas based on their DB id
- user registration using the Captcha plugin
- webtests using Canoo Webtest
- a minimal Hypersonic DB to store pointers to wiki areas and
user/role/permission data)
The system has two modes, workstation and server; the former does no user
management, the latter uses Spring Security.
2. Overview
Wikis are about allowing groups of people to create and edit sets of
interlinked web pages with minimal effort and minimal learning of software
conventions and features. Typically they achieve this by
- having an edit link from each page that runs a browser-based editor
- allowing pages to be written in simple plain text with a small number of
formatting conventions (e.g. *bold*)
- supporting creation of pages by directing links for non-existent pages to
a create and edit page
- allowing multiple users to use the system simultaneously (and sometimes to
edit the same document simultaneously)
Content Management Systems (CMSs) provide persistence, versioning, metadata
management, upload and browsing of sets of documents and other resources.
CoW is different from other wikis and CMSs because:
- it is designed from the ground up to support concurrent editing and off-line
working with straightforward synchronisation using SVN
- it uses the YAM language, which
- outputs LaTeX as well as HTML
- allows paths as links (i.e. does not limit the namespace to a single
directory like e.g. JSPWiki does) and consequently allows a
tree-structured page store (and later graph-structured navigation via an
ontology)
- it allows mixing of all types of files in its page store (which is just an
SVN sandbox, in fact)
- it supports versioning and differencing via SVN, and allows other tools that
manipulate SVN repositories to be used with the wiki data (e.g. Tortoise,
Eclipse, ViewVC, etc.)
- it supports embedded CLOnE (Controlled Language for Onotology Editing), and
therefore the GATE team's experiments with applications that store their
data in semantic repositories whose schema is user-defined and maintained
No available wiki in Java that we could find has good SVN support. Using SVN
as a backend gives us:
- off-line edit - simply checkout the pages and edit to your heart's content
while off-line
- edit with other tools, not just the web interface
- management of authorship-related metadata such as how many lines added,
difference between versions and so on
- a stable and reliable versionning system that's been proved in production
use by 000,000s of developers
- concurrent editing
CoW is partly intended to be an experimental framework for a new type of
website in which
- the database is replaced by a knowledgebase (using
OWLIM)
- the knowledgebase is defined and populated using CLOnE
- concurrent changes are managed as in CVS or SVN (check out, edit, update,
merge, etc.)
(In fact perhaps that isn't a wiki at all, but a new type of literate
database...)
The system is licenced under the GNU General Public Licence
version 3 (GPL 3) except where otherwise stated.
3. Information for Users
This is incomplete :-(
3.1. Modes
CoW has two operational modes:
- Workstation mode, where it runs on a personal machine and works off file
trees that are also in active use by the machine's user
- Server mode, where it manages file trees that are not generally subject to
change by other processes.
When you use CoW on your own machine it will be in workstation mode; when
you're using it over the web on another machine it will be in server mode.
3.2. Register, Log in
When CoW is running in server mode, it is necessary to create an account and
to log in before being allowed to edit pages. Some pages will also not be
accessible for reading unless an administrator adds you to the appropriate
group. To register, go to the login page and follow the register link.
3.3. Create a new wiki page
To create a new wiki page you can either:
- edit an existing page and add a relative link to a non-existent wiki page
(the wiki will then link this to a "create new page" facility)
- use the "new page" link from directory listings
- create a new .yam file under your wiki-managed SVN sandbox
Warning: if you create a new wiki page then the directory containing the
page gets upgraded to SVN 1.4 format and you will then need to use an SVN 1.4+
client to access it.
3.4. Edit a wiki page
When you have permission to edit a page that you're viewing, two links will
appear:
- "Edit": this will start a WYSYWIG editor (FCK Edit)
- "(with form)": this will forward to a web form page to edit the wiki page
with
When using 1., you can generally ignore YAM syntax
and work like you do in a word processor - e.g. hit the "B" button to make
text bold, or the "I" button to make it italic, etc. When you're finished,
hit the save button (it looks like an old floppy disk). There's one exception
to ignoring YAM: because the edit is converted back to YAM afterwards, if you
include YAM syntax in your edit you'll need to escape it. Do this by putting
a backslash in front - e.g. \*.
When using 2. use YAM syntax (here's a short
summary, which also appears below the form while
editing).
3.5. Create a new wiki space
NEEDS UPDATING. currently only available to administrators, who should go to
the top-level cow page and follow the links
To create a new wiki space you can either:
- browse for an existing SVN sandbox
- get the wiki to create a new sandbox for you
In the former case you can choose any existing SVN-controlled file tree and
CoW will allow you to create, share and update YAM files in that tree.
3.6. Report a bug
To report bugs, first please check that they've not been reported already!
Then add a report to
the bug
tracker, including information about the platform you're running on and all
details necessary to reproduce your problem.
4. Information for Developers
4.1. Roadmap
The development roadmap and wish-list is recorded in the backlog document, and currently active tasks list.
4.2. Checking out the code
To check out CoW from Subversion first decide if you want to check out a copy
of Grails HEAD and Jetty while you're at it. If so do this:
svn co https://gatewiki.svn.sourceforge.net/svnroot/gatewiki/trunk gatewiki
If not, do this:
svn co https://gatewiki.svn.sourceforge.net/svnroot/gatewiki/trunk/cow cow
If you do the latter you'll need to set properties in build.xml to point to
your own installation of Grails (and of Jetty if you want to run in
production). (Also, if you put CoW in a directory not named cow you will
need to change projectName in webtest/conf/webtest.properties to get the
Canoo tests to work.)
4.3. Selecting Modes
To select the mode (see above) use
- -Dgate.cow.mode=workstation
- -Dgate.cow.mode=server
Workstations include laptops and are expected to be off-line from
time-to-time; servers are expected to be always connected (and always have
accses to the relevant SVN repositories).
4.4. Building and testing CoW
CoW is built with ant. For more documentation do
ant help in the cow directory. To run CoW see next section.
Currently the build file
- assumes that ../grails and ../jetty contain Grails and Jetty (see the
properties defined in build.xml and change as necessary, or override in
a build.properties file in the build directory)
- requires Cygwin if you're on Windoze
To build CoW from a clean checkout, assuming that grails is in the same
directory:
- cd grails && ant clean jar
- cd ../cow && ant upgrade
- if the upgrade overwrote your nice shiny build.xml, svn revert it
- ant cruise
The cruise target does a clean build and runs the Grails unit tests, the
Java-only tests (for YAM etc.) and the Canoo webtests. The war target
creates a WAR file which can be deployed using the deploy target. Other
useful targets:
- webtest-workstation, webtest-server: run webtests for either mode
- webtest-quick: run a minimal test against an already running server; you can
use this to run webtests while developing, for example, or against the
production server to get some timing data (when running in production you'll
need to uncomment the line to set the context path to / in
webtest.properties)
See ant help for more details.
Note that there are some bugs in ant target ordering (workaround for most of
them is to run ant cruise once before doing anything else):
- when ant doc has never been called a webtest-workstation fails
- have to run ant webtest at least once before can do ant run-dev after ant
clean
- to generate the log4j properties for the java- targets you need to call ant
war
4.4.1. Upgrading to new Grails versions
- svn up && ant clean jar in grails
- check compatibility between cow/lib/* and grails/lib/* (the script
bin/check-jars.sh can help)
- change build.xml to reference new groovy jar if needed
- ant clean in cow
- grails upgrade in cow
4.4.2. Using the YAM Tests
The test suite uses a bunch of .yam and compiled .html files in
cow/test/resources. After running the tests the script
cow/bin/check-errors will check for failures and, when these are caused
by incorrect translations, display a (tk)diff of the actual and the correct
output.
Note: when updating to new versions of yam2html the test resource
yam-minimal-no-includes.html needs to be selectively merged with
yam-minimal.html. First update the latter to reflect the translation
changes, then:
- create a patch against the repository minimal file:
- svn diff yam-minimal.html >minimal.patch
- apply that to the no-includes file:
- patch -o new-no-includes.html yam-minimal-no-includes.html minimal.patch
- overwrite the working copy:
- mv new-no-includes.html yam-minimal-no-includes.html
- check that it worked:
- svn diff yam-minimal-no-includes.html
4.5. Running CoW
The ant run-dev target does a Grails run-app and ant run-prod runs a
non-Grails Jetty instance on the CoW WAR. ctrl-c will shut down
Jetty. ctrl-c of Ant does not, however, cleanly shutdown a Jetty forked from
Ant. For a clean shutdown with correct execution of all shutdown code, run ant
shutdown-prod You may supply an optional port on which Jetty will listen for
the shutdown signal, and a password key to listen for, with
-Djetty.shutdown.port and -Djetty.shutdown.key. Defaults are cleartext in
the build file.
Note that the first time the system runs it will create a .cowrc.d directory
(or cowrc.d on Windoze) in your home directory containing help
documentation, a DB etc.
4.6. Structure
CoW is made up of the following components (and numerous 3rd party libraries):
- the GATE YAM library, which lives in gate.yam
- the GATE versioning library (basically SVNKit), which lives in
gate.versioning
- the GATE utilities classes, which live in gate.util
- CLoNE and CLoNE QL, which live in gate.clone (not currently released)
- the CoW Grails webapp
4.6.1. Main classes and Grails objects
The CoW webapp is organised around the concept of wiki/content areas, which
are file trees stored in SVN. What CoW then provides is
- serving of static files (HTML and otherwise) as normal
- the ability to create and edit YAM files in normal Wiki fashion
- the ability to upload files and directories, and browse the directory trees
(subject to authorisation, of course)
CoW is implemented using Grails. The Grails MVC model works like this:
- domain classes are persistent objects that model the domain
- controllers are classes that handle requests and do related logic
- actions are methods (actually closures) on controllers that relate to
different types of request; actions build models which are then passed on to
views
- views are JSPs (actually their Groovy equivalent, GSPs) which act as
parameterised HTML for presentation
Or, put another way, the Grails web application architecture has four main
components:
- Controllers triage requests and use Services to build Models which are
forwarded to Views.
- Services encapsulate business logic and the more complex Model
manipulations.
- Domain classes handle persistence and participate in Models.
- Views handle presentation.
In CoW we have:
- Wiki, the main domain object
- WikiController, which handles viewing and editing wiki file trees, YAM files
and so on
- AdminController, a (mostly generated) controller that allows creation and
maintenance of wiki areas, people and their roles and so on
- a bunch of controllers supporting Spring Security configuration
Example:
- Let's say that we have a wiki area for a directory called
/web/gate-server/html with the id 9.
- A simple page display looks like this http://localhost:8080/cow/wiki/show/9/
and will pick up any index.html that exists there.
- Clicking on relative links will lead us to the other pages, which are served
from the file system within the CoW app, e.g.
http://localhost:8080/cow/wiki/show/9/projects.html
- When looking at an HTML file that has a .yam associated with it, an "Edit this
page" link will appear.
- When looking at any page a "List directory" link will appear.
- A "help" link is always present, which points to the CoW documentation in
the user's ~/.cowrc.d directory.
4.7. Authentication and Authorisation
4.7.1. Wikis and Roles
This section gives some examples of roles and the URLs that they relate
to (stored in Requestmap).
For example, roles on the gate.ac.uk site:
- gate-user: GATE team members / committers
- other-user: other logged-in users
- anonymous: anyone not logged in
The default roles are:
- Administrator
- Wiki Team (people on the team running the site)
- User (the default when a user registers themselves)
- Anonymous: anyone not logged in
The default accounts are:
- scott/tiger (with role Administrator)
- wiki-team/wiki-team (with role Wiki Team)
- user/user (with role User)
Wikis, URLs and roles examples for the example (GATE) site:
| Id | Content | Reader URL example | Readers | Writer URL example | Writers |
| 1 | CoW help docs | /show/1/ | all | /edit/1/ | admin, gate-user |
| 2 | main GATE HTML (gate-server/html) | /show/2/ | all | /edit/2/ | admin, gate-user |
| 3 | public wiki (gate-extras/pubwiki) | /show/3/support.html | all | /save/3/support.html | other-user, admin, gate-user |
| 4 | SALE stuff (sale) | /show/4/ | all | /preview/4/ | admin, gate-user |
| 5 | SALE internal (sale/internal) | /show/5/index.html | admin, gate-user | /edit/5/conventions.html | admin, gate-user |
The data model contains four classes:
- Person (name, authorities, Authority (role, people), Requestmap (url to role)
- Wiki: requestmaps:[Requestmap] (m-m)
4.8. Configuring mail for user registration
In cow/grails-app/conf/AcegiConfig.groovy
4.9. Referencing and regeneration
The problem is that a create/rename/delete/modify operation on a .yam should
be cascaded through any files that link to or include it. The relevant data
is what a file "linksTo" and "includes". Regeneration is needed:
- if the requested output (e.g. a .html) is younger than the .yam file
- if any included files have been created, modified, renamed or deleted
- if any linked files have been renamed, added or deleted
This information needs to be maintained in a single dependency graph for each
Wiki area. This is coded in class Dependencies.
If we can guarantee that all necessary regeneration and dependency maintenance
is done whenever any generation is done, then the graph can be assumed to be
consistent. In workstation mode that's an open issue because of updates from
other tools but in the worst case we can periodically or on request regenerate
all the output files to ensure consistency.
Referencing events
- page or directory is
| created | out-dates all linkers and includers |
| renamed | out-dates all linkers and includers |
| deleted | out-dates all linkers and includers |
| modified | out-dates all includers |
Event sources
- CoW
- svn up
- in workstation mode all sorts of editors etc.
Possible event handlers (using and maintaining a dependency graph)
- YamFile.generate
- WikiController.show/create/etc., perhaps complemented by SVN notifications
- a separate process
The current design is to use YamFile.generate.
4.9.1. Serialization
Dependencies are serialized to the directory conf.gate.cow.dbs, one file per
wiki. They are deserialized lazily, as required.
4.9.2. Speed of Running SVN Status
As noted above, YAM files managed by the wiki can be changed in several ways:
- user makes edits via the sandbox in the filesystem
- user updates the sandbox with changes from the repository
- user makes edits via the wiki
- user asks the wiki to update
In each of these cases we need to regenerate any files that are dependent on
the changes (e.g. a .html that is older than its .yam; a YAM file which
refers to a wiki page which no longer exists; etc.).
There are a number of
strategies that might be adopted to determine what needs regenerating:
- a low-priority process that inspects the filesystem directly
- a listener that receives notifications from the SVN repository
- a process that runs svn st to get a report on files that have changed
For option 3., the statistics in this table are interesting. They give an
indication of how long it takes to do an svn st on the SALE tree (which is
more than 5Gb of data in more than 100,000 files.
| svn st on the sale tree (from cold)
| svn st -u on sale (filesystem cached)
|
| First run | Tenth run |
|
real 0m58.839s
user 0m5.236s
sys 0m3.576s
|
real 0m2.380s
user 0m1.604s
sys 0m0.504s
|
|
| First run | Tenth run |
|
real 0m33.331s
user 0m3.772s
sys 0m0.852s
|
real 0m31.082s
user 0m3.280s
sys 0m0.972s
|
|
The local status check (which doesn't go to the network to check on repository
changes) takes around a minute from cold, but subsequently (when the operating
system has had a chance to cache parts of the file system) only takes a couple
of seconds. The network check (svn st -u) stays pretty constant around 30
seconds.
(Tests done on a 2GHz Pentium M with 1Gb RAM running Ubuntu Dapper on a
broadband connection.)
4.10. Sourceforge notes
4.11. Misc notes
- Grails MVC
- A request taht hits the application context path (e.g. "cow") is first
filtered according to the rules in conf/...UrlMappings.groovy and then
assigned to a controller/action when there is a match. Parts of the
request are assigned to the params property of the controller (often
including the id of a domain object).
- The action either renders a view directly or returns a map (model)
which is then forwarded to a view by Grails (a view is typically a GSP).
- Views are decorated by layouts (using some Grails tags built on top of
Sitemesh).
- The view is served to the requesting client.
- to check out the grails reference docs:
svn co http://svn.codehaus.org/grails/trunk/grails-doc/ grails-doc
- IntelliJ
- download the IDEA from
http://www.jetbrains.com/idea/download/index.html#linux
- unpackage the tar file to some place in your disk, e.g. userhome/apps/
- Have a look the InstallLinux-tar.txt in idea home, where you can see how
to lauch it.
- One thing worth mentioning is to increase the JVM heap size, so that you
idea can perform faster. To adjust the value of JVM heap size open
bin/idea.vmoptions and modify the -Xms and -Xmx parameters.
- After you open your Intellij first time, you should see a plugins link on
the top-right screen. If not, use Ctrl+Alt+S to open the IDE settings
window, then goto plugins tab, where you should see all the installed
plugins. Next, click on the available tab and search "Groovy". Then you
should find the JetGroovy plugin. After installation of JetGroovy plugin,
you need to restart your IDEA.
- Now you open the IDE settings window again, you should see the
Groovy&Grails icon on the left of the window. Click on it and set your
local Groovy and Grails installation directory.
- Set your project JDK from Platform settings.
- To import Cow, click on the New Project from the File tab, then choose
"Create project from existing sources", Next to select the location of
your local cow.
- Automatic formatting: goto IDEA settings and find the Global Code Style.
Set the tab, indent and etc. to the GATE conventions. Then once you open
each source file, you can use Ctrl+Alt+L or right-click on the file name
and select reformat code.