Hello all.

If you remember back some time, there were some writings on the Roller
mailing list concerning multi-domain support in Roller (This link
might help refresh your memory:
http://mail-archives.apache.org/mod_mbox/incubator-roller-dev/200603.mbox/[EMAIL
 PROTECTED]).

I am writing now because we are quite close to a production release
and we are now hoping that our work can be integrated as a part of the
Roller project. Our hope is that you will see that this extension, by
enabling larger scale deployment of Roller, is an extension that might
bring roller to even more widespread use. As a guideline when
we designed and implemented this extension, we made an effort to
modify as little as possible of the roller source code. This was both
to ease upgrades and to make it possible to easily use Roller with or
without multi-domain support. However, you are not forced to accept all
our patches. In addition to extending Roller with a
multi-domain model, we have also:

 * done a translation for both Norwegian languages (nynorsk and
   bokmål)

 * and we have made some improvements to the Roller source to
   facilitate our extension, (basically these include better support
   of the Norwegian languages, and converting <c:out ... to <c:url
   where that was needed). These changes don't alter Roller's behavior
   and does not introduce additional complexity.

As a minimum we hope that these two categories of patches will be
included.

The patches and user documentation are provided for review at:

http://users.linpro.no/kjellm/roller-patches.tar.bz2
http://users.linpro.no/kjellm/userguide_for_multidomain_en.pdf

I have included below a document describing the changes that has been
done. This document also enumerates all the patches with some
commentary on why they are needed.

Best regards

--
Kjell-Magne Øierud
Systems Consultant
Linpro AS


--


                    Multi-Domain Support In Roller

                 Henning Kulander and Shervin Asgari
                            June 27th 2006

ABSTRACT

This document explains what changes Linpro made to Roller 2.1 in order
to use it in a large scale deployment for 26 (currently) newspapers in
Norway. It also explains how the system is used.


INTRODUCTION

Linpro is a consulting company in Norway that specialize in services
running on Linux. We were hired by a company in Norway that owns a
large number of news papers (50+). They had used some time evaluating
different blog solutions, and had more or less decided to use Roller.

The biggest challenge was that they needed to serve separate blog
servers for all the different news papers, with separate lists of
blogs, the possibility to use the same blog name and handle on
different blog servers etc. This was a problem they had found no
adequate solution for in any current blog systems. So it was decided
to add this to Roller. One alternative would be to install Roller 50
times with 50 databases and try to administer them all.

The requirements was:

 * Enable use of same handle for different blogs on different domains

 * Enable use of same blog on different domains (shared blog), and
   again the blog should blend in with the news site you are currently
   viewing.

 * An administration interface to administer the domains

 * Enable different look and feel for each news paper to make the blog
  "blend in" with the news site

 * A front page (planet) with latest blog entries from current domain

Requirements not yet met are:

 * An administration interface to let a selected user in a domain
   administer his own domain with related blogs.

 * Enable searching in all blogs on the current domain

 * Control what domains a user is allowed to log in to


THE SOLUTION

After some consulting with people on the Roller mailing list it was
decided to go for a filter based solution. This would not require deep
changes in the Roller code base, so it would be easier to develop on
our own.

We have chosen to run Roller under /blog/ instead of /roller/, as this
is easier for the users. The filter filters everything coming to
/blog/domain/, finds the right website in an association table and
forwards the request to the normal servlet in the traditional form
(/blog/page/handle). In addition it creates wrappers for the request
and response. The point of the wrappers is to override URLs and
redirects so the user is not moved back to the main Roller-site (The
real address for the Roller server). The URLs are written back to the
/blog/domain/ form, and then re-translated from that form to the form
seen by the users (http://domain/blog/*) by a URLRewriteFilter. The
job of translating URLs like http://domain/blog/ to the /blog/domain
form is left to mod_rewrite in the Apache web server.

To enable this functionality, a DomainManager was added, and three new
tables with corresponding POJO-implementations (only two are currently
in use). The DomainManager needed to be added to RollerManager so it
can be used like the other managers. The URLs are picked up by
DomainFilter, which creates wrappers for the Response and Request
objects. The DomainFilter is also responsible for finding the correct
blog by inspecting the handle given in the request, finding this
handle in the DomainWebsite table, which points to the Roller Website
object for the blog. The request is then forwarded to that website
using its old handle and a normal Roller-URL.

In addition the URLs generated throughout Roller needs to be sent
through encodeURL in the wrapper for Request and Response. This
resulted in quite a few changes in velocity macros.  All these changes
consists in sending the URL through pageHelper.strutsUrlHelper(). This
in turn calls the encodeURL method in the wrapper. In addition,
SearchServlet and *WeblogCalendarModel needed to be
changed. SearchServlet needs to use another context initializer so the
pageHelper object is available in the velocity scripts,
WeblogCalendarModel needs to call encodeURL on the URLs they create.
This enables all URLs to be rewritten to the form
/roller/domain/(service)/(domain)/(handle) on the way out, so the user
still thinks he is on the domain. In addition, these changes enables
the use of UrlRewriteFilter in Roller, so you can do whatever magic
this can do. I use UrlRewriteFilter to rewrite the
/roller/domain/(service)/(domain)(handle) URLs to the more user
friendly form of http://(domain)/(service)/(handle). The rewrite
patches will also enable other forms of URLrewriteFiltering that other
users might require.

This takes care of the first two requirements. The third requirement
was solved by creating a new interface and adding it to the
admin-menu. This interface gives the administrator a list of available
domains, and the option to edit them, or create a new domain. A new
domain needs a domain name, which is the domain name the user sees in
the URL, ie (www.mynewspaper.no <http://www.mynewspaper.no/>). When
the administrator edits this domain, he can add websites to the domain
and give it a handle in this domain. This list is then used by the
filter to find the website.

To solve the fourth requirement, a new theme was made. This theme is
very specific to our customer, and will therefore not be made publicly
available at this time. The way the theme work is to use the $host
variable in the velocity script to dynamically include HTML-components
unique for each news paper. These components are in turn downloaded
from the news sites periodically using a server side script. These
components includes CSS, menu icons etc. from the different news
sites. This theme is then used as the default theme on all blogs. The
look of the theme will be different depending on the included
components.

The Roller planet did not meet our requirements. It did not seem to be
easily themeable, it was difficult to get it running stably and it
seemed to be quite difficult to enable a domain model here. We did an
evaluation of different planet solutions, and chose to use
Planetplanet in our setup. This seemed to be a flexible and
light-weight planet that would serve our needs quite well. The planet
is available as a front page on /blog/, so this is the first thing the
user will see when they enter the blog section of the news paper. This
is handled by apache by overriding ^/blog(|/|/index.jsp)$ and sending
requests to a static html generated by planetplanet. The configuration
for planetplanet is automatically generated by a script that reads the
domainwebsite and domain tables from the database, this script also
generates cron-scripts that are used for updating the planets and
fetching HTML-components for the themes. So the result is one
planetplanet for each domain in Roller, containing the websites for
this domain and the domains native look.

In addition there was a requirement that the solution be available in
the two major written languages in Norway (Bokmål and Nynorsk). Our
customer translated the properties file to these languages, and we
integrated them. But to ensure that the language is controlled by the
page a viewer is watching, and not by that users profile, we had to
make a tiny patch for LanguageUtil.java. We are also using email
addresses for login, so the input field had to have a larger max size.


CAVEATS 

This solution is now considered to be in a production ready state. But
there are still things that could be improved.

The most urgent need for improvement is to add a new administration
level for domain administrators. This could be done by adding a new
userrole called "domainadmin". A domain administrator would then be
associated with his domain through domainuser, and with the role
through userrole. A user with these associations whould then be able
to administer what blogs are available in his domain. This job is now
left to a central administrator.

The procedure to create a new domain with a set of blogs is now to
create the users as the administrator user, create blogs for these
users, create the new domain, associate the blogs with the domain,
link users to the domain and add an editor to the blog (The latter is
OPTIONAL). This is quite time consuming, as the administrator needs to
go through many different web forms. And login as the created users to
create the blogs for them. This procedure needs to be simplified so
the administrator can just create the domain and a domain
administrator. The domain administrator must then be able to create
new blogs with a new user as owner in one simplified form, where all
the administrator needs to enter is User full name, email-address
(used as username), password, Name of blog and handle. The rest will
get default values which can be changed by the users at a later time.

The news papers have legal responsibility for the content they
publish. The editor for the news paper must therefore be able to
remove or edit entries in any blog under his domain in case a blog
contains material that could result in legal issues.  To solve this,
we have enabled the administrator to link users to a specific
domain. This adds the user and domain in the domainuser table. The
interface lists all users, and allow the administrator to choose which
user he wants to add to the domain. Subsequently, when accessing the
'add editor' interface, only the users linked to the domain in
question is viewed for election. This is to ensure that only users
from the specific domain is allowed to be an editor.


THE PATCHES USED IN THIS SOLUTION

Patches that enable URLs to be rewritten:

(Add context to be used later for URL rewrite)
./src/org/roller/presentation/search/SearchServlet.java.patch

(Rewrite URLs)
./src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java.patch
./src/org/roller/presentation/weblog/tags/BigWeblogCalendarModel.java.patch
./src/org/roller/presentation/website/actions/UploadFileFormAction.java.patch
./web/theme/bannerStatus.jsp.patch
./web/WEB-INF/classes/navbar.vm.patch
./web/WEB-INF/classes/searchresults_day.vm.patch
./web/WEB-INF/classes/searchresults.vm.patch
./web/WEB-INF/classes/website.vm.patch
./web/WEB-INF/classes/flavors/rss.vm.patch
./web/WEB-INF/classes/comments.vm.patch
./web/WEB-INF/classes/rssmacros.vm.patch 
./web/WEB-INF/classes/weblog.vm.patch
./web/weblog/WeblogEdit.jsp.patch 
./web/weblog/WeblogQuery.jsp.patch
./web/weblog/CommentManagement.jsp.patch 
./web/website/UploadFile.jsp.patch 
./web/website/YourWebsites.jsp.patch 

(Rewrite URLs and make description translatable:)
./contrib/plugins/src/org/roller/presentation/velocity/plugins/readmore/ReadMorePlugin.java.patch

----------------------------------------------------------------------
Patches that add new tables and a domain manager (DB stuff):

(Add the new database tables:)
./metadata/database/droptables.sql.patch
./metadata/database/createdb.vm.patch
./metadata/database/hibernate/hibernate.cfg.xml.patch
./src/org/roller/pojos/DomainWebsiteData.java
./src/org/roller/pojos/DomainData.java
./src/org/roller/pojos/DomainUserData.java

(Add DomainManager:)
./src/org/roller/model/Roller.java.patch
./src/org/roller/model/DomainManager.java
./src/org/roller/business/DomainManagerImpl.java
./src/org/roller/business/RollerImpl.java.patch
./src/org/roller/business/hibernate/HibernateRollerImpl.java.patch
./src/org/roller/business/hibernate/HibernateDomainManagerImpl.java

----------------------------------------------------------------------
Patches that enable the use of the domain model (ie. filter incoming
requests
under /domain/ and rewrite URLs on the way out:

(A servlet filter to filter incoming domain requests, with helper
classes:)
./src/org/roller/presentation/filters/DomainFilter.java
./src/org/roller/presentation/filters/DomainFilterRequestWrapper.java
./src/org/roller/presentation/filters/DomainFilterResponseWrapper.java
./src/org/roller/util/DomainUtil.java

(Rewrite outgoing URLs:)
./contrib/lib/urlrewrite-2.6.0.jar
./web/WEB-INF/urlrewrite.xml
./metadata/xdoclet/filters.xml.patch
./metadata/xdoclet/filter-mappings.xml.patch

----------------------------------------------------------------------
Patches that add a configuration interface that lets the administrator
administer the domain model: 

./src/org/roller/presentation/website/actions/DomainWebsiteAdminAction.java
./src/org/roller/presentation/website/actions/DomainAdminAction.java
./web/website/domainAdminDeleteOK.jsp
./web/website/domainwebsiteAdminEdit.jsp 
./web/website/domainAdmin.jsp
./web/website/domainwebsiteAdminDeleteOK.jsp
./web/website/domainAdminEdit.jsp
./web/website/domainAdminAddDomainUser.jsp
./web/website/domainEditor.jsp

(Add some constants:)
./src/org/roller/presentation/RollerRequest.java.patch

(Add menu items and bind JSPs to actions:)
./web/WEB-INF/tiles-defs.xml.patch
./web/WEB-INF/admin-menu.xml.patch
./metadata/xdoclet/global-forwards.xml.patch

(New properties used by domain administration interface:)
./web/WEB-INF/classes/ApplicationResources.properties.patch

----------------------------------------------------------------------
General patches used to fix problems we encountered:

(Add norsk and nynorsk as available languages:)
./src/org/roller/presentation/velocity/LanguageServlet.java.patch
./web/WEB-INF/classes/ApplicationResources_nn.properties
./web/WEB-INF/classes/ApplicationResources_no.properties

(Use language from current blog as default:)
./src/org/roller/presentation/LanguageUtil.java.patch

(Use Asynchronous GET when gettin list of users, fixes Firefox bug:)
./web/theme/scripts/ajax-user.js.patch

(Allow 255 character usernames to handle long email addresses:)
./web/website/UserAdmin.jsp.patch

Reply via email to