Status |
Proposal needs feedback |
Target Release |
4.1 |
Original Authors |
Dave Johnson |
Abstract
This is a proposal to enable simple multi-domain support in Roller. It is based on code that I have in production, which enables me to run http://rollerweblogger.org and http://photophys.com via of the very same Roller instance.
Requirements
- Allow one Roller instance to specify different URLs for different weblogs
- Ensure that each weblog is only accessed by one root URL
Issues
Is this simple design what we want to support in Roller?
Patches
There are two "patches" attached to Jira ROL-1670. One uploaded by Dave Johnson, the other by Sean Gilligan. They are described in the next two sections.
Dave's Patch
Dave's Patch (changedfiles-rol-1670.tgz) is actually a tarball containing all files that were changed or modified.
Sean's Patch
Sean's Patch (sean_simple_multidomain_support.patch) is a real patch. It has one other difference: rather than add the new files in the org.rollerweblogger.roller
package they are in org.apache
packages where their related classes live. This means that JPAMultiDomainWebloggerModule.java
is the name of the Guice binding file, since it lives in the same package as JPAWebloggerModule.java
that it is based upon.
Design
From the administrator's point of view, once this proposal is implemented in Roller, all you have to do to enable multi-domain support in Roller is to add one configuration property to Roller for each blog that you would like to give it's own unique domain name to.
For example, on rollerweblogger.org, I wanted my dad's photo-physics blog to have it's own unique URL. So, I added this property to my roller-custom.properties
file:
weblog.absoluteurl.photophys=http://photophys.com guice.backend.module=org.rollerweblogger.roller.JPAWebloggerModule
And I had to add that second line to hook in the mutli-domain implementation, so let's talk about that. The implementation is made up of these five parts:
- Weblog.java: changed to return correct weblog URL based on weblog.absolute.* property
- MutliDomainURLModel.java: new class to return correct URLs
- MultiDomainURLStrategy.java: new class to return correct URLs
- WeblogRequestMapper.java: changes to prevent weblogs from being referred to by two URLs
- JPAWebloggerModule.java: new class to hook in MultiDomainURLStrategy.java
Now let's discuss each change.
Weblog.java
In this class, the only change is to return the correct URL if the weblog is one for which a weblog.absolute.*
URL is specified. The proposal is to make these changes directly to Roller's Weblog.java.
Seems kinda silly that a weblog's absolute URL is defined in two places, here and in the Weblog object itself. The URLStrategy is probably the right place for this logic.
Index: src/java/org/apache/roller/weblogger/pojos/Weblog.java =================================================================== --- src/java/org/apache/roller/weblogger/pojos/Weblog.java (revision 618002) +++ src/java/org/apache/roller/weblogger/pojos/Weblog.java (working copy) @@ -30,7 +30,6 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.roller.weblogger.WebloggerException; @@ -45,6 +44,7 @@ import org.apache.roller.weblogger.business.themes.ThemeManager; import org.apache.roller.weblogger.business.WeblogManager; import org.apache.roller.util.UUIDGenerator; +import org.apache.roller.weblogger.config.WebloggerConfig; import org.apache.roller.weblogger.util.I18nUtils; @@ -838,10 +838,14 @@ * @roller.wrapPojoMethod type="simple" */ public String getAbsoluteURL() { - // TODO: ATLAS reconcile entry.getPermaLink() with new URLs - String relPath = WebloggerRuntimeConfig.getAbsoluteContextURL(); - return relPath + "/" + getHandle(); - //return URLUtilities.getWeblogURL(this, null, true); + String weblogAbsoluteURL = + WebloggerConfig.getProperty("weblog.absoluteurl." + getHandle()); + if (weblogAbsoluteURL != null) { + return weblogAbsoluteURL + "/" + getHandle(); + } else { + String relPath = WebloggerRuntimeConfig.getAbsoluteContextURL(); + return relPath + "/" + getHandle(); + } } public void setAbsoluteURL(String url) { // noop
MultiDomainURLModel.java
In this class, the only change is to return the correct URL if the weblog is one for which a weblog.absolute.*
URL is specified.
Seems kinda silly that a weblog's absolute URL is defined in two places, here and in the Weblog object itself. Shouldn't the URLModel defer to the strategy for this?
package org.rollerweblogger.roller; import org.apache.roller.weblogger.config.WebloggerConfig; import org.apache.roller.weblogger.config.WebloggerRuntimeConfig; import org.apache.roller.weblogger.ui.rendering.model.URLModel; /** Multi-domain URL model */ public class MultiDomainURLModel extends URLModel { /** Absolute URL of Roller, e.g. http://localhost:8080/roller */ public String getAbsoluteSite() { String weblogAbsoluteURL = WebloggerConfig.getProperty("weblog.absoluteurl." + weblog.getHandle()); if (weblogAbsoluteURL != null) { return weblogAbsoluteURL; } else { return WebloggerRuntimeConfig.getAbsoluteContextURL(); } } }
MultiDomainURLStrategy.java
In this class, the only change is to return the correct URL if the weblog is one for which a weblog.absolute.*
URL is specified. The proposal is to make these changes directly to Roller's URLStrategy.
Seems kinda silly that a weblog's absolute URL is defined in two places, here and in the Weblog object itself. This is probably the right place for the definitive definition.
package org.rollerweblogger.roller; import org.apache.roller.weblogger.business.MultiWeblogURLStrategy; import org.apache.roller.weblogger.config.WebloggerConfig; import org.apache.roller.weblogger.config.WebloggerRuntimeConfig; import org.apache.roller.weblogger.pojos.Weblog; /** Multi-domain URL strategy. */ public class MultiDomainURLStrategy extends MultiWeblogURLStrategy { /** Get root url for a given weblog. Optionally for a certain locale. */ public String getWeblogURL(Weblog weblog, String locale, boolean absolute) { if(weblog == null) return null; StringBuffer url = new StringBuffer(); if(absolute) { String weblogAbsoluteURL = WebloggerConfig.getProperty("weblog.absoluteurl." + weblog.getHandle()); if (weblogAbsoluteURL != null) { url.append(weblogAbsoluteURL); } else { url.append(WebloggerRuntimeConfig.getAbsoluteContextURL()); } } else { url.append(WebloggerRuntimeConfig.getRelativeContextURL()); } url.append("/").append(weblog.getHandle()).append("/"); if(locale != null) { url.append(locale).append("/"); } return url.toString(); } }
WeblogRequestMapper.java
This change ensures that a weblog whose URL is specified by a {{weblog.absolute.*} URL is never referred to by it's original URL. The proposal is to make these changes directly to Roller's WeblogRequestMapper.
Index: src/java/org/apache/roller/weblogger/ui/rendering/WeblogRequestMapper.java =================================================================== --- src/java/org/apache/roller/weblogger/ui/rendering/WeblogRequestMapper.java (revision 618002) +++ src/java/org/apache/roller/weblogger/ui/rendering/WeblogRequestMapper.java (working copy) @@ -136,6 +136,16 @@ return false; } + String weblogAbsoluteURL = + WebloggerConfig.getProperty("weblog.absoluteurl." + weblogHandle); + if (weblogAbsoluteURL != null) { + // An absolute URL is specified for this weblog, make sure request URL matches + if (!request.getRequestURL().toString().startsWith(weblogAbsoluteURL)) { + log.debug("SKIPPED "+weblogHandle); + return false; + } + } + log.debug("WEBLOG_URL "+request.getServletPath()); // parse the rest of the url and build forward url
JPAWebloggerModule.java
This module is used to allow us to hook in the new URLStrategy defined above.
package org.rollerweblogger.roller; import org.apache.roller.weblogger.business.jpa.*; import com.google.inject.Binder; import com.google.inject.Module; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.roller.weblogger.business.BookmarkManager; import org.apache.roller.weblogger.business.FileManager; import org.apache.roller.weblogger.business.FileManagerImpl; import org.apache.roller.weblogger.business.PropertiesManager; import org.apache.roller.weblogger.business.URLStrategy; import org.apache.roller.weblogger.business.Weblogger; import org.apache.roller.weblogger.business.UserManager; import org.apache.roller.weblogger.business.WeblogManager; import org.apache.roller.weblogger.business.pings.AutoPingManager; import org.apache.roller.weblogger.business.pings.PingQueueManager; import org.apache.roller.weblogger.business.pings.PingTargetManager; import org.apache.roller.weblogger.business.plugins.PluginManager; import org.apache.roller.weblogger.business.plugins.PluginManagerImpl; import org.apache.roller.weblogger.business.referrers.RefererManager; import org.apache.roller.weblogger.business.referrers.ReferrerQueueManager; import org.apache.roller.weblogger.business.referrers.ReferrerQueueManagerImpl; import org.apache.roller.weblogger.business.runnable.ThreadManager; import org.apache.roller.weblogger.business.search.IndexManager; import org.apache.roller.weblogger.business.search.IndexManagerImpl; import org.apache.roller.weblogger.business.themes.ThemeManager; import org.apache.roller.weblogger.business.themes.ThemeManagerImpl; /** * Guice module for configuring JPA as Weblogger-backend. */ public class JPAWebloggerModule implements Module { private static final Log logger = LogFactory.getLog(JPAWebloggerModule.class); public void configure(Binder binder) { logger.info("Configuring Blogging Roller Module with multi-domain support"); binder.bind(Weblogger.class).to(JPAWebloggerImpl.class); binder.bind(JPAPersistenceStrategy.class); binder.bind(org.apache.roller.weblogger.planet.business.jpa.JPARollerPlanetPersistenceStrategy.class); binder.bind(AutoPingManager.class).to( JPAAutoPingManagerImpl.class); binder.bind(BookmarkManager.class).to( JPABookmarkManagerImpl.class); binder.bind(PingQueueManager.class).to( JPAPingQueueManagerImpl.class); binder.bind(PingTargetManager.class).to( JPAPingTargetManagerImpl.class); binder.bind(PropertiesManager.class).to( JPAPropertiesManagerImpl.class); binder.bind(RefererManager.class).to( JPARefererManagerImpl.class); binder.bind(ThreadManager.class).to( JPAThreadManagerImpl.class); binder.bind(UserManager.class).to( JPAUserManagerImpl.class); binder.bind(WeblogManager.class).to( JPAWeblogManagerImpl.class); binder.bind(ReferrerQueueManager.class).to(ReferrerQueueManagerImpl.class); binder.bind(FileManager.class).to( FileManagerImpl.class); binder.bind(IndexManager.class).to( IndexManagerImpl.class); binder.bind(PluginManager.class).to( PluginManagerImpl.class); binder.bind(ThemeManager.class).to( ThemeManagerImpl.class); binder.bind(URLStrategy.class).to( MultiDomainURLStrategy.class); } }
Comments
Please comment on the Roller dev mailing list.
Mailing list comments have led to an alternate proposal: Proposal Configurable Domain Resolution