From 99d0d4fd66f3490b61c700065b7d16bc4e73f226 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Tue, 26 Nov 2013 16:07:04 -0500
Subject: [PATCH] Eliminate nearly all direct GitBlit singleton references in Wicket

---
 src/main/java/com/gitblit/wicket/AuthorizationStrategy.java               |   12 
 src/main/java/com/gitblit/wicket/pages/ForksPage.java                     |    7 
 src/main/java/com/gitblit/wicket/pages/RootSubPage.java                   |    5 
 src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java     |    5 
 src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java            |   19 
 src/main/java/com/gitblit/wicket/GitBlitWebApp.java                       |  455 +++++++++++--------
 src/main/java/com/gitblit/wicket/panels/ReflogPanel.java                  |    7 
 src/main/java/com/gitblit/wicket/pages/FederationPage.java                |    5 
 src/main/java/com/gitblit/wicket/pages/BlamePage.java                     |    3 
 src/main/java/com/gitblit/wicket/panels/GravatarImage.java                |    6 
 src/main/java/com/gitblit/wicket/pages/RootPage.java                      |   55 +-
 src/main/java/com/gitblit/wicket/pages/BasePage.java                      |   39 
 src/main/java/com/gitblit/wicket/pages/DocsPage.java                      |    3 
 src/main/java/com/gitblit/wicket/panels/LogPanel.java                     |    7 
 src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java   |    3 
 src/main/java/com/gitblit/wicket/WicketUtils.java                         |   19 
 src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java              |    9 
 src/main/java/com/gitblit/wicket/pages/ProjectPage.java                   |    7 
 src/main/java/com/gitblit/wicket/panels/FilterableProjectList.java        |    3 
 src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java            |   19 
 src/main/java/com/gitblit/utils/MessageProcessor.java                     |  126 +++++
 src/main/java/com/gitblit/wicket/pages/ProjectsPage.java                  |    5 
 src/main/java/com/gitblit/wicket/pages/ReviewProposalPage.java            |   16 
 src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java              |    9 
 src/main/java/com/gitblit/wicket/pages/UserPage.java                      |    9 
 src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java     |    5 
 src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java       |    9 
 src/main/java/com/gitblit/wicket/pages/PatchPage.java                     |    6 
 src/main/java/com/gitblit/wicket/pages/ActivityPage.java                  |    7 
 src/main/java/com/gitblit/wicket/pages/DashboardPage.java                 |    7 
 src/main/java/com/gitblit/wicket/pages/CommitPage.java                    |    3 
 src/main/java/com/gitblit/wicket/panels/ActivityPanel.java                |    3 
 src/main/java/com/gitblit/wicket/panels/SearchPanel.java                  |    3 
 src/main/java/com/gitblit/wicket/pages/FederationRegistrationPage.java    |    3 
 src/main/java/com/gitblit/wicket/panels/BasePanel.java                    |   10 
 src/main/java/com/gitblit/wicket/pages/EditTeamPage.java                  |   25 
 src/main/java/com/gitblit/wicket/panels/CompressedDownloadsPanel.java     |    8 
 src/main/java/com/gitblit/wicket/panels/FederationTokensPanel.java        |   13 
 src/main/java/com/gitblit/wicket/pages/OverviewPage.java                  |   13 
 src/main/java/com/gitblit/wicket/pages/EditUserPage.java                  |   33 
 src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java               |   15 
 src/main/java/com/gitblit/wicket/pages/SummaryPage.java                   |   17 
 src/main/java/com/gitblit/wicket/panels/TeamsPanel.java                   |    7 
 src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java       |   14 
 src/main/java/com/gitblit/wicket/pages/ForkPage.java                      |   12 
 src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java            |   53 +-
 src/main/java/com/gitblit/wicket/pages/RepositoryPage.java                |   48 +-
 src/main/java/com/gitblit/wicket/panels/DigestsPanel.java                 |    7 
 src/main/java/com/gitblit/wicket/pages/SessionPage.java                   |   17 
 src/main/java/com/gitblit/wicket/panels/FederationRegistrationsPanel.java |    5 
 src/main/java/com/gitblit/wicket/panels/UsersPanel.java                   |    7 
 src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java           |   15 
 src/main/java/com/gitblit/wicket/panels/HistoryPanel.java                 |   11 
 src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java           |    5 
 src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java                |    3 
 src/main/java/com/gitblit/wicket/pages/BlobPage.java                      |   11 
 src/main/java/com/gitblit/wicket/pages/RawPage.java                       |   11 
 src/main/java/com/gitblit/wicket/pages/DocPage.java                       |    5 
 src/main/java/com/gitblit/wicket/pages/LogoutPage.java                    |    5 
 src/main/java/com/gitblit/wicket/pages/SendProposalPage.java              |    5 
 src/main/java/com/gitblit/wicket/panels/BranchesPanel.java                |    5 
 61 files changed, 718 insertions(+), 561 deletions(-)

diff --git a/src/main/java/com/gitblit/utils/MessageProcessor.java b/src/main/java/com/gitblit/utils/MessageProcessor.java
new file mode 100644
index 0000000..58493de
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/MessageProcessor.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2013 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.utils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.IStoredSettings;
+import com.gitblit.Keys;
+import com.gitblit.models.RepositoryModel;
+
+public class MessageProcessor {
+
+	private final Logger logger = LoggerFactory.getLogger(getClass());
+
+	private final IStoredSettings settings;
+
+	public MessageProcessor(IStoredSettings settings) {
+		this.settings = settings;
+	}
+
+	/**
+	 * Returns an html version of the commit message with any global or
+	 * repository-specific regular expression substitution applied.
+	 *
+	 * This method uses the preferred renderer to transform the commit message.
+	 *
+	 * @param repository
+	 * @param text
+	 * @return html version of the commit message
+	 */
+	public String processCommitMessage(RepositoryModel repository, String text) {
+		switch (repository.commitMessageRenderer) {
+		case MARKDOWN:
+			try {
+				String prepared = processCommitMessageRegex(repository.name, text);
+				return MarkdownUtils.transformMarkdown(prepared);
+			} catch (Exception e) {
+				logger.error("Failed to render commit message as markdown", e);
+			}
+			break;
+		default:
+			// noop
+			break;
+		}
+
+		return processPlainCommitMessage(repository.name, text);
+	}
+
+	/**
+	 * Returns an html version of the commit message with any global or
+	 * repository-specific regular expression substitution applied.
+	 *
+	 * This method assumes the commit message is plain text.
+	 *
+	 * @param repositoryName
+	 * @param text
+	 * @return html version of the commit message
+	 */
+	public String processPlainCommitMessage(String repositoryName, String text) {
+		String html = StringUtils.escapeForHtml(text, false);
+		html = processCommitMessageRegex(repositoryName, html);
+		return StringUtils.breakLinesForHtml(html);
+
+	}
+
+	/**
+	 * Apply globally or per-repository specified regex substitutions to the
+	 * commit message.
+	 *
+	 * @param repositoryName
+	 * @param text
+	 * @return the processed commit message
+	 */
+	protected String processCommitMessageRegex(String repositoryName, String text) {
+		Map<String, String> map = new HashMap<String, String>();
+		// global regex keys
+		if (settings.getBoolean(Keys.regex.global, false)) {
+			for (String key : settings.getAllKeys(Keys.regex.global)) {
+				if (!key.equals(Keys.regex.global)) {
+					String subKey = key.substring(key.lastIndexOf('.') + 1);
+					map.put(subKey, settings.getString(key, ""));
+				}
+			}
+		}
+
+		// repository-specific regex keys
+		List<String> keys = settings.getAllKeys(Keys.regex._ROOT + "."
+				+ repositoryName.toLowerCase());
+		for (String key : keys) {
+			String subKey = key.substring(key.lastIndexOf('.') + 1);
+			map.put(subKey, settings.getString(key, ""));
+		}
+
+		for (Entry<String, String> entry : map.entrySet()) {
+			String definition = entry.getValue().trim();
+			String[] chunks = definition.split("!!!");
+			if (chunks.length == 2) {
+				text = text.replaceAll(chunks[0], chunks[1]);
+			} else {
+				logger.warn(entry.getKey()
+						+ " improperly formatted.  Use !!! to separate match from replacement: "
+						+ definition);
+			}
+		}
+		return text;
+	}
+}
diff --git a/src/main/java/com/gitblit/wicket/AuthorizationStrategy.java b/src/main/java/com/gitblit/wicket/AuthorizationStrategy.java
index a00e2e2..51ae648 100644
--- a/src/main/java/com/gitblit/wicket/AuthorizationStrategy.java
+++ b/src/main/java/com/gitblit/wicket/AuthorizationStrategy.java
@@ -21,7 +21,7 @@
 import org.apache.wicket.authorization.strategies.page.AbstractPageAuthorizationStrategy;
 import org.apache.wicket.markup.html.WebPage;
 
-import com.gitblit.GitBlit;
+import com.gitblit.IStoredSettings;
 import com.gitblit.Keys;
 import com.gitblit.models.UserModel;
 import com.gitblit.wicket.pages.BasePage;
@@ -29,9 +29,11 @@
 public class AuthorizationStrategy extends AbstractPageAuthorizationStrategy implements
 		IUnauthorizedComponentInstantiationListener {
 
+	IStoredSettings settings;
 	Class<? extends WebPage> homepageClass;
 
-	public AuthorizationStrategy(Class<? extends WebPage> homepageClass) {
+	public AuthorizationStrategy(IStoredSettings settings, Class<? extends WebPage> homepageClass) {
+		this.settings = settings;
 		this.homepageClass = homepageClass;
 	}
 
@@ -45,9 +47,9 @@
 		}
 
 		if (BasePage.class.isAssignableFrom(pageClass)) {
-			boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
-			boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
-			boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, true);
+			boolean authenticateView = settings.getBoolean(Keys.web.authenticateViewPages, true);
+			boolean authenticateAdmin = settings.getBoolean(Keys.web.authenticateAdminPages, true);
+			boolean allowAdmin = settings.getBoolean(Keys.web.allowAdministration, true);
 
 			GitBlitWebSession session = GitBlitWebSession.get();
 			if (authenticateView && !session.isLoggedIn()) {
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
index 8cbda46..1a46a1f 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
+++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -1,193 +1,262 @@
-/*
- * Copyright 2011 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.wicket;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.Request;
-import org.apache.wicket.Response;
-import org.apache.wicket.Session;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.protocol.http.WebApplication;
-
-import com.gitblit.GitBlit;
-import com.gitblit.Keys;
-import com.gitblit.utils.StringUtils;
-import com.gitblit.wicket.pages.ActivityPage;
-import com.gitblit.wicket.pages.BlamePage;
-import com.gitblit.wicket.pages.BlobDiffPage;
-import com.gitblit.wicket.pages.BlobPage;
-import com.gitblit.wicket.pages.BranchesPage;
-import com.gitblit.wicket.pages.CommitDiffPage;
-import com.gitblit.wicket.pages.CommitPage;
-import com.gitblit.wicket.pages.ComparePage;
-import com.gitblit.wicket.pages.DocPage;
-import com.gitblit.wicket.pages.DocsPage;
-import com.gitblit.wicket.pages.FederationRegistrationPage;
-import com.gitblit.wicket.pages.ForkPage;
-import com.gitblit.wicket.pages.ForksPage;
-import com.gitblit.wicket.pages.GitSearchPage;
-import com.gitblit.wicket.pages.GravatarProfilePage;
-import com.gitblit.wicket.pages.HistoryPage;
-import com.gitblit.wicket.pages.LogPage;
-import com.gitblit.wicket.pages.LogoutPage;
-import com.gitblit.wicket.pages.LuceneSearchPage;
-import com.gitblit.wicket.pages.MetricsPage;
-import com.gitblit.wicket.pages.MyDashboardPage;
-import com.gitblit.wicket.pages.OverviewPage;
-import com.gitblit.wicket.pages.PatchPage;
-import com.gitblit.wicket.pages.ProjectPage;
-import com.gitblit.wicket.pages.ProjectsPage;
-import com.gitblit.wicket.pages.RawPage;
-import com.gitblit.wicket.pages.ReflogPage;
-import com.gitblit.wicket.pages.RepositoriesPage;
-import com.gitblit.wicket.pages.ReviewProposalPage;
-import com.gitblit.wicket.pages.SummaryPage;
-import com.gitblit.wicket.pages.TagPage;
-import com.gitblit.wicket.pages.TagsPage;
-import com.gitblit.wicket.pages.TreePage;
-import com.gitblit.wicket.pages.UserPage;
-import com.gitblit.wicket.pages.UsersPage;
-
-public class GitBlitWebApp extends WebApplication {
-
-	private final Class<? extends WebPage> homePageClass = MyDashboardPage.class;
-
-	private final Map<String, CacheControl> cacheablePages = new HashMap<String, CacheControl>();
-
-	@Override
-	public void init() {
-		super.init();
-
-		// Setup page authorization mechanism
-		boolean useAuthentication = GitBlit.getBoolean(Keys.web.authenticateViewPages, false)
-				|| GitBlit.getBoolean(Keys.web.authenticateAdminPages, false);
-		if (useAuthentication) {
-			AuthorizationStrategy authStrategy = new AuthorizationStrategy(homePageClass);
-			getSecuritySettings().setAuthorizationStrategy(authStrategy);
-			getSecuritySettings().setUnauthorizedComponentInstantiationListener(authStrategy);
-		}
-
-		// Grab Browser info (like timezone, etc)
-		if (GitBlit.getBoolean(Keys.web.useClientTimezone, false)) {
-			getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
-		}
-
-		// configure the resource cache duration to 90 days for deployment
-		if (!GitBlit.isDebugMode()) {
-			getResourceSettings().setDefaultCacheDuration(90 * 86400);
-		}
-
-		// setup the standard gitweb-ish urls
-		mount("/repositories", RepositoriesPage.class);
-		mount("/overview", OverviewPage.class, "r", "h");
-		mount("/summary", SummaryPage.class, "r");
-		mount("/reflog", ReflogPage.class, "r", "h");
-		mount("/commits", LogPage.class, "r", "h");
-		mount("/log", LogPage.class, "r", "h");
-		mount("/tags", TagsPage.class, "r");
-		mount("/branches", BranchesPage.class, "r");
-		mount("/commit", CommitPage.class, "r", "h");
-		mount("/tag", TagPage.class, "r", "h");
-		mount("/tree", TreePage.class, "r", "h", "f");
-		mount("/blob", BlobPage.class, "r", "h", "f");
-		mount("/raw", RawPage.class, "r", "h", "f");
-		mount("/blobdiff", BlobDiffPage.class, "r", "h", "f");
-		mount("/commitdiff", CommitDiffPage.class, "r", "h");
-		mount("/compare", ComparePage.class, "r", "h");
-		mount("/patch", PatchPage.class, "r", "h", "f");
-		mount("/history", HistoryPage.class, "r", "h", "f");
-		mount("/search", GitSearchPage.class);
-		mount("/metrics", MetricsPage.class, "r");
-		mount("/blame", BlamePage.class, "r", "h", "f");
-		mount("/users", UsersPage.class);
-		mount("/logout", LogoutPage.class);
-
-		// setup the markup document urls
-		mount("/docs", DocsPage.class, "r");
-		mount("/doc", DocPage.class, "r", "h", "f");
-
-		// federation urls
-		mount("/proposal", ReviewProposalPage.class, "t");
-		mount("/registration", FederationRegistrationPage.class, "u", "n");
-
-		mount("/activity", ActivityPage.class, "r", "h");
-		mount("/gravatar", GravatarProfilePage.class, "h");
-		mount("/lucene", LuceneSearchPage.class);
-		mount("/project", ProjectPage.class, "p");
-		mount("/projects", ProjectsPage.class);
-		mount("/user", UserPage.class, "user");
-		mount("/forks", ForksPage.class, "r");
-		mount("/fork", ForkPage.class, "r");
-		
-		getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
-	}
-
-	private void mount(String location, Class<? extends WebPage> clazz, String... parameters) {
-		if (parameters == null) {
-			parameters = new String[] {};
-		}
-		if (!GitBlit.getBoolean(Keys.web.mountParameters, true)) {
-			parameters = new String[] {};
-		}
-		mount(new GitblitParamUrlCodingStrategy(location, clazz, parameters));
-
-		// map the mount point to the cache control definition
-		if (clazz.isAnnotationPresent(CacheControl.class)) {
-			CacheControl cacheControl = clazz.getAnnotation(CacheControl.class);
-			cacheablePages.put(location.substring(1), cacheControl);
-		}
-	}
-
-	@Override
-	public Class<? extends WebPage> getHomePage() {
-		return homePageClass;
-	}
-
-	public boolean isCacheablePage(String mountPoint) {
-		return cacheablePages.containsKey(mountPoint);
-	}
-
-	public CacheControl getCacheControl(String mountPoint) {
-		return cacheablePages.get(mountPoint);
-	}
-
-	@Override
-	public final Session newSession(Request request, Response response) {
-		GitBlitWebSession gitBlitWebSession = new GitBlitWebSession(request);
-
-		String forcedLocale = GitBlit.getString(Keys.web.forceDefaultLocale, null);
-		if (!StringUtils.isEmpty(forcedLocale)) {
-			gitBlitWebSession.setLocale(new Locale(forcedLocale));
-		}
-		return gitBlitWebSession;
-	}
-
-	@Override
-	public final String getConfigurationType() {
-		if (GitBlit.isDebugMode()) {
-			return Application.DEVELOPMENT;
-		}
-		return Application.DEPLOYMENT;
-	}
-
-	public static GitBlitWebApp get() {
-		return (GitBlitWebApp) WebApplication.get();
-	}
-}
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Request;
+import org.apache.wicket.Response;
+import org.apache.wicket.Session;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.WebApplication;
+
+import com.gitblit.GitBlit;
+import com.gitblit.IStoredSettings;
+import com.gitblit.Keys;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.pages.ActivityPage;
+import com.gitblit.wicket.pages.BlamePage;
+import com.gitblit.wicket.pages.BlobDiffPage;
+import com.gitblit.wicket.pages.BlobPage;
+import com.gitblit.wicket.pages.BranchesPage;
+import com.gitblit.wicket.pages.CommitDiffPage;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.ComparePage;
+import com.gitblit.wicket.pages.DocPage;
+import com.gitblit.wicket.pages.DocsPage;
+import com.gitblit.wicket.pages.FederationRegistrationPage;
+import com.gitblit.wicket.pages.ForkPage;
+import com.gitblit.wicket.pages.ForksPage;
+import com.gitblit.wicket.pages.GitSearchPage;
+import com.gitblit.wicket.pages.GravatarProfilePage;
+import com.gitblit.wicket.pages.HistoryPage;
+import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.LogoutPage;
+import com.gitblit.wicket.pages.LuceneSearchPage;
+import com.gitblit.wicket.pages.MetricsPage;
+import com.gitblit.wicket.pages.MyDashboardPage;
+import com.gitblit.wicket.pages.OverviewPage;
+import com.gitblit.wicket.pages.PatchPage;
+import com.gitblit.wicket.pages.ProjectPage;
+import com.gitblit.wicket.pages.ProjectsPage;
+import com.gitblit.wicket.pages.RawPage;
+import com.gitblit.wicket.pages.ReflogPage;
+import com.gitblit.wicket.pages.RepositoriesPage;
+import com.gitblit.wicket.pages.ReviewProposalPage;
+import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.TagPage;
+import com.gitblit.wicket.pages.TagsPage;
+import com.gitblit.wicket.pages.TreePage;
+import com.gitblit.wicket.pages.UserPage;
+import com.gitblit.wicket.pages.UsersPage;
+
+public class GitBlitWebApp extends WebApplication {
+
+	private final Class<? extends WebPage> homePageClass = MyDashboardPage.class;
+
+	private final Map<String, CacheControl> cacheablePages = new HashMap<String, CacheControl>();
+
+	private IStoredSettings settings;
+
+	@Override
+	public void init() {
+		super.init();
+
+		settings = GitBlit.getSettings();
+
+		// Setup page authorization mechanism
+		boolean useAuthentication = settings.getBoolean(Keys.web.authenticateViewPages, false)
+				|| settings.getBoolean(Keys.web.authenticateAdminPages, false);
+		if (useAuthentication) {
+			AuthorizationStrategy authStrategy = new AuthorizationStrategy(settings, homePageClass);
+			getSecuritySettings().setAuthorizationStrategy(authStrategy);
+			getSecuritySettings().setUnauthorizedComponentInstantiationListener(authStrategy);
+		}
+
+		// Grab Browser info (like timezone, etc)
+		if (settings.getBoolean(Keys.web.useClientTimezone, false)) {
+			getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
+		}
+
+		// configure the resource cache duration to 90 days for deployment
+		if (!isDebugMode()) {
+			getResourceSettings().setDefaultCacheDuration(90 * 86400);
+		}
+
+		// setup the standard gitweb-ish urls
+		mount("/repositories", RepositoriesPage.class);
+		mount("/overview", OverviewPage.class, "r", "h");
+		mount("/summary", SummaryPage.class, "r");
+		mount("/reflog", ReflogPage.class, "r", "h");
+		mount("/commits", LogPage.class, "r", "h");
+		mount("/log", LogPage.class, "r", "h");
+		mount("/tags", TagsPage.class, "r");
+		mount("/branches", BranchesPage.class, "r");
+		mount("/commit", CommitPage.class, "r", "h");
+		mount("/tag", TagPage.class, "r", "h");
+		mount("/tree", TreePage.class, "r", "h", "f");
+		mount("/blob", BlobPage.class, "r", "h", "f");
+		mount("/raw", RawPage.class, "r", "h", "f");
+		mount("/blobdiff", BlobDiffPage.class, "r", "h", "f");
+		mount("/commitdiff", CommitDiffPage.class, "r", "h");
+		mount("/compare", ComparePage.class, "r", "h");
+		mount("/patch", PatchPage.class, "r", "h", "f");
+		mount("/history", HistoryPage.class, "r", "h", "f");
+		mount("/search", GitSearchPage.class);
+		mount("/metrics", MetricsPage.class, "r");
+		mount("/blame", BlamePage.class, "r", "h", "f");
+		mount("/users", UsersPage.class);
+		mount("/logout", LogoutPage.class);
+
+		// setup the markup document urls
+		mount("/docs", DocsPage.class, "r");
+		mount("/doc", DocPage.class, "r", "h", "f");
+
+		// federation urls
+		mount("/proposal", ReviewProposalPage.class, "t");
+		mount("/registration", FederationRegistrationPage.class, "u", "n");
+
+		mount("/activity", ActivityPage.class, "r", "h");
+		mount("/gravatar", GravatarProfilePage.class, "h");
+		mount("/lucene", LuceneSearchPage.class);
+		mount("/project", ProjectPage.class, "p");
+		mount("/projects", ProjectsPage.class);
+		mount("/user", UserPage.class, "user");
+		mount("/forks", ForksPage.class, "r");
+		mount("/fork", ForkPage.class, "r");
+		
+		getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
+		super.init();
+	}
+
+	private void mount(String location, Class<? extends WebPage> clazz, String... parameters) {
+		if (parameters == null) {
+			parameters = new String[] {};
+		}
+		if (!settings.getBoolean(Keys.web.mountParameters, true)) {
+			parameters = new String[] {};
+		}
+		mount(new GitblitParamUrlCodingStrategy(settings, location, clazz, parameters));
+
+		// map the mount point to the cache control definition
+		if (clazz.isAnnotationPresent(CacheControl.class)) {
+			CacheControl cacheControl = clazz.getAnnotation(CacheControl.class);
+			cacheablePages.put(location.substring(1), cacheControl);
+		}
+	}
+
+	@Override
+	public Class<? extends WebPage> getHomePage() {
+		return homePageClass;
+	}
+
+	public boolean isCacheablePage(String mountPoint) {
+		return cacheablePages.containsKey(mountPoint);
+	}
+
+	public CacheControl getCacheControl(String mountPoint) {
+		return cacheablePages.get(mountPoint);
+	}
+
+	@Override
+	public final Session newSession(Request request, Response response) {
+		GitBlitWebSession gitBlitWebSession = new GitBlitWebSession(request);
+
+		String forcedLocale = settings.getString(Keys.web.forceDefaultLocale, null);
+		if (!StringUtils.isEmpty(forcedLocale)) {
+			gitBlitWebSession.setLocale(new Locale(forcedLocale));
+		}
+		return gitBlitWebSession;
+	}
+
+	public IStoredSettings settings() {
+		return settings;
+	}
+
+	/**
+	 * Is Gitblit running in debug mode?
+	 *
+	 * @return true if Gitblit is running in debug mode
+	 */
+	public boolean isDebugMode() {
+		return GitBlit.isDebugMode();
+	}
+
+	/*
+	 * These methods look strange... and they are... but they are the first
+	 * step towards modularization across multiple commits.
+	 */
+	public Date getBootDate() {
+		return GitBlit.getBootDate();
+	}
+
+	public Date getLastActivityDate() {
+		return GitBlit.getLastActivityDate();
+	}
+
+	public GitBlit runtime() {
+		return GitBlit.self();
+	}
+
+	public GitBlit mail() {
+		return GitBlit.self();
+	}
+
+	public GitBlit users() {
+		return GitBlit.self();
+	}
+
+	public GitBlit session() {
+		return GitBlit.self();
+	}
+
+	public GitBlit repositories() {
+		return GitBlit.self();
+	}
+
+	public GitBlit projects() {
+		return GitBlit.self();
+	}
+
+	public GitBlit federation() {
+		return GitBlit.self();
+	}
+
+	public GitBlit gitblit() {
+		return GitBlit.self();
+	}
+
+	public TimeZone getTimezone() {
+		return GitBlit.getTimezone();
+	}
+
+	@Override
+	public final String getConfigurationType() {
+		if (isDebugMode()) {
+			return Application.DEVELOPMENT;
+		}
+		return Application.DEPLOYMENT;
+	}
+
+	public static GitBlitWebApp get() {
+		return (GitBlitWebApp) WebApplication.get();
+	}
+}
diff --git a/src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java b/src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java
index 2d65d37..4f67a4a 100644
--- a/src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java
+++ b/src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java
@@ -25,7 +25,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.gitblit.GitBlit;
+import com.gitblit.IStoredSettings;
 import com.gitblit.Keys;
 
 /**
@@ -42,6 +42,8 @@
 
 	private Logger logger = LoggerFactory.getLogger(GitblitParamUrlCodingStrategy.class);
 
+	private IStoredSettings settings;
+
 	/**
 	 * Construct.
 	 *
@@ -53,9 +55,13 @@
 	 * @param parameterNames
 	 *            the parameter names (not null)
 	 */
-	public <C extends Page> GitblitParamUrlCodingStrategy(String mountPath,
+	public <C extends Page> GitblitParamUrlCodingStrategy(
+			IStoredSettings settings,
+			String mountPath,
 			Class<C> bookmarkablePageClass, String[] parameterNames) {
+
 		super(mountPath, bookmarkablePageClass, parameterNames);
+		this.settings = settings;
 	}
 
 	/**
@@ -67,7 +73,7 @@
 	 */
 	@Override
 	protected String urlEncodePathComponent(String string) {
-		char altChar = GitBlit.getChar(Keys.web.forwardSlashCharacter, '/');
+		char altChar = settings.getChar(Keys.web.forwardSlashCharacter, '/');
 		if (altChar != '/') {
 			string = string.replace('/', altChar);
 		}
@@ -83,7 +89,7 @@
 	 */
 	@Override
 	protected String urlDecodePathComponent(String value) {
-		char altChar = GitBlit.getChar(Keys.web.forwardSlashCharacter, '/');
+		char altChar = settings.getChar(Keys.web.forwardSlashCharacter, '/');
 		if (altChar != '/') {
 			value = value.replace(altChar, '/');
 		}
diff --git a/src/main/java/com/gitblit/wicket/WicketUtils.java b/src/main/java/com/gitblit/wicket/WicketUtils.java
index 6e3d932..8e119da 100644
--- a/src/main/java/com/gitblit/wicket/WicketUtils.java
+++ b/src/main/java/com/gitblit/wicket/WicketUtils.java
@@ -44,7 +44,6 @@
 import com.gitblit.Constants;
 import com.gitblit.Constants.AccessPermission;
 import com.gitblit.Constants.FederationPullStatus;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.FederationModel;
 import com.gitblit.models.Metric;
@@ -189,7 +188,7 @@
 			return newImage(wicketId, "file_settings_16x16.png");
 		}
 
-		MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
+		MarkupProcessor processor = new MarkupProcessor(GitBlitWebApp.get().settings());
 		String ext = StringUtils.getFileExtension(filename).toLowerCase();
 		if (processor.getMarkupExtensions().contains(ext)) {
 			return newImage(wicketId, "file_world_16x16.png");
@@ -510,10 +509,10 @@
 	}
 
 	public static Label createDateLabel(String wicketId, Date date, TimeZone timeZone, TimeUtils timeUtils, boolean setCss) {
-		String format = GitBlit.getString(Keys.web.datestampShortFormat, "MM/dd/yy");
+		String format = GitBlitWebApp.get().settings().getString(Keys.web.datestampShortFormat, "MM/dd/yy");
 		DateFormat df = new SimpleDateFormat(format);
 		if (timeZone == null) {
-			timeZone = GitBlit.getTimezone();
+			timeZone = GitBlitWebApp.get().getTimezone();
 		}
 		df.setTimeZone(timeZone);
 		String dateString;
@@ -543,10 +542,10 @@
 	}
 
 	public static Label createTimeLabel(String wicketId, Date date, TimeZone timeZone, TimeUtils timeUtils) {
-		String format = GitBlit.getString(Keys.web.timeFormat, "HH:mm");
+		String format = GitBlitWebApp.get().settings().getString(Keys.web.timeFormat, "HH:mm");
 		DateFormat df = new SimpleDateFormat(format);
 		if (timeZone == null) {
-			timeZone = GitBlit.getTimezone();
+			timeZone = GitBlitWebApp.get().getTimezone();
 		}
 		df.setTimeZone(timeZone);
 		String timeString;
@@ -564,10 +563,10 @@
 	}
 
 	public static Label createDatestampLabel(String wicketId, Date date, TimeZone timeZone, TimeUtils timeUtils) {
-		String format = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
+		String format = GitBlitWebApp.get().settings().getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
 		DateFormat df = new SimpleDateFormat(format);
 		if (timeZone == null) {
-			timeZone = GitBlit.getTimezone();
+			timeZone = GitBlitWebApp.get().getTimezone();
 		}
 		df.setTimeZone(timeZone);
 		String dateString;
@@ -598,11 +597,11 @@
 	}
 
 	public static Label createTimestampLabel(String wicketId, Date date, TimeZone timeZone, TimeUtils timeUtils) {
-		String format = GitBlit.getString(Keys.web.datetimestampLongFormat,
+		String format = GitBlitWebApp.get().settings().getString(Keys.web.datetimestampLongFormat,
 				"EEEE, MMMM d, yyyy HH:mm Z");
 		DateFormat df = new SimpleDateFormat(format);
 		if (timeZone == null) {
-			timeZone = GitBlit.getTimezone();
+			timeZone = GitBlitWebApp.get().getTimezone();
 		}
 		df.setTimeZone(timeZone);
 		String dateString;
diff --git a/src/main/java/com/gitblit/wicket/pages/ActivityPage.java b/src/main/java/com/gitblit/wicket/pages/ActivityPage.java
index 99992ea..5e7332f 100644
--- a/src/main/java/com/gitblit/wicket/pages/ActivityPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ActivityPage.java
@@ -29,7 +29,6 @@
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Fragment;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.Activity;
 import com.gitblit.models.Metric;
@@ -66,7 +65,7 @@
 		// parameters
 		int daysBack = WicketUtils.getDaysBack(params);
 		if (daysBack < 1) {
-			daysBack = GitBlit.getInteger(Keys.web.activityDuration, 7);
+			daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
 		}
 		String objectId = WicketUtils.getObject(params);
 
@@ -113,7 +112,7 @@
 					daysBack, totalCommits, totalAuthors)));
 
 			// create the activity charts
-			if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
+			if (app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
 				GoogleCharts charts = createCharts(recentActivity);
 				add(new HeaderContributor(charts));
 				add(new Fragment("chartsPanel", "chartsFragment", this));
@@ -137,7 +136,7 @@
 				ActivityPage.class);
 
 		PageParameters currentParameters = getPageParameters();
-		int daysBack = GitBlit.getInteger(Keys.web.activityDuration, 7);
+		int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
 		if (currentParameters != null && !currentParameters.containsKey("db")) {
 			currentParameters.put("db", daysBack);
 		}
diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java
index 9bae378..647a938 100644
--- a/src/main/java/com/gitblit/wicket/pages/BasePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java
@@ -52,7 +52,6 @@
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
 import com.gitblit.models.TeamModel;
@@ -83,7 +82,7 @@
 	}
 
 	private void customizeHeader() {
-		if (GitBlit.getBoolean(Keys.web.useResponsiveLayout, true)) {
+		if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) {
 			add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css"));
 		}
 	}
@@ -121,7 +120,7 @@
 
 	@Override
 	protected void onBeforeRender() {
-		if (GitBlit.isDebugMode()) {
+		if (app().isDebugMode()) {
 			// strip Wicket tags in debug mode for jQuery DOM traversal
 			Application.get().getMarkupSettings().setStripWicketTags(true);
 		}
@@ -130,7 +129,7 @@
 
 	@Override
 	protected void onAfterRender() {
-		if (GitBlit.isDebugMode()) {
+		if (app().isDebugMode()) {
 			// restore Wicket debug tags
 			Application.get().getMarkupSettings().setStripWicketTags(false);
 		}
@@ -141,8 +140,8 @@
 	protected void setHeaders(WebResponse response)	{
 		// set canonical link as http header for SEO (issue-304)
 		// https://support.google.com/webmasters/answer/139394?hl=en
-		response.setHeader("Link" ,MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl()));
-		int expires = GitBlit.getInteger(Keys.web.pageCacheExpires, 0);
+		response.setHeader("Link", MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl()));
+		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
 		if (expires > 0) {
 			// pages are personalized for the authenticated user so they must be
 			// marked private to prohibit proxy servers from caching them
@@ -164,10 +163,10 @@
 			CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
 			switch (cacheControl.value()) {
 			case ACTIVITY:
-				setLastModified(GitBlit.getLastActivityDate());
+				setLastModified(app().getLastActivityDate());
 				break;
 			case BOOT:
-				setLastModified(GitBlit.getBootDate());
+				setLastModified(app().getBootDate());
 				break;
 			case NONE:
 				break;
@@ -188,21 +187,21 @@
 			return;
 		}
 
-		if (when.before(GitBlit.getBootDate())) {
+		if (when.before(app().getBootDate())) {
 			// last-modified can not be before the Gitblit boot date
 			// this helps ensure that pages are properly refreshed after a
 			// server config change
-			when = GitBlit.getBootDate();
+			when = app().getBootDate();
 		}
 
-		int expires = GitBlit.getInteger(Keys.web.pageCacheExpires, 0);
+		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
 		WebResponse response = (WebResponse) getResponse();
 		response.setLastModifiedTime(Time.valueOf(when));
 		response.setDateHeader("Expires", System.currentTimeMillis() + Duration.minutes(expires).getMilliseconds());
 	}
 
 	protected void setupPage(String repositoryName, String pageName) {
-		String siteName = GitBlit.getString(Keys.web.siteName, Constants.NAME);
+		String siteName = app().settings().getString(Keys.web.siteName, Constants.NAME);
 		if (StringUtils.isEmpty(siteName)) {
 			siteName = Constants.NAME;
 		}
@@ -212,16 +211,16 @@
 			add(new Label("title", siteName));
 		}
 
-		String rootLinkUrl = GitBlit.getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString());
+		String rootLinkUrl = app().settings().getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString());
 		ExternalLink rootLink = new ExternalLink("rootLink", rootLinkUrl);
-		WicketUtils.setHtmlTooltip(rootLink, GitBlit.getString(Keys.web.siteName, Constants.NAME));
+		WicketUtils.setHtmlTooltip(rootLink, app().settings().getString(Keys.web.siteName, Constants.NAME));
 		add(rootLink);
 
 		// Feedback panel for info, warning, and non-fatal error messages
 		add(new FeedbackPanel("feedback"));
 
 		add(new Label("gbVersion", "v" + Constants.getVersion()));
-		if (GitBlit.getBoolean(Keys.web.aggressiveHeapManagement, false)) {
+		if (app().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) {
 			System.gc();
 		}
 	}
@@ -314,8 +313,8 @@
 	}
 
 	protected TimeZone getTimeZone() {
-		return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
-				.getTimezone() : GitBlit.getTimezone();
+		return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
+				.getTimezone() : app().getTimezone();
 	}
 
 	protected String getServerName() {
@@ -326,7 +325,7 @@
 
 	protected List<ProjectModel> getProjectModels() {
 		final UserModel user = GitBlitWebSession.get().getUser();
-		List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);
+		List<ProjectModel> projects = app().projects().getProjectModels(user, true);
 		return projects;
 	}
 
@@ -339,7 +338,7 @@
 		String regex = WicketUtils.getRegEx(params);
 		String team = WicketUtils.getTeam(params);
 		int daysBack = params.getInt("db", 0);
-		int maxDaysBack = GitBlit.getInteger(Keys.web.activityDurationMaximum, 30);
+		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
 
 		List<ProjectModel> availableModels = getProjectModels();
 		Set<ProjectModel> models = new HashSet<ProjectModel>();
@@ -363,7 +362,7 @@
 			// need TeamModels first
 			List<TeamModel> teamModels = new ArrayList<TeamModel>();
 			for (String name : teams) {
-				TeamModel teamModel = GitBlit.self().getTeamModel(name);
+				TeamModel teamModel = app().users().getTeamModel(name);
 				if (teamModel != null) {
 					teamModels.add(teamModel);
 				}
diff --git a/src/main/java/com/gitblit/wicket/pages/BlamePage.java b/src/main/java/com/gitblit/wicket/pages/BlamePage.java
index 9f00d21..5268263 100644
--- a/src/main/java/com/gitblit/wicket/pages/BlamePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/BlamePage.java
@@ -30,7 +30,6 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.revwalk.RevCommit;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.AnnotatedLine;
 import com.gitblit.models.PathModel;
@@ -71,7 +70,7 @@
 
 		add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, objectId));
 
-		String format = GitBlit.getString(Keys.web.datetimestampLongFormat,
+		String format = app().settings().getString(Keys.web.datetimestampLongFormat,
 				"EEEE, MMMM d, yyyy HH:mm Z");
 		final DateFormat df = new SimpleDateFormat(format);
 		df.setTimeZone(getTimeZone());
diff --git a/src/main/java/com/gitblit/wicket/pages/BlobPage.java b/src/main/java/com/gitblit/wicket/pages/BlobPage.java
index 56ad5b9..c4eca10 100644
--- a/src/main/java/com/gitblit/wicket/pages/BlobPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/BlobPage.java
@@ -28,7 +28,6 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
@@ -50,7 +49,7 @@
 
 		Repository r = getRepository();
 		final String blobPath = WicketUtils.getPath(params);
-		String [] encodings = GitBlit.getEncodings();
+		String [] encodings = getEncodings();
 
 		if (StringUtils.isEmpty(blobPath)) {
 			// blob by objectid
@@ -75,7 +74,7 @@
 			}
 
 			// see if we should redirect to the doc page
-			MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
+			MarkupProcessor processor = new MarkupProcessor(app().settings());
 			for (String ext : processor.getMarkupExtensions()) {
 				if (ext.equals(extension)) {
 					setResponsePage(DocPage.class, params);
@@ -102,13 +101,13 @@
 
 			// Map the extensions to types
 			Map<String, Integer> map = new HashMap<String, Integer>();
-			for (String ext : GitBlit.getStrings(Keys.web.prettyPrintExtensions)) {
+			for (String ext : app().settings().getStrings(Keys.web.prettyPrintExtensions)) {
 				map.put(ext.toLowerCase(), 1);
 			}
-			for (String ext : GitBlit.getStrings(Keys.web.imageExtensions)) {
+			for (String ext : app().settings().getStrings(Keys.web.imageExtensions)) {
 				map.put(ext.toLowerCase(), 2);
 			}
-			for (String ext : GitBlit.getStrings(Keys.web.binaryExtensions)) {
+			for (String ext : app().settings().getStrings(Keys.web.binaryExtensions)) {
 				map.put(ext.toLowerCase(), 3);
 			}
 
diff --git a/src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java b/src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java
index 302de0d..3e308f1 100644
--- a/src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ChangePasswordPage.java
@@ -25,7 +25,6 @@
 import org.apache.wicket.model.Model;
 import org.apache.wicket.protocol.http.WebResponse;
 
-import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
 import com.gitblit.models.UserModel;
@@ -45,16 +44,16 @@
 			throw new RestartResponseException(getApplication().getHomePage());
 		}
 
-		if (!GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)
-				&& !GitBlit.getBoolean(Keys.web.authenticateViewPages, false)) {
+		if (!app().settings().getBoolean(Keys.web.authenticateAdminPages, true)
+				&& !app().settings().getBoolean(Keys.web.authenticateViewPages, false)) {
 			// no authentication enabled
 			throw new RestartResponseException(getApplication().getHomePage());
 		}
 
 		UserModel user = GitBlitWebSession.get().getUser();
-		if (!GitBlit.self().supportsCredentialChanges(user)) {
+		if (!app().users().supportsCredentialChanges(user)) {
 			error(MessageFormat.format(getString("gb.userServiceDoesNotPermitPasswordChanges"),
-					GitBlit.getString(Keys.realm.userService, "${baseFolder}/users.conf")), true);
+					app().settings().getString(Keys.realm.userService, "${baseFolder}/users.conf")), true);
 		}
 
 		setupPage(getString("gb.changePassword"), user.username);
@@ -74,7 +73,7 @@
 				}
 
 				// ensure password satisfies minimum length requirement
-				int minLength = GitBlit.getInteger(Keys.realm.minPasswordLength, 5);
+				int minLength = app().settings().getInteger(Keys.realm.minPasswordLength, 5);
 				if (minLength < 4) {
 					minLength = 4;
 				}
@@ -86,7 +85,7 @@
 				UserModel user = GitBlitWebSession.get().getUser();
 
 				// convert to MD5 digest, if appropriate
-				String type = GitBlit.getString(Keys.realm.passwordStorage, "md5");
+				String type = app().settings().getString(Keys.realm.passwordStorage, "md5");
 				if (type.equalsIgnoreCase("md5")) {
 					// store MD5 digest of password
 					password = StringUtils.MD5_TYPE + StringUtils.getMD5(password);
@@ -98,10 +97,10 @@
 
 				user.password = password;
 				try {
-					GitBlit.self().updateUserModel(user.username, user, false);
-					if (GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {
+					app().users().updateUserModel(user.username, user, false);
+					if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) {
 						WebResponse response = (WebResponse) getRequestCycle().getResponse();
-						GitBlit.self().setCookie(response, user);
+						app().session().setCookie(response, user);
 					}
 				} catch (GitBlitException e) {
 					error(e.getMessage());
diff --git a/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java b/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java
index 468fb66..5d14bfe 100644
--- a/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java
@@ -31,7 +31,6 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.models.GitNote;
 import com.gitblit.models.PathModel.PathChangeModel;
 import com.gitblit.models.SubmoduleModel;
@@ -108,7 +107,7 @@
 				item.add(new GravatarImage("noteAuthorAvatar", entry.notesRef.getAuthorIdent()));
 				item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
 						.getAuthorIdent().getWhen(), getTimeZone(), getTimeUtils()));
-				item.add(new Label("noteContent", GitBlit.self().processPlainCommitMessage(repositoryName,
+				item.add(new Label("noteContent", messageProcessor().processPlainCommitMessage(repositoryName,
 						entry.content)).setEscapeModelStrings(false));
 			}
 		};
diff --git a/src/main/java/com/gitblit/wicket/pages/CommitPage.java b/src/main/java/com/gitblit/wicket/pages/CommitPage.java
index 1772f3a..5942233 100644
--- a/src/main/java/com/gitblit/wicket/pages/CommitPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/CommitPage.java
@@ -32,7 +32,6 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.models.GitNote;
 import com.gitblit.models.PathModel.PathChangeModel;
 import com.gitblit.models.SubmoduleModel;
@@ -136,7 +135,7 @@
 				item.add(new GravatarImage("noteAuthorAvatar", entry.notesRef.getAuthorIdent()));
 				item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
 						.getAuthorIdent().getWhen(), getTimeZone(), getTimeUtils()));
-				item.add(new Label("noteContent", GitBlit.self().processPlainCommitMessage(repositoryName,
+				item.add(new Label("noteContent", messageProcessor().processPlainCommitMessage(repositoryName,
 						entry.content)).setEscapeModelStrings(false));
 			}
 		};
diff --git a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
index 46adcff..959a3d3 100644
--- a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
@@ -34,7 +34,6 @@
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.eclipse.jgit.lib.Repository;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.DailyLogEntry;
 import com.gitblit.models.Metric;
@@ -83,7 +82,7 @@
 				continue;
 			}
 			if (model.hasCommits && model.lastChange.after(minimumDate)) {
-				Repository repository = GitBlit.self().getRepository(model.name);
+				Repository repository = app().repositories().getRepository(model.name);
 				List<DailyLogEntry> entries = RefLogUtils.getDailyLogByRef(model.name, repository, minimumDate, timezone);
 				digests.addAll(entries);
 				repository.close();
@@ -123,7 +122,7 @@
 		if (!ArrayUtils.isEmpty(digests)) {
 			// aggregate author exclusions
 			Set<String> authorExclusions = new TreeSet<String>();
-			for (String author : GitBlit.getStrings(Keys.web.metricAuthorExclusions)) {
+			for (String author : app().settings().getStrings(Keys.web.metricAuthorExclusions)) {
 				authorExclusions.add(author.toLowerCase());
 			}
 			for (RepositoryModel model : repositories) {
@@ -217,7 +216,7 @@
 		frag.add(new Label("feedheader", MessageFormat.format(headerPattern,
 				daysBack, totalCommits, authorMetrics.size())));
 
-		if (GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
+		if (app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
 			// build google charts
 			GoogleCharts charts = new GoogleCharts();
 
diff --git a/src/main/java/com/gitblit/wicket/pages/DocPage.java b/src/main/java/com/gitblit/wicket/pages/DocPage.java
index ab0c462..03d2337 100644
--- a/src/main/java/com/gitblit/wicket/pages/DocPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/DocPage.java
@@ -24,7 +24,6 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
 
-import com.gitblit.GitBlit;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.wicket.CacheControl;
@@ -41,11 +40,11 @@
 		super(params);
 
 		final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/");
-		MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
+		MarkupProcessor processor = new MarkupProcessor(app().settings());
 
 		Repository r = getRepository();
 		RevCommit commit = JGitUtils.getCommit(r, objectId);
-		String [] encodings = GitBlit.getEncodings();
+		String [] encodings = getEncodings();
 
 		// Read raw markup content and transform it to html
 		String documentPath = path;
diff --git a/src/main/java/com/gitblit/wicket/pages/DocsPage.java b/src/main/java/com/gitblit/wicket/pages/DocsPage.java
index 174311c..3f9ccdb 100644
--- a/src/main/java/com/gitblit/wicket/pages/DocsPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/DocsPage.java
@@ -30,7 +30,6 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.PathModel;
 import com.gitblit.utils.ByteFormat;
 import com.gitblit.utils.JGitUtils;
@@ -49,7 +48,7 @@
 	public DocsPage(PageParameters params) {
 		super(params);
 
-		MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
+		MarkupProcessor processor = new MarkupProcessor(app().settings());
 
 		Repository r = getRepository();
 		RevCommit head = JGitUtils.getCommit(r, null);
diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
index 1b3cbd6..76b34f3 100644
--- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
@@ -55,7 +55,6 @@
 import com.gitblit.Constants.CommitMessageRenderer;
 import com.gitblit.Constants.FederationStrategy;
 import com.gitblit.Constants.RegistrantType;
-import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
 import com.gitblit.models.RegistrantAccessPermission;
@@ -86,9 +85,9 @@
 		super();
 		isCreate = true;
 		RepositoryModel model = new RepositoryModel();
-		String restriction = GitBlit.getString(Keys.git.defaultAccessRestriction, "PUSH");
+		String restriction = app().settings().getString(Keys.git.defaultAccessRestriction, "PUSH");
 		model.accessRestriction = AccessRestrictionType.fromName(restriction);
-		String authorization = GitBlit.getString(Keys.git.defaultAuthorizationControl, null);
+		String authorization = app().settings().getString(Keys.git.defaultAuthorizationControl, null);
 		model.authorizationControl = AuthorizationControl.fromName(authorization);
 
 		GitBlitWebSession session = GitBlitWebSession.get();
@@ -113,7 +112,7 @@
 		super(params);
 		isCreate = false;
 		String name = WicketUtils.getRepositoryName(params);
-		RepositoryModel model = GitBlit.self().getRepositoryModel(name);
+		RepositoryModel model = app().repositories().getRepositoryModel(name);
 		setupPage(model);
 		setStatelessHint(false);
 		setOutputMarkupId(true);
@@ -154,8 +153,8 @@
 			}
 		} else {
 			super.setupPage(getString("gb.edit"), repositoryModel.name);
-			repositoryUsers.addAll(GitBlit.self().getUserAccessPermissions(repositoryModel));
-			repositoryTeams.addAll(GitBlit.self().getTeamAccessPermissions(repositoryModel));
+			repositoryUsers.addAll(app().repositories().getUserAccessPermissions(repositoryModel));
+			repositoryTeams.addAll(app().repositories().getTeamAccessPermissions(repositoryModel));
 			Collections.sort(repositoryUsers);
 			Collections.sort(repositoryTeams);
 
@@ -168,13 +167,13 @@
 		final String oldName = repositoryModel.name;
 
 		final RegistrantPermissionsPanel usersPalette = new RegistrantPermissionsPanel("users",
-				RegistrantType.USER, GitBlit.self().getAllUsernames(), repositoryUsers, getAccessPermissions());
+				RegistrantType.USER, app().users().getAllUsernames(), repositoryUsers, getAccessPermissions());
 		final RegistrantPermissionsPanel teamsPalette = new RegistrantPermissionsPanel("teams",
-				RegistrantType.TEAM, GitBlit.self().getAllTeamnames(), repositoryTeams, getAccessPermissions());
+				RegistrantType.TEAM, app().users().getAllTeamnames(), repositoryTeams, getAccessPermissions());
 
 		// owners palette
 		List<String> owners = new ArrayList<String>(repositoryModel.owners);
-		List<String> persons = GitBlit.self().getAllUsernames();
+		List<String> persons = app().users().getAllUsernames();
 		final Palette<String> ownersPalette = new Palette<String>("owners", new ListModel<String>(owners), new CollectionModel<String>(
 		      persons), new StringChoiceRenderer(), 12, true);
 
@@ -182,14 +181,14 @@
 		List<String> allLocalBranches = new ArrayList<String>();
 		allLocalBranches.add(Constants.DEFAULT_BRANCH);
 		allLocalBranches.addAll(repositoryModel.getLocalBranches());
-		boolean luceneEnabled = GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true);
+		boolean luceneEnabled = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true);
 		final Palette<String> indexedBranchesPalette = new Palette<String>("indexedBranches", new ListModel<String>(
 				indexedBranches), new CollectionModel<String>(allLocalBranches),
 				new StringChoiceRenderer(), 8, false);
 		indexedBranchesPalette.setEnabled(luceneEnabled);
 
 		// federation sets palette
-		List<String> sets = GitBlit.getStrings(Keys.federation.sets);
+		List<String> sets = app().settings().getStrings(Keys.federation.sets);
 		final Palette<String> federationSetsPalette = new Palette<String>("federationSets",
 				new ListModel<String>(federationSets), new CollectionModel<String>(sets),
 				new StringChoiceRenderer(), 8, false);
@@ -199,8 +198,8 @@
 			preReceiveScripts.addAll(repositoryModel.preReceiveScripts);
 		}
 		final Palette<String> preReceivePalette = new Palette<String>("preReceiveScripts",
-				new ListModel<String>(preReceiveScripts), new CollectionModel<String>(GitBlit
-						.self().getPreReceiveScriptsUnused(repositoryModel)),
+				new ListModel<String>(preReceiveScripts), new CollectionModel<String>(app().repositories()
+						.getPreReceiveScriptsUnused(repositoryModel)),
 				new StringChoiceRenderer(), 12, true);
 
 		// post-receive palette
@@ -208,12 +207,12 @@
 			postReceiveScripts.addAll(repositoryModel.postReceiveScripts);
 		}
 		final Palette<String> postReceivePalette = new Palette<String>("postReceiveScripts",
-				new ListModel<String>(postReceiveScripts), new CollectionModel<String>(GitBlit
-						.self().getPostReceiveScriptsUnused(repositoryModel)),
+				new ListModel<String>(postReceiveScripts), new CollectionModel<String>(app().repositories()
+						.getPostReceiveScriptsUnused(repositoryModel)),
 				new StringChoiceRenderer(), 12, true);
 
 		// custom fields
-		final Map<String, String> customFieldsMap = GitBlit.getMap(Keys.groovy.customFields);
+		final Map<String, String> customFieldsMap = app().settings().getMap(Keys.groovy.customFields);
 		List<String> customKeys = new ArrayList<String>(customFieldsMap.keySet());
 		final ListView<String> customFieldsListView = new ListView<String>("customFieldsListView", customKeys) {
 
@@ -393,12 +392,12 @@
 					}
 
 					// save the repository
-					GitBlit.self().updateRepositoryModel(oldName, repositoryModel, isCreate);
+					app().repositories().updateRepositoryModel(oldName, repositoryModel, isCreate);
 
 					// repository access permissions
 					if (repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
-						GitBlit.self().setUserAccessPermissions(repositoryModel, repositoryUsers);
-						GitBlit.self().setTeamAccessPermissions(repositoryModel, repositoryTeams);
+						app().repositories().setUserAccessPermissions(repositoryModel, repositoryUsers);
+						app().repositories().setTeamAccessPermissions(repositoryModel, repositoryTeams);
 					}
 				} catch (GitBlitException e) {
 					error(e.getMessage());
@@ -416,9 +415,9 @@
 		form.add(new TextField<String>("name").setEnabled(allowEditName));
 		form.add(new TextField<String>("description"));
 		form.add(ownersPalette);
-		form.add(new CheckBox("allowForks").setEnabled(GitBlit.getBoolean(Keys.web.allowForking, true)));
+		form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true)));
 		DropDownChoice<AccessRestrictionType> accessRestriction = new DropDownChoice<AccessRestrictionType>("accessRestriction",
-				AccessRestrictionType.choices(GitBlit.getBoolean(Keys.git.allowAnonymousPushes, false)), new AccessRestrictionRenderer());
+				AccessRestrictionType.choices(app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)), new AccessRestrictionRenderer());
 		form.add(accessRestriction);
 		form.add(new CheckBox("isFrozen"));
 		// TODO enable origin definition
@@ -431,7 +430,7 @@
 		}
 		form.add(new DropDownChoice<String>("HEAD", availableRefs).setEnabled(availableRefs.size() > 0));
 
-		boolean gcEnabled = GitBlit.getBoolean(Keys.git.enableGarbageCollection, false);
+		boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false);
 		List<Integer> gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 );
 		form.add(new DropDownChoice<Integer>("gcPeriod", gcPeriods, new GCPeriodRenderer()).setEnabled(gcEnabled));
 		form.add(new TextField<String>("gcThreshold").setEnabled(gcEnabled));
@@ -474,15 +473,15 @@
 		form.add(teamsPalette);
 		form.add(federationSetsPalette);
 		form.add(preReceivePalette);
-		form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), GitBlit.self()
+		form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), app().repositories()
 				.getPreReceiveScriptsInherited(repositoryModel)));
 		form.add(postReceivePalette);
-		form.add(new BulletListPanel("inheritedPostReceive", getString("gb.inherited"), GitBlit.self()
+		form.add(new BulletListPanel("inheritedPostReceive", getString("gb.inherited"), app().repositories()
 				.getPostReceiveScriptsInherited(repositoryModel)));
 
 		WebMarkupContainer customFieldsSection = new WebMarkupContainer("customFieldsSection");
 		customFieldsSection.add(customFieldsListView);
-		form.add(customFieldsSection.setVisible(!GitBlit.getString(Keys.groovy.customFields, "").isEmpty()));
+		form.add(customFieldsSection.setVisible(!app().settings().getString(Keys.groovy.customFields, "").isEmpty()));
 
 		// initial enable/disable of permission controls
 		if (repositoryModel.accessRestriction.equals(AccessRestrictionType.NONE)) {
@@ -579,8 +578,8 @@
 	 * Repository Owners should be able to edit their repository.
 	 */
 	private void checkPermissions(RepositoryModel model) {
-		boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
-		boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, true);
+		boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true);
+		boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true);
 
 		GitBlitWebSession session = GitBlitWebSession.get();
 		UserModel user = session.getUser();
diff --git a/src/main/java/com/gitblit/wicket/pages/EditTeamPage.java b/src/main/java/com/gitblit/wicket/pages/EditTeamPage.java
index 617aa86..32905c9 100644
--- a/src/main/java/com/gitblit/wicket/pages/EditTeamPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/EditTeamPage.java
@@ -37,7 +37,6 @@
 import org.apache.wicket.model.util.ListModel;
 
 import com.gitblit.Constants.RegistrantType;
-import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
 import com.gitblit.models.RegistrantAccessPermission;
@@ -70,7 +69,7 @@
 		super(params);
 		isCreate = false;
 		String name = WicketUtils.getTeamname(params);
-		TeamModel model = GitBlit.self().getTeamModel(name);
+		TeamModel model = app().users().getTeamModel(name);
 		setupPage(model);
 		setStatelessHint(false);
 		setOutputMarkupId(true);
@@ -107,7 +106,7 @@
 
 		// users palette
 		final Palette<String> users = new Palette<String>("users", new ListModel<String>(
-				new ArrayList<String>(teamUsers)), new CollectionModel<String>(GitBlit.self()
+				new ArrayList<String>(teamUsers)), new CollectionModel<String>(app().users()
 				.getAllUsernames()), new StringChoiceRenderer(), 10, false);
 
 		// pre-receive palette
@@ -115,8 +114,8 @@
 			preReceiveScripts.addAll(teamModel.preReceiveScripts);
 		}
 		final Palette<String> preReceivePalette = new Palette<String>("preReceiveScripts",
-				new ListModel<String>(preReceiveScripts), new CollectionModel<String>(GitBlit
-						.self().getPreReceiveScriptsUnused(null)), new StringChoiceRenderer(),
+				new ListModel<String>(preReceiveScripts), new CollectionModel<String>(app().repositories()
+						.getPreReceiveScriptsUnused(null)), new StringChoiceRenderer(),
 						12, true);
 
 		// post-receive palette
@@ -124,8 +123,8 @@
 			postReceiveScripts.addAll(teamModel.postReceiveScripts);
 		}
 		final Palette<String> postReceivePalette = new Palette<String>("postReceiveScripts",
-				new ListModel<String>(postReceiveScripts), new CollectionModel<String>(GitBlit
-						.self().getPostReceiveScriptsUnused(null)), new StringChoiceRenderer(),
+				new ListModel<String>(postReceiveScripts), new CollectionModel<String>(app().repositories()
+						.getPostReceiveScriptsUnused(null)), new StringChoiceRenderer(),
 								12, true);
 
 		Form<TeamModel> form = new Form<TeamModel>("editForm", model) {
@@ -145,7 +144,7 @@
 					return;
 				}
 				if (isCreate) {
-					TeamModel model = GitBlit.self().getTeamModel(teamname);
+					TeamModel model = app().users().getTeamModel(teamname);
 					if (model != null) {
 						error(MessageFormat.format(getString("gb.teamNameUnavailable"), teamname));
 						return;
@@ -197,7 +196,7 @@
 				teamModel.postReceiveScripts.addAll(postReceiveScripts);
 
 				try {
-					GitBlit.self().updateTeamModel(oldName, teamModel, isCreate);
+					app().users().updateTeamModel(oldName, teamModel, isCreate);
 				} catch (GitBlitException e) {
 					error(e.getMessage());
 					return;
@@ -217,12 +216,12 @@
 		form.add(new SimpleAttributeModifier("autocomplete", "off"));
 
 		// not all user services support manipulating team memberships
-		boolean editMemberships = GitBlit.self().supportsTeamMembershipChanges(null);
+		boolean editMemberships = app().users().supportsTeamMembershipChanges(null);
 
 		// field names reflective match TeamModel fields
 		form.add(new TextField<String>("name"));
 		form.add(new CheckBox("canAdmin"));
-		form.add(new CheckBox("canFork").setEnabled(GitBlit.getBoolean(Keys.web.allowForking, true)));
+		form.add(new CheckBox("canFork").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true)));
 		form.add(new CheckBox("canCreate"));
 		form.add(users.setEnabled(editMemberships));
 		mailingLists = new Model<String>(teamModel.mailingLists == null ? ""
@@ -232,10 +231,10 @@
 		form.add(new RegistrantPermissionsPanel("repositories", RegistrantType.REPOSITORY,
 				repos, permissions, getAccessPermissions()));
 		form.add(preReceivePalette);
-		form.add(new BulletListPanel("inheritedPreReceive", "inherited", GitBlit.self()
+		form.add(new BulletListPanel("inheritedPreReceive", "inherited", app().repositories()
 				.getPreReceiveScriptsInherited(null)));
 		form.add(postReceivePalette);
-		form.add(new BulletListPanel("inheritedPostReceive", "inherited", GitBlit.self()
+		form.add(new BulletListPanel("inheritedPostReceive", "inherited", app().repositories()
 				.getPostReceiveScriptsInherited(null)));
 
 		form.add(new Button("save"));
diff --git a/src/main/java/com/gitblit/wicket/pages/EditUserPage.java b/src/main/java/com/gitblit/wicket/pages/EditUserPage.java
index 6838c19..d0e52f4 100644
--- a/src/main/java/com/gitblit/wicket/pages/EditUserPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/EditUserPage.java
@@ -35,7 +35,6 @@
 import org.apache.wicket.model.util.ListModel;
 
 import com.gitblit.Constants.RegistrantType;
-import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
 import com.gitblit.models.RegistrantAccessPermission;
@@ -55,9 +54,9 @@
 	public EditUserPage() {
 		// create constructor
 		super();
-		if (!GitBlit.self().supportsAddUser()) {
+		if (!app().users().supportsAddUser()) {
 			error(MessageFormat.format(getString("gb.userServiceDoesNotPermitAddUser"),
-					GitBlit.getString(Keys.realm.userService, "${baseFolder}/users.conf")), true);
+					app().settings().getString(Keys.realm.userService, "${baseFolder}/users.conf")), true);
 		}
 		isCreate = true;
 		setupPage(new UserModel(""));
@@ -70,7 +69,7 @@
 		super(params);
 		isCreate = false;
 		String name = WicketUtils.getUsername(params);
-		UserModel model = GitBlit.self().getUserModel(name);
+		UserModel model = app().users().getUserModel(name);
 		setupPage(model);
 		setStatelessHint(false);
 		setOutputMarkupId(true);
@@ -107,10 +106,10 @@
 		Collections.sort(userTeams);
 
 		final String oldName = userModel.username;
-		final List<RegistrantAccessPermission> permissions = GitBlit.self().getUserAccessPermissions(userModel);
+		final List<RegistrantAccessPermission> permissions = app().repositories().getUserAccessPermissions(userModel);
 
 		final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(
-				new ArrayList<String>(userTeams)), new CollectionModel<String>(GitBlit.self()
+				new ArrayList<String>(userTeams)), new CollectionModel<String>(app().users()
 				.getAllTeamnames()), new StringChoiceRenderer(), 10, false);
 		Form<UserModel> form = new Form<UserModel>("editForm", model) {
 
@@ -131,7 +130,7 @@
 				userModel.username = userModel.username.toLowerCase();
 				String username = userModel.username;
 				if (isCreate) {
-					UserModel model = GitBlit.self().getUserModel(username);
+					UserModel model = app().users().getUserModel(username);
 					if (model != null) {
 						error(MessageFormat.format(getString("gb.usernameUnavailable"), username));
 						return;
@@ -139,7 +138,7 @@
 				}
 				boolean rename = !StringUtils.isEmpty(oldName)
 						&& !oldName.equalsIgnoreCase(username);
-				if (GitBlit.self().supportsCredentialChanges(userModel)) {
+				if (app().users().supportsCredentialChanges(userModel)) {
 					if (!userModel.password.equals(confirmPassword.getObject())) {
 						error(getString("gb.passwordsDoNotMatch"));
 						return;
@@ -149,7 +148,7 @@
 							&& !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
 						// This is a plain text password.
 						// Check length.
-						int minLength = GitBlit.getInteger(Keys.realm.minPasswordLength, 5);
+						int minLength = app().settings().getInteger(Keys.realm.minPasswordLength, 5);
 						if (minLength < 4) {
 							minLength = 4;
 						}
@@ -160,7 +159,7 @@
 						}
 
 						// Optionally store the password MD5 digest.
-						String type = GitBlit.getString(Keys.realm.passwordStorage, "md5");
+						String type = app().settings().getString(Keys.realm.passwordStorage, "md5");
 						if (type.equalsIgnoreCase("md5")) {
 							// store MD5 digest of password
 							userModel.password = StringUtils.MD5_TYPE
@@ -185,7 +184,7 @@
 				Iterator<String> selectedTeams = teams.getSelectedChoices();
 				userModel.teams.clear();
 				while (selectedTeams.hasNext()) {
-					TeamModel team = GitBlit.self().getTeamModel(selectedTeams.next());
+					TeamModel team = app().users().getTeamModel(selectedTeams.next());
 					if (team == null) {
 						continue;
 					}
@@ -193,7 +192,7 @@
 				}
 
 				try {
-					GitBlit.self().updateUserModel(oldName, userModel, isCreate);
+					app().users().updateUserModel(oldName, userModel, isCreate);
 				} catch (GitBlitException e) {
 					error(e.getMessage());
 					return;
@@ -215,16 +214,16 @@
 		form.add(new SimpleAttributeModifier("autocomplete", "off"));
 
 		// not all user services support manipulating username and password
-		boolean editCredentials = GitBlit.self().supportsCredentialChanges(userModel);
+		boolean editCredentials = app().users().supportsCredentialChanges(userModel);
 
 		// not all user services support manipulating display name
-		boolean editDisplayName = GitBlit.self().supportsDisplayNameChanges(userModel);
+		boolean editDisplayName = app().users().supportsDisplayNameChanges(userModel);
 
 		// not all user services support manipulating email address
-		boolean editEmailAddress = GitBlit.self().supportsEmailAddressChanges(userModel);
+		boolean editEmailAddress = app().users().supportsEmailAddressChanges(userModel);
 
 		// not all user services support manipulating team memberships
-		boolean editTeams = GitBlit.self().supportsTeamMembershipChanges(userModel);
+		boolean editTeams = app().users().supportsTeamMembershipChanges(userModel);
 
 		// field names reflective match UserModel fields
 		form.add(new TextField<String>("username").setEnabled(editCredentials));
@@ -238,7 +237,7 @@
 		form.add(new TextField<String>("displayName").setEnabled(editDisplayName));
 		form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress));
 		form.add(new CheckBox("canAdmin"));
-		form.add(new CheckBox("canFork").setEnabled(GitBlit.getBoolean(Keys.web.allowForking, true)));
+		form.add(new CheckBox("canFork").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true)));
 		form.add(new CheckBox("canCreate"));
 		form.add(new CheckBox("excludeFromFederation"));
 		form.add(new RegistrantPermissionsPanel("repositories",	RegistrantType.REPOSITORY, repos, permissions, getAccessPermissions()));
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java
index 4e05fad..9e4d355 100644
--- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java
@@ -24,7 +24,6 @@
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.protocol.http.WebRequest;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.RepositoryUrl;
 import com.gitblit.models.UserModel;
@@ -41,7 +40,7 @@
 		setVersioned(false);
 
 		String repositoryName = WicketUtils.getRepositoryName(params);
-		RepositoryModel repository = GitBlit.self().getRepositoryModel(repositoryName);
+		RepositoryModel repository = app().repositories().getRepositoryModel(repositoryName);
 		if (repository == null) {
 			error(getString("gb.canNotLoadRepository") + " " + repositoryName, true);
 		}
@@ -59,7 +58,7 @@
 		}
 
 		HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
-		List<RepositoryUrl> repositoryUrls = GitBlit.self().getRepositoryUrls(req, user, repository);
+		List<RepositoryUrl> repositoryUrls = app().repositories().getRepositoryUrls(req, user, repository);
 		RepositoryUrl primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
 		String url = primaryUrl != null ? primaryUrl.url : "";
 
diff --git a/src/main/java/com/gitblit/wicket/pages/FederationPage.java b/src/main/java/com/gitblit/wicket/pages/FederationPage.java
index 1f98c17..a834293 100644
--- a/src/main/java/com/gitblit/wicket/pages/FederationPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/FederationPage.java
@@ -15,7 +15,6 @@
  */
 package com.gitblit.wicket.pages;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.wicket.panels.FederationProposalsPanel;
 import com.gitblit.wicket.panels.FederationRegistrationsPanel;
@@ -27,7 +26,7 @@
 		super();
 		setupPage("", "");
 
-		boolean showFederation = showAdmin && GitBlit.canFederate();
+		boolean showFederation = showAdmin && app().federation().canFederate();
 		add(new FederationTokensPanel("federationTokensPanel", showFederation)
 				.setVisible(showFederation));
 		FederationProposalsPanel proposalsPanel = new FederationProposalsPanel(
@@ -38,7 +37,7 @@
 			proposalsPanel.setVisible(false);
 		}
 
-		boolean showRegistrations = GitBlit.getBoolean(Keys.web.showFederationRegistrations, false);
+		boolean showRegistrations = app().settings().getBoolean(Keys.web.showFederationRegistrations, false);
 		FederationRegistrationsPanel registrationsPanel = new FederationRegistrationsPanel(
 				"federationRegistrationsPanel");
 		if (showAdmin || showRegistrations) {
diff --git a/src/main/java/com/gitblit/wicket/pages/FederationRegistrationPage.java b/src/main/java/com/gitblit/wicket/pages/FederationRegistrationPage.java
index 42f4694..c26c975 100644
--- a/src/main/java/com/gitblit/wicket/pages/FederationRegistrationPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/FederationRegistrationPage.java
@@ -24,7 +24,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.FederationModel;
 import com.gitblit.models.FederationModel.RepositoryStatus;
 import com.gitblit.wicket.WicketUtils;
@@ -39,7 +38,7 @@
 		String url = WicketUtils.getUrlParameter(params);
 		String name = WicketUtils.getNameParameter(params);
 
-		FederationModel registration = GitBlit.self().getFederationRegistration(url, name);
+		FederationModel registration = app().federation().getFederationRegistration(url, name);
 		if (registration == null) {
 			error(getString("gb.couldNotFindFederationRegistration"), true);
 		}
diff --git a/src/main/java/com/gitblit/wicket/pages/ForkPage.java b/src/main/java/com/gitblit/wicket/pages/ForkPage.java
index fe316ff..1202012 100644
--- a/src/main/java/com/gitblit/wicket/pages/ForkPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ForkPage.java
@@ -21,9 +21,9 @@
 import org.apache.wicket.markup.html.basic.Label;
 import org.slf4j.LoggerFactory;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.wicket.GitBlitWebApp;
 import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.GitblitRedirectException;
 import com.gitblit.wicket.WicketUtils;
@@ -49,7 +49,7 @@
 			throw new GitblitRedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(repository.name));
 		}
 
-		String fork = GitBlit.self().getFork(user.username, repository.name);
+		String fork = app().repositories().getFork(user.username, repository.name);
 		if (fork != null) {
 			// redirect to user's fork
 			throw new GitblitRedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(fork));
@@ -62,7 +62,7 @@
 			session.isForking(true);
 
 			// fork it
-			ForkThread forker = new ForkThread(repository, session);
+			ForkThread forker = new ForkThread(app(), repository, session);
 			forker.start();
 		}
 	}
@@ -84,10 +84,12 @@
 	 */
 	private static class ForkThread extends Thread {
 
+		private final GitBlitWebApp app;
 		private final RepositoryModel repository;
 		private final GitBlitWebSession session;
 
-		public ForkThread(RepositoryModel repository, GitBlitWebSession session) {
+		public ForkThread(GitBlitWebApp app, RepositoryModel repository, GitBlitWebSession session) {
+			this.app = app;
 			this.repository = repository;
 			this.session = session;
 		}
@@ -96,7 +98,7 @@
 		public void run() {
 			UserModel user = session.getUser();
 			try {
-				GitBlit.self().fork(repository, user);
+				app.gitblit().fork(repository, user);
 			} catch (Exception e) {
 				LoggerFactory.getLogger(ForkPage.class).error(MessageFormat.format("Failed to fork {0} for {1}", repository.name, user.username), e);
 			} finally {
diff --git a/src/main/java/com/gitblit/wicket/pages/ForksPage.java b/src/main/java/com/gitblit/wicket/pages/ForksPage.java
index 5b5fcc0..9fd7f4d 100644
--- a/src/main/java/com/gitblit/wicket/pages/ForksPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ForksPage.java
@@ -27,7 +27,6 @@
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 import org.eclipse.jgit.lib.PersonIdent;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ForkModel;
 import com.gitblit.models.RepositoryModel;
@@ -45,7 +44,7 @@
 
 		final RepositoryModel pageRepository = getRepositoryModel();
 
-		ForkModel root = GitBlit.self().getForkNetwork(pageRepository.name);
+		ForkModel root = app().repositories().getForkNetwork(pageRepository.name);
 		List<FlatFork> network = flatten(root);
 
 		ListDataProvider<FlatFork> forksDp = new ListDataProvider<FlatFork>(network);
@@ -58,7 +57,7 @@
 				RepositoryModel repository = fork.repository;
 
 				if (repository.isPersonalRepository()) {
-					UserModel user = GitBlit.self().getUserModel(repository.projectPath.substring(1));
+					UserModel user = app().users().getUserModel(repository.projectPath.substring(1));
 					if (user == null) {
 						// user account no longer exists
 						user = new UserModel(repository.projectPath.substring(1));
@@ -84,7 +83,7 @@
 					item.add(swatch);
 					String projectName = repository.projectPath;
 					if (StringUtils.isEmpty(projectName)) {
-						projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");
+						projectName = app().settings().getString(Keys.web.repositoryRootGroupName, "main");
 					}
 					if (pageRepository.equals(repository)) {
 						// do not link to self
diff --git a/src/main/java/com/gitblit/wicket/pages/LogoutPage.java b/src/main/java/com/gitblit/wicket/pages/LogoutPage.java
index ff3b507..f7be99a 100644
--- a/src/main/java/com/gitblit/wicket/pages/LogoutPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/LogoutPage.java
@@ -18,7 +18,6 @@
 import org.apache.wicket.protocol.http.WebRequest;
 import org.apache.wicket.protocol.http.WebResponse;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.UserModel;
 import com.gitblit.wicket.GitBlitWebSession;
 
@@ -28,8 +27,8 @@
 		super();
 		GitBlitWebSession session = GitBlitWebSession.get();
 		UserModel user = session.getUser();
-		GitBlit.self().setCookie((WebResponse) getResponse(), null);
-		GitBlit.self().logout(user);
+		app().session().setCookie((WebResponse) getResponse(), null);
+		app().session().logout(user);
 		session.invalidate();
 
 		/*
diff --git a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
index 86a426c..4d4545a 100644
--- a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
@@ -32,7 +32,6 @@
 import org.eclipse.jgit.lib.Constants;
 
 import com.gitblit.Constants.SearchType;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.SearchResult;
@@ -65,7 +64,7 @@
 		ArrayList<String> repositories = new ArrayList<String>();
 		String query = "";
 		int page = 1;
-		int pageSize = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
+		int pageSize = app().settings().getInteger(Keys.web.itemsPerPage, 50);
 
 		if (params != null) {
 			String repository = WicketUtils.getRepositoryName(params);
@@ -100,12 +99,12 @@
 		// display user-accessible selections
 		UserModel user = GitBlitWebSession.get().getUser();
 		List<String> availableRepositories = new ArrayList<String>();
-		for (RepositoryModel model : GitBlit.self().getRepositoryModels(user)) {
+		for (RepositoryModel model : app().repositories().getRepositoryModels(user)) {
 			if (model.hasCommits && !ArrayUtils.isEmpty(model.indexedBranches)) {
 				availableRepositories.add(model.name);
 			}
 		}
-		boolean luceneEnabled = GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true);
+		boolean luceneEnabled = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true);
 		if (luceneEnabled) {
 			if (availableRepositories.size() == 0) {
 				info(getString("gb.noIndexedRepositoriesWarning"));
@@ -158,7 +157,7 @@
 		// execute search
 		final List<SearchResult> results = new ArrayList<SearchResult>();
 		if (!ArrayUtils.isEmpty(searchRepositories) && !StringUtils.isEmpty(query)) {
-			results.addAll(GitBlit.self().search(query, page, pageSize, searchRepositories));
+			results.addAll(app().repositories().search(query, page, pageSize, searchRepositories));
 		}
 
 		// results header
diff --git a/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java
index 8e05b4f..ba85b82 100644
--- a/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java
@@ -35,7 +35,6 @@
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.eclipse.jgit.lib.Constants;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
 import com.gitblit.models.RepositoryModel;
@@ -71,9 +70,9 @@
 	private void setup(PageParameters params) {
 		setupPage("", "");
 		// check to see if we should display a login message
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
 		if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
-			String messageSource = GitBlit.getString(Keys.web.loginMessage, "gitblit");
+			String messageSource = app().settings().getString(Keys.web.loginMessage, "gitblit");
 			String message = readMarkdown(messageSource, "login.mkd");
 			Component repositoriesMessage = new Label("repositoriesMessage", message);
 			add(repositoriesMessage.setEscapeModelStrings(false));
@@ -83,7 +82,7 @@
 		}
 
 		// Load the markdown welcome message
-		String messageSource = GitBlit.getString(Keys.web.repositoriesMessage, "gitblit");
+		String messageSource = app().settings().getString(Keys.web.repositoriesMessage, "gitblit");
 		String message = readMarkdown(messageSource, "welcome.mkd");
 		Component repositoriesMessage = new Label("repositoriesMessage", message)
 				.setEscapeModelStrings(false).setVisible(message.length() > 0);
@@ -96,9 +95,9 @@
 
 		// parameters
 		int daysBack = params == null ? 0 : WicketUtils.getDaysBack(params);
-		int maxDaysBack = GitBlit.getInteger(Keys.web.activityDurationMaximum, 30);
+		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
 		if (daysBack < 1) {
-			daysBack = GitBlit.getInteger(Keys.web.activityDuration, 7);
+			daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
 		}
 		if (maxDaysBack > 0 && daysBack > maxDaysBack) {
 			daysBack = maxDaysBack;
@@ -168,7 +167,7 @@
 		add(repositoryTabs);
 
 		// projects list
-		List<ProjectModel> projects = GitBlit.self().getProjectModels(getRepositoryModels(), false);
+		List<ProjectModel> projects = app().projects().getProjectModels(getRepositoryModels(), false);
 		repositoryTabs.add(new FilterableProjectList("projects", projects));
 
 		// active repository list
@@ -208,7 +207,7 @@
 		} else {
 			// Read user-supplied message
 			if (!StringUtils.isEmpty(messageSource)) {
-				File file = GitBlit.getFileOrFolder(messageSource);
+				File file = app().runtime().getFileOrFolder(messageSource);
 				if (file.exists()) {
 					try {
 						FileInputStream fis = new FileInputStream(file);
diff --git a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
index f6362c2..efb7f4c 100644
--- a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
@@ -28,7 +28,6 @@
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 import org.eclipse.jgit.lib.Repository;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.Metric;
 import com.gitblit.models.RepositoryModel;
@@ -53,7 +52,7 @@
 	public OverviewPage(PageParameters params) {
 		super(params);
 
-		int numberRefs = GitBlit.getInteger(Keys.web.summaryRefsCount, 5);
+		int numberRefs = app().settings().getInteger(Keys.web.summaryRefsCount, 5);
 
 		Repository r = getRepository();
 		final RepositoryModel model = getRepositoryModel();
@@ -64,8 +63,8 @@
 
 		List<Metric> metrics = null;
 		Metric metricsTotal = null;
-		if (!model.skipSummaryMetrics && GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
-			metrics = GitBlit.self().getRepositoryDefaultMetrics(model, r);
+		if (!model.skipSummaryMetrics && app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
+			metrics = app().repositories().getRepositoryDefaultMetrics(model, r);
 			metricsTotal = metrics.remove(0);
 		}
 
@@ -83,7 +82,7 @@
 			@Override
 			public void populateItem(final Item<String> item) {
 				String ownername = item.getModelObject();
-				UserModel ownerModel = GitBlit.self().getUserModel(ownername);
+				UserModel ownerModel = app().users().getUserModel(ownername);
 				if (ownerModel != null) {
 					item.add(new LinkPanel("owner", null, ownerModel.getDisplayName(), UserPage.class,
 							WicketUtils.newUsernameParameter(ownerModel.username)).setRenderBodyOnly(true));
@@ -117,7 +116,7 @@
 
 		add(new RepositoryUrlPanel("repositoryUrlPanel", false, user, model));
 
-		int reflogCount = GitBlit.getInteger(Keys.web.overviewReflogCount, 5);
+		int reflogCount = app().settings().getInteger(Keys.web.overviewReflogCount, 5);
 		ReflogPanel reflog = new ReflogPanel("reflogPanel", getRepositoryModel(), r, reflogCount, 0);
 		add(reflog);
 		add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());
@@ -134,7 +133,7 @@
 
 	private void insertActivityGraph(List<Metric> metrics) {
 		if ((metrics != null) && (metrics.size() > 0)
-				&& GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
+				&& app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
 
 			// daily line chart
 			GoogleChart chart = new GoogleLineChart("chartDaily", "", "unit",
diff --git a/src/main/java/com/gitblit/wicket/pages/PatchPage.java b/src/main/java/com/gitblit/wicket/pages/PatchPage.java
index be959d0..ece4136 100644
--- a/src/main/java/com/gitblit/wicket/pages/PatchPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/PatchPage.java
@@ -16,12 +16,10 @@
 package com.gitblit.wicket.pages;
 
 import org.apache.wicket.PageParameters;
-import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
 
-import com.gitblit.GitBlit;
 import com.gitblit.utils.DiffUtils;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
@@ -31,7 +29,7 @@
 import com.gitblit.wicket.WicketUtils;
 
 @CacheControl(LastModified.BOOT)
-public class PatchPage extends WebPage {
+public class PatchPage extends SessionPage {
 
 	public PatchPage(PageParameters params) {
 		super(params);
@@ -47,7 +45,7 @@
 		final String objectId = WicketUtils.getObject(params);
 		final String blobPath = WicketUtils.getPath(params);
 
-		Repository r = GitBlit.self().getRepository(repositoryName);
+		Repository r = app().repositories().getRepository(repositoryName);
 		if (r == null) {
 			GitBlitWebSession.get().cacheErrorMessage(getString("gb.canNotLoadRepository") + " " + repositoryName);
 			redirectToInterceptPage(new RepositoriesPage());
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
index 19588a9..22396be 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
@@ -25,7 +25,6 @@
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.ExternalLink;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.SyndicationServlet;
 import com.gitblit.models.ProjectModel;
@@ -87,7 +86,7 @@
 	private void setup(PageParameters params) {
 		setupPage("", "");
 		// check to see if we should display a login message
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
 		if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
 			authenticationError("Please login");
 			return;
@@ -130,7 +129,7 @@
 		}
 		int daysBack = params == null ? 0 : WicketUtils.getDaysBack(params);
 		if (daysBack < 1) {
-			daysBack = GitBlit.getInteger(Keys.web.activityDuration, 7);
+			daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
 		}
 		// reset the daysback parameter so that we have a complete project
 		// repository list.  the recent activity will be built up by the
@@ -186,7 +185,7 @@
 	protected List<ProjectModel> getProjectModels() {
 		if (projectModels.isEmpty()) {
 			List<RepositoryModel> repositories = getRepositoryModels();
-			List<ProjectModel> projects = GitBlit.self().getProjectModels(repositories, false);
+			List<ProjectModel> projects = app().projects().getProjectModels(repositories, false);
 			projectModels.addAll(projects);
 		}
 		return projectModels;
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
index e500046..77d4984 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
@@ -23,7 +23,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
 import com.gitblit.wicket.GitBlitWebSession;
@@ -57,13 +56,13 @@
 
 	@Override
 	protected List<ProjectModel> getProjectModels() {
-		return GitBlit.self().getProjectModels(getRepositoryModels(), false);
+		return app().projects().getProjectModels(getRepositoryModels(), false);
 	}
 
 	private void setup(PageParameters params) {
 		setupPage("", "");
 		// check to see if we should display a login message
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
 		if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
 			add(new Label("projectsPanel"));
 			return;
diff --git a/src/main/java/com/gitblit/wicket/pages/RawPage.java b/src/main/java/com/gitblit/wicket/pages/RawPage.java
index 1783764..ac4af6d 100644
--- a/src/main/java/com/gitblit/wicket/pages/RawPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RawPage.java
@@ -31,7 +31,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
@@ -66,11 +65,11 @@
 				final String repositoryName = WicketUtils.getRepositoryName(params);
 				final String objectId = WicketUtils.getObject(params);
 				final String blobPath = WicketUtils.getPath(params);
-				String[] encodings = GitBlit.getEncodings();
+				String[] encodings = getEncodings();
 				GitBlitWebSession session = GitBlitWebSession.get();
 				UserModel user = session.getUser();
 
-				RepositoryModel model = GitBlit.self().getRepositoryModel(user, repositoryName);
+				RepositoryModel model = app().repositories().getRepositoryModel(user, repositoryName);
 				if (model == null) {
 					// user does not have permission
 					error(getString("gb.canNotLoadRepository") + " " + repositoryName);
@@ -78,7 +77,7 @@
 					return;
 				}
 
-				Repository r = GitBlit.self().getRepository(repositoryName);
+				Repository r = app().repositories().getRepository(repositoryName);
 				if (r == null) {
 					error(getString("gb.canNotLoadRepository") + " " + repositoryName);
 					redirectToInterceptPage(new RepositoriesPage());
@@ -112,10 +111,10 @@
 
 					// Map the extensions to types
 					Map<String, Integer> map = new HashMap<String, Integer>();
-					for (String ext : GitBlit.getStrings(Keys.web.imageExtensions)) {
+					for (String ext : app().settings().getStrings(Keys.web.imageExtensions)) {
 						map.put(ext.toLowerCase(), 2);
 					}
-					for (String ext : GitBlit.getStrings(Keys.web.binaryExtensions)) {
+					for (String ext : app().settings().getStrings(Keys.web.binaryExtensions)) {
 						map.put(ext.toLowerCase(), 3);
 					}
 
diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java
index b446279..70266f8 100644
--- a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -28,7 +28,6 @@
 import org.apache.wicket.markup.html.basic.Label;
 import org.eclipse.jgit.lib.Constants;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.utils.MarkdownUtils;
@@ -63,9 +62,9 @@
 	private void setup(PageParameters params) {
 		setupPage("", "");
 		// check to see if we should display a login message
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
 		if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
-			String messageSource = GitBlit.getString(Keys.web.loginMessage, "gitblit");
+			String messageSource = app().settings().getString(Keys.web.loginMessage, "gitblit");
 			String message = readMarkdown(messageSource, "login.mkd");
 			Component repositoriesMessage = new Label("repositoriesMessage", message);
 			add(repositoriesMessage.setEscapeModelStrings(false));
@@ -74,7 +73,7 @@
 		}
 
 		// Load the markdown welcome message
-		String messageSource = GitBlit.getString(Keys.web.repositoriesMessage, "gitblit");
+		String messageSource = app().settings().getString(Keys.web.repositoriesMessage, "gitblit");
 		String message = readMarkdown(messageSource, "welcome.mkd");
 		Component repositoriesMessage = new Label("repositoriesMessage", message)
 				.setEscapeModelStrings(false).setVisible(message.length() > 0);
@@ -120,7 +119,7 @@
 		} else {
 			// Read user-supplied message
 			if (!StringUtils.isEmpty(messageSource)) {
-				File file = GitBlit.getFileOrFolder(messageSource);
+				File file = app().runtime().getFileOrFolder(messageSource);
 				if (file.exists()) {
 					try {
 						FileInputStream fis = new FileInputStream(file);
diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
index 93af1be..e19c195 100644
--- a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
@@ -46,7 +46,6 @@
 import org.slf4j.LoggerFactory;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
 import com.gitblit.Keys;
 import com.gitblit.PagesServlet;
@@ -60,6 +59,7 @@
 import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.DeepCopier;
 import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.MessageProcessor;
 import com.gitblit.utils.RefLogUtils;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.wicket.CacheControl;
@@ -97,7 +97,7 @@
 		repositoryName = WicketUtils.getRepositoryName(params);
 		String root =StringUtils.getFirstPathElement(repositoryName);
 		if (StringUtils.isEmpty(root)) {
-			projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");
+			projectName = app().settings().getString(Keys.web.repositoryRootGroupName, "main");
 		} else {
 			projectName = root;
 		}
@@ -139,7 +139,7 @@
 				UserRepositoryPreferences prefs = user.getPreferences().getRepositoryPreferences(getRepositoryModel().name);
 				prefs.starred = star;
 				try {
-					GitBlit.self().updateUserModel(user.username, user, false);
+					app().users().updateUserModel(user.username, user, false);
 				} catch (GitBlitException e) {
 					logger.error("Failed to update user " + user.username, e);
 					error(getString("gb.failedToUpdateUser"), false);
@@ -176,6 +176,10 @@
 		return getClass();
 	}
 
+	protected MessageProcessor messageProcessor() {
+		return new MessageProcessor(app().settings());
+	}
+
 	private Map<String, PageRegistration> registerPages() {
 		PageParameters params = null;
 		if (!StringUtils.isEmpty(repositoryName)) {
@@ -198,7 +202,7 @@
 		pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));
 		pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true));
 		pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true));
-		if (GitBlit.getBoolean(Keys.web.allowForking, true)) {
+		if (app().settings().getBoolean(Keys.web.allowForking, true)) {
 			pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true));
 		}
 
@@ -212,11 +216,11 @@
 
 		// Conditionally add edit link
 		showAdmin = false;
-		if (GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {
-			boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
+		if (app().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
+			boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
 			showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
 		} else {
-			showAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
+			showAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
 		}
 		isOwner = GitBlitWebSession.get().isLoggedIn()
 				&& (model.isOwner(GitBlitWebSession.get()
@@ -225,13 +229,13 @@
 	}
 
 	protected boolean allowForkControls() {
-		return GitBlit.getBoolean(Keys.web.allowForking, true);
+		return app().settings().getBoolean(Keys.web.allowForking, true);
 	}
 
 	@Override
 	protected void setupPage(String repositoryName, String pageName) {
 		String projectName = StringUtils.getFirstPathElement(repositoryName);
-		ProjectModel project = GitBlit.self().getProjectModel(projectName);
+		ProjectModel project = app().projects().getProjectModel(projectName);
 		if (project.isUserProject()) {
 			// user-as-project
 			add(new LinkPanel("projectTitle", null, project.getDisplayName(),
@@ -267,7 +271,7 @@
 				add(new Label("originRepository").setVisible(false));
 			}
 		} else {
-			RepositoryModel origin = GitBlit.self().getRepositoryModel(model.originRepository);
+			RepositoryModel origin = app().repositories().getRepositoryModel(model.originRepository);
 			if (origin == null) {
 				// no origin repository
 				add(new Label("originRepository").setVisible(false));
@@ -311,7 +315,7 @@
 			add(new ExternalLink("forkLink", "").setVisible(false));
 			add(new ExternalLink("myForkLink", "").setVisible(false));
 		} else {
-			String fork = GitBlit.self().getFork(user.username, model.name);
+			String fork = app().repositories().getFork(user.username, model.name);
 			boolean hasFork = fork != null;
 			boolean canFork = user.canFork(model);
 
@@ -363,7 +367,7 @@
 
 	protected Repository getRepository() {
 		if (r == null) {
-			Repository r = GitBlit.self().getRepository(repositoryName);
+			Repository r = app().repositories().getRepository(repositoryName);
 			if (r == null) {
 				error(getString("gb.canNotLoadRepository") + " " + repositoryName, true);
 				return null;
@@ -375,10 +379,10 @@
 
 	protected RepositoryModel getRepositoryModel() {
 		if (m == null) {
-			RepositoryModel model = GitBlit.self().getRepositoryModel(
+			RepositoryModel model = app().repositories().getRepositoryModel(
 					GitBlitWebSession.get().getUser(), repositoryName);
 			if (model == null) {
-				if (GitBlit.self().hasRepository(repositoryName, true)) {
+				if (app().repositories().hasRepository(repositoryName, true)) {
 					// has repository, but unauthorized
 					authenticationError(getString("gb.unauthorizedAccessForRepository") + " " + repositoryName);
 				} else {
@@ -450,7 +454,7 @@
 			return model;
 		} else {
 			// extract the repository name from the clone url
-			List<String> patterns = GitBlit.getStrings(Keys.git.submoduleUrlPatterns);
+			List<String> patterns = app().settings().getStrings(Keys.git.submoduleUrlPatterns);
 			String submoduleName = StringUtils.extractRepositoryPath(model.url, patterns.toArray(new String[0]));
 
 			// determine the current path for constructing paths relative
@@ -489,7 +493,7 @@
 			// create a unique, ordered set of candidate paths
 			Set<String> paths = new LinkedHashSet<String>(candidates);
 			for (String candidate : paths) {
-				if (GitBlit.self().hasRepository(candidate)) {
+				if (app().repositories().hasRepository(candidate)) {
 					model.hasSubmodule = true;
 					model.gitblitPath = candidate;
 					return model;
@@ -503,7 +507,7 @@
 	}
 
 	protected String getShortObjectId(String objectId) {
-		return objectId.substring(0, GitBlit.getInteger(Keys.web.shortCommitIdLength, 6));
+		return objectId.substring(0, app().settings().getInteger(Keys.web.shortCommitIdLength, 6));
 	}
 
 	protected void addRefs(Repository r, RevCommit c) {
@@ -512,7 +516,7 @@
 
 	protected void addFullText(String wicketId, String text) {
 		RepositoryModel model = getRepositoryModel();
-		String content = GitBlit.self().processCommitMessage(model, text);
+		String content = messageProcessor().processCommitMessage(model, text);
 		String html;
 		switch (model.commitMessageRenderer) {
 		case MARKDOWN:
@@ -533,7 +537,7 @@
 		String address = identity == null ? "" : identity.getEmailAddress();
 		name = StringUtils.removeNewlines(name);
 		address = StringUtils.removeNewlines(address);
-		boolean showEmail = GitBlit.getBoolean(Keys.web.showEmailAddresses, false);
+		boolean showEmail = app().settings().getBoolean(Keys.web.showEmailAddresses, false);
 		if (!showEmail || StringUtils.isEmpty(name) || StringUtils.isEmpty(address)) {
 			String value = name;
 			if (StringUtils.isEmpty(value)) {
@@ -664,7 +668,7 @@
 			DropDownChoice<Constants.SearchType> searchType = new DropDownChoice<Constants.SearchType>(
 					"searchType", Arrays.asList(Constants.SearchType.values()));
 			searchType.setModel(searchTypeModel);
-			add(searchType.setVisible(GitBlit.getBoolean(Keys.web.showSearchTypeSelection, false)));
+			add(searchType.setVisible(app().settings().getBoolean(Keys.web.showSearchTypeSelection, false)));
 			TextField<String> searchBox = new TextField<String>("searchBox", searchBoxModel);
 			add(searchBox);
 		}
@@ -695,8 +699,8 @@
 				}
 			}
 			Class<? extends BasePage> searchPageClass = GitSearchPage.class;
-			RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
-			if (GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true)
+			RepositoryModel model = app().repositories().getRepositoryModel(repositoryName);
+			if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)
 					&& !ArrayUtils.isEmpty(model.indexedBranches)) {
 				// this repository is Lucene-indexed
 				searchPageClass = LuceneSearchPage.class;
diff --git a/src/main/java/com/gitblit/wicket/pages/ReviewProposalPage.java b/src/main/java/com/gitblit/wicket/pages/ReviewProposalPage.java
index ebe1530..8aec9e6 100644
--- a/src/main/java/com/gitblit/wicket/pages/ReviewProposalPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ReviewProposalPage.java
@@ -23,7 +23,6 @@
 import org.apache.wicket.markup.html.basic.Label;
 
 import com.gitblit.Constants.FederationToken;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.FederationProposal;
 import com.gitblit.models.RepositoryModel;
@@ -37,14 +36,12 @@
 
 	private final String PROPS_PATTERN = "{0} = {1}\n";
 
-	private final String WEBXML_PATTERN = "\n<context-param>\n\t<param-name>{0}</param-name>\n\t<param-value>{1}</param-value>\n</context-param>\n";
-
 	public ReviewProposalPage(PageParameters params) {
 		super(params);
 
 		final String token = WicketUtils.getToken(params);
 
-		FederationProposal proposal = GitBlit.self().getPendingFederationProposal(token);
+		FederationProposal proposal = app().federation().getPendingFederationProposal(token);
 		if (proposal == null) {
 			error(getString("gb.couldNotFindFederationProposal"), true);
 		}
@@ -58,14 +55,7 @@
 		add(new Label("token", proposal.token));
 		add(new Label("tokenType", proposal.tokenType.name()));
 
-		String p;
-		if (GitBlit.isGO()) {
-			// gitblit.properties definition
-			p = PROPS_PATTERN;
-		} else {
-			// web.xml definition
-			p = WEBXML_PATTERN;
-		}
+		String p = PROPS_PATTERN;
 
 		// build proposed definition
 		StringBuilder sb = new StringBuilder();
@@ -77,7 +67,7 @@
 			sb.append(asParam(p, proposal.name, "mergeAccounts", "false"));
 		}
 		sb.append(asParam(p, proposal.name, "frequency",
-				GitBlit.getString(Keys.federation.defaultFrequency, "60 mins")));
+				app().settings().getString(Keys.federation.defaultFrequency, "60 mins")));
 		sb.append(asParam(p, proposal.name, "folder", proposal.name));
 		sb.append(asParam(p, proposal.name, "bare", "true"));
 		sb.append(asParam(p, proposal.name, "mirror", "true"));
diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java
index a59e202..98a8cb3 100644
--- a/src/main/java/com/gitblit/wicket/pages/RootPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java
@@ -46,7 +46,6 @@
 import org.apache.wicket.protocol.http.WebResponse;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.TeamModel;
@@ -97,22 +96,22 @@
 				StringBuilder buffer = new StringBuilder();
 				buffer.append("<style type=\"text/css\">\n");
 				buffer.append(".navbar-inner {\n");
-				final String headerBackground = GitBlit.getString(Keys.web.headerBackgroundColor, null);
+				final String headerBackground = app().settings().getString(Keys.web.headerBackgroundColor, null);
 				if (!StringUtils.isEmpty(headerBackground)) {
 					buffer.append(MessageFormat.format("background-color: {0};\n", headerBackground));
 				}
-				final String headerBorder = GitBlit.getString(Keys.web.headerBorderColor, null);
+				final String headerBorder = app().settings().getString(Keys.web.headerBorderColor, null);
 				if (!StringUtils.isEmpty(headerBorder)) {
 					buffer.append(MessageFormat.format("border-bottom: 1px solid {0} !important;\n", headerBorder));
 				}
 				buffer.append("}\n");
-				final String headerBorderFocus = GitBlit.getString(Keys.web.headerBorderFocusColor, null);
+				final String headerBorderFocus = app().settings().getString(Keys.web.headerBorderFocusColor, null);
 				if (!StringUtils.isEmpty(headerBorderFocus)) {
 					buffer.append(".navbar ul li:focus, .navbar .active {\n");
 					buffer.append(MessageFormat.format("border-bottom: 4px solid {0};\n", headerBorderFocus));
 					buffer.append("}\n");
 				}
-				final String headerForeground = GitBlit.getString(Keys.web.headerForegroundColor, null);
+				final String headerForeground = app().settings().getString(Keys.web.headerForegroundColor, null);
 				if (!StringUtils.isEmpty(headerForeground)) {
 					buffer.append(".navbar ul.nav li a {\n");
 					buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
@@ -121,7 +120,7 @@
 					buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
 					buffer.append("}\n");
 				}
-				final String headerHover = GitBlit.getString(Keys.web.headerHoverColor, null);
+				final String headerHover = app().settings().getString(Keys.web.headerHoverColor, null);
 				if (!StringUtils.isEmpty(headerHover)) {
 					buffer.append(".navbar ul.nav li a:hover {\n");
 					buffer.append(MessageFormat.format("color: {0} !important;\n", headerHover));
@@ -132,9 +131,9 @@
 				}
 			}));
 
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, false);
-		boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
-		boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false);
+		boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true);
+		boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true);
 
 		if (authenticateAdmin) {
 			showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
@@ -163,8 +162,8 @@
 			add(new Label("userPanel").setVisible(false));
 		}
 
-		boolean showRegistrations = GitBlit.canFederate()
-				&& GitBlit.getBoolean(Keys.web.showFederationRegistrations, false);
+		boolean showRegistrations = app().federation().canFederate()
+				&& app().settings().getBoolean(Keys.web.showFederationRegistrations, false);
 
 		// navigation links
 		List<PageRegistration> pages = new ArrayList<PageRegistration>();
@@ -174,7 +173,7 @@
 			pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class,
 					getRootPageParameters()));
 			pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters()));
-			if (GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true)) {
+			if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) {
 				pages.add(new PageRegistration("gb.search", LuceneSearchPage.class));
 			}
 			if (showAdmin) {
@@ -197,7 +196,7 @@
 		if (!StringUtils.isEmpty(cachedMessage)) {
 			error(cachedMessage);
 		} else if (showAdmin) {
-			int pendingProposals = GitBlit.self().getPendingFederationProposals().size();
+			int pendingProposals = app().federation().getPendingFederationProposals().size();
 			if (pendingProposals == 1) {
 				info(getString("gb.OneProposalToReview"));
 			} else if (pendingProposals > 1) {
@@ -229,7 +228,7 @@
 
 				// remove days back parameter if it is the default value
 				if (params.containsKey("db")
-						&& params.getInt("db") == GitBlit.getInteger(Keys.web.activityDuration, 7)) {
+						&& params.getInt("db") == app().settings().getInteger(Keys.web.activityDuration, 7)) {
 					params.remove("db");
 				}
 				return params;
@@ -251,9 +250,9 @@
 			session.setUser(user);
 
 			// Set Cookie
-			if (GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {
+			if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) {
 				WebResponse response = (WebResponse) getRequestCycle().getResponse();
-				GitBlit.self().setCookie(response, user);
+				app().session().setCookie(response, user);
 			}
 
 			if (!session.continueRequest()) {
@@ -274,7 +273,7 @@
 	protected List<RepositoryModel> getRepositoryModels() {
 		if (repositoryModels.isEmpty()) {
 			final UserModel user = GitBlitWebSession.get().getUser();
-			List<RepositoryModel> repositories = GitBlit.self().getRepositoryModels(user);
+			List<RepositoryModel> repositories = app().repositories().getRepositoryModels(user);
 			repositoryModels.addAll(repositories);
 			Collections.sort(repositoryModels);
 		}
@@ -326,7 +325,7 @@
 		}
 
 		// custom filters
-		String customFilters = GitBlit.getString(Keys.web.customFilters, null);
+		String customFilters = app().settings().getString(Keys.web.customFilters, null);
 		if (!StringUtils.isEmpty(customFilters)) {
 			boolean addedExpression = false;
 			List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!");
@@ -346,8 +345,8 @@
 
 	protected List<DropDownMenuItem> getTimeFilterItems(PageParameters params) {
 		// days back choices - additive parameters
-		int daysBack = GitBlit.getInteger(Keys.web.activityDuration, 7);
-		int maxDaysBack = GitBlit.getInteger(Keys.web.activityDurationMaximum, 30);
+		int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
+		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
 		if (daysBack < 1) {
 			daysBack = 7;
 		}
@@ -366,7 +365,7 @@
 		}
 
 		List<DropDownMenuItem> items = new ArrayList<DropDownMenuItem>();
-		Set<Integer> choicesSet = new TreeSet<Integer>(GitBlit.getIntegers(Keys.web.activityDurationChoices));
+		Set<Integer> choicesSet = new TreeSet<Integer>(app().settings().getIntegers(Keys.web.activityDurationChoices));
 		if (choicesSet.isEmpty()) {
 			 choicesSet.addAll(Arrays.asList(1, 3, 7, 14, 21, 28));
 		}
@@ -403,7 +402,7 @@
 		String regex = WicketUtils.getRegEx(params);
 		String team = WicketUtils.getTeam(params);
 		int daysBack = params.getInt("db", 0);
-		int maxDaysBack = GitBlit.getInteger(Keys.web.activityDurationMaximum, 30);
+		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
 
 		List<RepositoryModel> availableModels = getRepositoryModels();
 		Set<RepositoryModel> models = new HashSet<RepositoryModel>();
@@ -422,7 +421,7 @@
 		if (!StringUtils.isEmpty(projectName)) {
 			// try named project
 			hasParameter = true;
-			if (projectName.equalsIgnoreCase(GitBlit.getString(Keys.web.repositoryRootGroupName, "main"))) {
+			if (projectName.equalsIgnoreCase(app().settings().getString(Keys.web.repositoryRootGroupName, "main"))) {
 				// root project/group
 				for (RepositoryModel model : availableModels) {
 					if (model.name.indexOf('/') == -1) {
@@ -472,7 +471,7 @@
 			// need TeamModels first
 			List<TeamModel> teamModels = new ArrayList<TeamModel>();
 			for (String name : teams) {
-				TeamModel teamModel = GitBlit.self().getTeamModel(name);
+				TeamModel teamModel = app().users().getTeamModel(name);
 				if (teamModel != null) {
 					teamModels.add(teamModel);
 				}
@@ -537,7 +536,7 @@
 					String username = RootPage.this.username.getObject();
 					char[] password = RootPage.this.password.getObject().toCharArray();
 
-					UserModel user = GitBlit.self().authenticate(username, password);
+					UserModel user = app().session().authenticate(username, password);
 					if (user == null) {
 						error(getString("gb.invalidUsernameOrPassword"));
 					} else if (user.username.equals(Constants.FEDERATION_USER)) {
@@ -563,7 +562,7 @@
 	/**
 	 * Menu for the authenticated user.
 	 */
-	static class UserMenu extends Fragment {
+	class UserMenu extends Fragment {
 
 		private static final long serialVersionUID = 1L;
 
@@ -573,10 +572,10 @@
 
 			GitBlitWebSession session = GitBlitWebSession.get();
 			UserModel user = session.getUser();
-			boolean editCredentials = GitBlit.self().supportsCredentialChanges(user);
+			boolean editCredentials = app().users().supportsCredentialChanges(user);
 			boolean standardLogin = session.authenticationType.isStandard();
 
-			if (GitBlit.getBoolean(Keys.web.allowGravatar, true)) {
+			if (app().settings().getBoolean(Keys.web.allowGravatar, true)) {
 				add(new GravatarImage("username", user.getDisplayName(),
 						user.emailAddress, "navbarGravatar", 20, false, false));
 			} else {
diff --git a/src/main/java/com/gitblit/wicket/pages/RootSubPage.java b/src/main/java/com/gitblit/wicket/pages/RootSubPage.java
index e81717a..62d07a7 100644
--- a/src/main/java/com/gitblit/wicket/pages/RootSubPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RootSubPage.java
@@ -24,7 +24,6 @@
 
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.AuthorizationControl;
-import com.gitblit.GitBlit;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.ModelUtils;
@@ -86,8 +85,8 @@
 			}
 		}
 
-		for (String repo : GitBlit.self().getRepositoryList()) {
-			RepositoryModel repositoryModel = GitBlit.self().getRepositoryModel(repo);
+		for (String repo : app().repositories().getRepositoryList()) {
+			RepositoryModel repositoryModel = app().repositories().getRepositoryModel(repo);
 			if (repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE)
 					&& repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED)) {
 				if (user != null &&
diff --git a/src/main/java/com/gitblit/wicket/pages/SendProposalPage.java b/src/main/java/com/gitblit/wicket/pages/SendProposalPage.java
index b1a8c5b..9ccf1aa 100644
--- a/src/main/java/com/gitblit/wicket/pages/SendProposalPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/SendProposalPage.java
@@ -27,7 +27,6 @@
 import org.apache.wicket.model.CompoundPropertyModel;
 
 import com.gitblit.Constants.FederationProposalResult;
-import com.gitblit.GitBlit;
 import com.gitblit.models.FederationProposal;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.utils.FederationUtils;
@@ -57,7 +56,7 @@
 		destinationUrl = "https://";
 
 		// temporary proposal
-		FederationProposal proposal = GitBlit.self().createFederationProposal(myUrl, token);
+		FederationProposal proposal = app().federation().createFederationProposal(myUrl, token);
 		if (proposal == null) {
 			error(getString("gb.couldNotCreateFederationProposal"), true);
 		}
@@ -81,7 +80,7 @@
 				}
 
 				// build new proposal
-				FederationProposal proposal = GitBlit.self().createFederationProposal(myUrl, token);
+				FederationProposal proposal = app().federation().createFederationProposal(myUrl, token);
 				proposal.url = myUrl;
 				proposal.message = message;
 				try {
diff --git a/src/main/java/com/gitblit/wicket/pages/SessionPage.java b/src/main/java/com/gitblit/wicket/pages/SessionPage.java
index 5a255ec..886dd6e 100644
--- a/src/main/java/com/gitblit/wicket/pages/SessionPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/SessionPage.java
@@ -22,8 +22,9 @@
 import org.apache.wicket.protocol.http.WebRequest;
 import org.apache.wicket.protocol.http.WebResponse;
 
-import com.gitblit.GitBlit;
+import com.gitblit.Keys;
 import com.gitblit.models.UserModel;
+import com.gitblit.wicket.GitBlitWebApp;
 import com.gitblit.wicket.GitBlitWebSession;
 
 public abstract class SessionPage extends WebPage {
@@ -38,12 +39,20 @@
 		login();
 	}
 
+	protected String [] getEncodings() {
+		return app().settings().getStrings(Keys.web.blobEncodings).toArray(new String[0]);
+	}
+
+	protected GitBlitWebApp app() {
+		return GitBlitWebApp.get();
+	}
+
 	private void login() {
 		GitBlitWebSession session = GitBlitWebSession.get();
 		if (session.isLoggedIn() && !session.isSessionInvalidated()) {
 			// already have a session, refresh usermodel to pick up
 			// any changes to permissions or roles (issue-186)
-			UserModel user = GitBlit.self().getUserModel(session.getUser().username);
+			UserModel user = app().users().getUserModel(session.getUser().username);
 			session.setUser(user);
 			return;
 		}
@@ -51,7 +60,7 @@
 		// try to authenticate by servlet request
 		HttpServletRequest httpRequest = ((WebRequest) getRequestCycle().getRequest())
 				.getHttpServletRequest();
-		UserModel user = GitBlit.self().authenticate(httpRequest);
+		UserModel user = app().session().authenticate(httpRequest);
 
 		// Login the user
 		if (user != null) {
@@ -61,7 +70,7 @@
 
 			// Set Cookie
 			WebResponse response = (WebResponse) getRequestCycle().getResponse();
-			GitBlit.self().setCookie(response, user);
+			app().session().setCookie(response, user);
 
 			session.continueRequest();
 		}
diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
index 5604be4..9129302 100644
--- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java
@@ -40,7 +40,6 @@
 import org.wicketstuff.googlecharts.MarkerType;
 import org.wicketstuff.googlecharts.ShapeMarker;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.Metric;
 import com.gitblit.models.RepositoryModel;
@@ -67,11 +66,11 @@
 	public SummaryPage(PageParameters params) {
 		super(params);
 
-		int numberCommits = GitBlit.getInteger(Keys.web.summaryCommitCount, 20);
+		int numberCommits = app().settings().getInteger(Keys.web.summaryCommitCount, 20);
 		if (numberCommits <= 0) {
 			numberCommits = 20;
 		}
-		int numberRefs = GitBlit.getInteger(Keys.web.summaryRefsCount, 5);
+		int numberRefs = app().settings().getInteger(Keys.web.summaryRefsCount, 5);
 
 		Repository r = getRepository();
 		final RepositoryModel model = getRepositoryModel();
@@ -82,8 +81,8 @@
 
 		List<Metric> metrics = null;
 		Metric metricsTotal = null;
-		if (!model.skipSummaryMetrics && GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
-			metrics = GitBlit.self().getRepositoryDefaultMetrics(model, r);
+		if (!model.skipSummaryMetrics && app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
+			metrics = app().repositories().getRepositoryDefaultMetrics(model, r);
 			metricsTotal = metrics.remove(0);
 		}
 
@@ -101,7 +100,7 @@
 			@Override
 			public void populateItem(final Item<String> item) {
 				String ownername = item.getModelObject();
-				UserModel ownerModel = GitBlit.self().getUserModel(ownername);
+				UserModel ownerModel = app().users().getUserModel(ownername);
 				if (ownerModel != null) {
 					item.add(new LinkPanel("owner", null, ownerModel.getDisplayName(), UserPage.class,
 							WicketUtils.newUsernameParameter(ownerModel.username)).setRenderBodyOnly(true));
@@ -138,10 +137,10 @@
 		add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());
 		add(new BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty());
 
-		if (GitBlit.getBoolean(Keys.web.summaryShowReadme, false)) {
+		if (app().settings().getBoolean(Keys.web.summaryShowReadme, false)) {
 			// show a readme on the summary page
 			RevCommit head = JGitUtils.getCommit(r, null);
-			MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());
+			MarkupProcessor processor = new MarkupProcessor(app().settings());
 			MarkupDocument markupDoc = processor.getReadme(r, repositoryName, getBestCommitId(head));
 			if (markupDoc == null || markupDoc.markup == null) {
 				add(new Label("readme").setVisible(false));
@@ -169,7 +168,7 @@
 
 	private void insertActivityGraph(List<Metric> metrics) {
 		if ((metrics != null) && (metrics.size() > 0)
-				&& GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
+				&& app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
 			IChartData data = WicketUtils.getChartData(metrics);
 
 			ChartProvider provider = new ChartProvider(new Dimension(290, 100), ChartType.LINE,
diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java
index 4b62e79..1e5ddcf 100644
--- a/src/main/java/com/gitblit/wicket/pages/UserPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java
@@ -28,7 +28,6 @@
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 import org.eclipse.jgit.lib.PersonIdent;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
 import com.gitblit.models.RepositoryModel;
@@ -67,7 +66,7 @@
 	private void setup(PageParameters params) {
 		setupPage("", "");
 		// check to see if we should display a login message
-		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
 		if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
 			authenticationError("Please login");
 			return;
@@ -78,7 +77,7 @@
 			throw new GitblitRedirectException(GitBlitWebApp.get().getHomePage());
 		}
 
-		UserModel user = GitBlit.self().getUserModel(userName);
+		UserModel user = app().users().getUserModel(userName);
 		if (user == null) {
 			// construct a temporary user model
 			user = new UserModel(userName);
@@ -86,7 +85,7 @@
 
 		String projectName = user.getPersonalPath();
 
-		ProjectModel project = GitBlit.self().getProjectModel(projectName);
+		ProjectModel project = app().projects().getProjectModel(projectName);
 		if (project == null) {
 			project = new ProjectModel(projectName);
 		}
@@ -95,7 +94,7 @@
 		add(new Label("userUsername", user.username));
 		LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#");
 		email.setRenderBodyOnly(true);
-		add(email.setVisible(GitBlit.getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress)));
+		add(email.setVisible(app().settings().getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress)));
 
 		PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
 		add(new GravatarImage("gravatar", person, 210));
diff --git a/src/main/java/com/gitblit/wicket/panels/ActivityPanel.java b/src/main/java/com/gitblit/wicket/panels/ActivityPanel.java
index e5c8e46..bbb7608 100644
--- a/src/main/java/com/gitblit/wicket/panels/ActivityPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/ActivityPanel.java
@@ -25,7 +25,6 @@
 import org.eclipse.jgit.lib.Repository;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.Activity;
 import com.gitblit.models.RepositoryCommit;
@@ -53,7 +52,7 @@
 
 		Collections.sort(recentActivity);
 
-		final int shortHashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+		final int shortHashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
 		DataView<Activity> activityView = new DataView<Activity>("activity",
 				new ListDataProvider<Activity>(recentActivity)) {
 			private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/gitblit/wicket/panels/BasePanel.java b/src/main/java/com/gitblit/wicket/panels/BasePanel.java
index b60579b..dda5797 100644
--- a/src/main/java/com/gitblit/wicket/panels/BasePanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/BasePanel.java
@@ -24,9 +24,9 @@
 import org.apache.wicket.model.Model;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.utils.TimeUtils;
+import com.gitblit.wicket.GitBlitWebApp;
 import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.WicketUtils;
 
@@ -40,9 +40,13 @@
 		super(wicketId);
 	}
 
+	protected GitBlitWebApp app() {
+		return GitBlitWebApp.get();
+	}
+
 	protected TimeZone getTimeZone() {
-		return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
-				.getTimezone() : GitBlit.getTimezone();
+		return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
+				.getTimezone() : app().getTimezone();
 	}
 
 	protected TimeUtils getTimeUtils() {
diff --git a/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java b/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java
index 4981c8b..7fec0ea 100644
--- a/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/BranchesPanel.java
@@ -37,7 +37,6 @@
 import org.eclipse.jgit.lib.Repository;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.SyndicationServlet;
 import com.gitblit.models.RefModel;
 import com.gitblit.models.RepositoryModel;
@@ -190,9 +189,9 @@
 
 			@Override
 			public void onClick() {
-				Repository r = GitBlit.self().getRepository(repositoryModel.name);
+				Repository r = app().repositories().getRepository(repositoryModel.name);
 				if (r == null) {
-					if (GitBlit.self().isCollectingGarbage(repositoryModel.name)) {
+					if (app().repositories().isCollectingGarbage(repositoryModel.name)) {
 						error(MessageFormat.format(getString("gb.busyCollectingGarbage"), repositoryModel.name));
 					} else {
 						error(MessageFormat.format("Failed to find repository {0}", repositoryModel.name));
diff --git a/src/main/java/com/gitblit/wicket/panels/CompressedDownloadsPanel.java b/src/main/java/com/gitblit/wicket/panels/CompressedDownloadsPanel.java
index d8a4a10..72a032e 100644
--- a/src/main/java/com/gitblit/wicket/panels/CompressedDownloadsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/CompressedDownloadsPanel.java
@@ -18,24 +18,22 @@
 import java.util.List;
 
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
 import com.gitblit.DownloadZipServlet;
 import com.gitblit.DownloadZipServlet.Format;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 
-public class CompressedDownloadsPanel extends Panel {
+public class CompressedDownloadsPanel extends BasePanel {
 
 	private static final long serialVersionUID = 1L;
 
 	public CompressedDownloadsPanel(String id, final String baseUrl, final String repositoryName, final String objectId, final String path) {
 		super(id);
 
-		List<String> types = GitBlit.getStrings(Keys.web.compressedDownloads);
+		List<String> types = app().settings().getStrings(Keys.web.compressedDownloads);
 		if (types.isEmpty()) {
 			types.add(Format.zip.name());
 			types.add(Format.gz.name());
@@ -72,6 +70,6 @@
 		};
 		add(refsView);
 
-		setVisible(GitBlit.getBoolean(Keys.web.allowZipDownloads, true));
+		setVisible(app().settings().getBoolean(Keys.web.allowZipDownloads, true));
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java
index 10d5d1b..318e74c 100644
--- a/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java
@@ -31,7 +31,6 @@
 import org.eclipse.jgit.lib.PersonIdent;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.DailyLogEntry;
 import com.gitblit.models.RepositoryCommit;
@@ -56,9 +55,9 @@
 		super(wicketId);
 		hasChanges = digests.size() > 0;
 
-		final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+		final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
 
-		String dateFormat = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
+		String dateFormat = app().settings().getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
 		final TimeZone timezone = getTimeZone();
 		final DateFormat df = new SimpleDateFormat(dateFormat);
 		df.setTimeZone(timezone);
@@ -203,7 +202,7 @@
 					logItem.add(new LinkPanel("compareLink", null, compareLinkText, ComparePage.class, WicketUtils.newRangeParameter(change.repository, startRangeId, endRangeId)));
 				}
 
-				final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
+				final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);
 
 				ListDataProvider<RepositoryCommit> cdp = new ListDataProvider<RepositoryCommit>(commits);
 				DataView<RepositoryCommit> commitsView = new DataView<RepositoryCommit>("commit", cdp) {
diff --git a/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java b/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java
index c15a0a5..b02e848 100644
--- a/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/FederationProposalsPanel.java
@@ -25,7 +25,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.FederationProposal;
 import com.gitblit.wicket.WicketUtils;
 import com.gitblit.wicket.pages.ReviewProposalPage;
@@ -39,7 +38,7 @@
 	public FederationProposalsPanel(String wicketId) {
 		super(wicketId);
 
-		final List<FederationProposal> list = GitBlit.self().getPendingFederationProposals();
+		final List<FederationProposal> list = app().federation().getPendingFederationProposals();
 		hasProposals = list.size() > 0;
 		DataView<FederationProposal> dataView = new DataView<FederationProposal>("row",
 				new ListDataProvider<FederationProposal>(list)) {
@@ -68,7 +67,7 @@
 
 					@Override
 					public void onClick() {
-						if (GitBlit.self().deletePendingFederationProposal(entry)) {
+						if (app().federation().deletePendingFederationProposal(entry)) {
 							list.remove(entry);
 							info(MessageFormat.format("Proposal ''{0}'' deleted.", entry.name));
 						} else {
diff --git a/src/main/java/com/gitblit/wicket/panels/FederationRegistrationsPanel.java b/src/main/java/com/gitblit/wicket/panels/FederationRegistrationsPanel.java
index 344af49..264d40d 100644
--- a/src/main/java/com/gitblit/wicket/panels/FederationRegistrationsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/FederationRegistrationsPanel.java
@@ -25,7 +25,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.FederationModel;
 import com.gitblit.wicket.WicketUtils;
 import com.gitblit.wicket.pages.FederationRegistrationPage;
@@ -39,9 +38,9 @@
 	public FederationRegistrationsPanel(String wicketId) {
 		super(wicketId);
 
-		final List<FederationModel> list = new ArrayList<FederationModel>(GitBlit.self()
+		final List<FederationModel> list = new ArrayList<FederationModel>(app().federation()
 				.getFederationRegistrations());
-		list.addAll(GitBlit.self().getFederationResultRegistrations());
+		list.addAll(app().federation().getFederationResultRegistrations());
 		Collections.sort(list);
 		hasRegistrations = list.size() > 0;
 		DataView<FederationModel> dataView = new DataView<FederationModel>("row",
diff --git a/src/main/java/com/gitblit/wicket/panels/FederationTokensPanel.java b/src/main/java/com/gitblit/wicket/panels/FederationTokensPanel.java
index afe553c..0bad71d 100644
--- a/src/main/java/com/gitblit/wicket/panels/FederationTokensPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/FederationTokensPanel.java
@@ -28,7 +28,6 @@
 
 import com.gitblit.Constants.FederationRequest;
 import com.gitblit.Constants.FederationToken;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.utils.FederationUtils;
 import com.gitblit.wicket.WicketUtils;
@@ -42,22 +41,22 @@
 		super(wicketId);
 
 		final String baseUrl = WicketUtils.getGitblitURL(getRequest());
-		add(new ExternalLink("federatedUsers", FederationUtils.asLink(baseUrl, GitBlit.self()
+		add(new ExternalLink("federatedUsers", FederationUtils.asLink(baseUrl, app().federation()
 				.getFederationToken(FederationToken.USERS_AND_REPOSITORIES),
 				FederationRequest.PULL_USERS)));
 
-		add(new ExternalLink("federatedSettings", FederationUtils.asLink(baseUrl, GitBlit
-				.self().getFederationToken(FederationToken.ALL), FederationRequest.PULL_SETTINGS)));
+		add(new ExternalLink("federatedSettings", FederationUtils.asLink(baseUrl, app().federation()
+				.getFederationToken(FederationToken.ALL), FederationRequest.PULL_SETTINGS)));
 
 		final List<String[]> data = new ArrayList<String[]>();
 		for (FederationToken token : FederationToken.values()) {
-			data.add(new String[] { token.name(), GitBlit.self().getFederationToken(token), null });
+			data.add(new String[] { token.name(), app().federation().getFederationToken(token), null });
 		}
-		List<String> sets = GitBlit.getStrings(Keys.federation.sets);
+		List<String> sets = app().settings().getStrings(Keys.federation.sets);
 		Collections.sort(sets);
 		for (String set : sets) {
 			data.add(new String[] { FederationToken.REPOSITORIES.name(),
-					GitBlit.self().getFederationToken(set), set });
+					app().federation().getFederationToken(set), set });
 		}
 
 		DataView<String[]> dataView = new DataView<String[]>("row", new ListDataProvider<String[]>(
diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableProjectList.java b/src/main/java/com/gitblit/wicket/panels/FilterableProjectList.java
index 4c57926..3a269a9 100644
--- a/src/main/java/com/gitblit/wicket/panels/FilterableProjectList.java
+++ b/src/main/java/com/gitblit/wicket/panels/FilterableProjectList.java
@@ -29,7 +29,6 @@
 import org.apache.wicket.behavior.HeaderContributor;
 import org.apache.wicket.markup.html.basic.Label;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
 import com.gitblit.utils.StringUtils;
@@ -93,7 +92,7 @@
 			panel.add(icon);
 		}
 
-		String format = GitBlit.getString(Keys.web.datestampShortFormat, "MM/dd/yy");
+		String format = app().settings().getString(Keys.web.datestampShortFormat, "MM/dd/yy");
 		final DateFormat df = new SimpleDateFormat(format);
 		df.setTimeZone(getTimeZone());
 		Collections.sort(projects, new Comparator<ProjectModel>() {
diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java
index d68155e..45b0bab 100644
--- a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java
+++ b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java
@@ -27,7 +27,6 @@
 import org.apache.wicket.behavior.HeaderContributor;
 import org.apache.wicket.markup.html.basic.Label;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.utils.StringUtils;
@@ -104,7 +103,7 @@
 			panel.add(new Label(ngList + "Button").setVisible(false));
 		}
 
-		String format = GitBlit.getString(Keys.web.datestampShortFormat, "MM/dd/yy");
+		String format = app().settings().getString(Keys.web.datestampShortFormat, "MM/dd/yy");
 		final DateFormat df = new SimpleDateFormat(format);
 		df.setTimeZone(getTimeZone());
 
@@ -123,7 +122,7 @@
 			item.p = path;
 			item.r = repo.name;
 			item.i = repo.description;
-			item.s = GitBlit.self().getStarCount(repo);
+			item.s = app().repositories().getStarCount(repo);
 			item.t = getTimeUtils().timeAgo(repo.lastChange);
 			item.d = df.format(repo.lastChange);
 			item.c = StringUtils.getColor(StringUtils.stripDotGit(repo.name));
diff --git a/src/main/java/com/gitblit/wicket/panels/GravatarImage.java b/src/main/java/com/gitblit/wicket/panels/GravatarImage.java
index 741328c..34af2bf 100644
--- a/src/main/java/com/gitblit/wicket/panels/GravatarImage.java
+++ b/src/main/java/com/gitblit/wicket/panels/GravatarImage.java
@@ -20,10 +20,8 @@
 import org.apache.wicket.behavior.SimpleAttributeModifier;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.link.Link;
-import org.apache.wicket.markup.html.panel.Panel;
 import org.eclipse.jgit.lib.PersonIdent;
 
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.utils.ActivityUtils;
 import com.gitblit.utils.StringUtils;
@@ -37,7 +35,7 @@
  * @author James Moger
  *
  */
-public class GravatarImage extends Panel {
+public class GravatarImage extends BasePanel {
 
 	private static final long serialVersionUID = 1L;
 
@@ -79,6 +77,6 @@
 			WicketUtils.setHtmlTooltip(link, username);
 		}
 		add(link.setEnabled(linked));
-		setVisible(GitBlit.getBoolean(Keys.web.allowGravatar, true));
+		setVisible(app().settings().getBoolean(Keys.web.allowGravatar, true));
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/HistoryPanel.java b/src/main/java/com/gitblit/wicket/panels/HistoryPanel.java
index 10a8b57..ecdad52 100644
--- a/src/main/java/com/gitblit/wicket/panels/HistoryPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/HistoryPanel.java
@@ -39,7 +39,6 @@
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.PathModel;
 import com.gitblit.models.PathModel.PathChangeModel;
@@ -66,7 +65,7 @@
 			final String path, Repository r, int limit, int pageOffset, boolean showRemoteRefs) {
 		super(wicketId);
 		boolean pageResults = limit <= 0;
-		int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
+		int itemsPerPage = app().settings().getInteger(Keys.web.itemsPerPage, 50);
 		if (itemsPerPage <= 1) {
 			itemsPerPage = 50;
 		}
@@ -143,7 +142,7 @@
 		// breadcrumbs
 		add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, path, objectId));
 
-		final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+		final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
 		ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
 		DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
 			private static final long serialVersionUID = 1L;
@@ -205,7 +204,7 @@
 					item.add(links);
 				} else if (isSubmodule) {
 					// submodule
-					Repository repository = GitBlit.self().getRepository(repositoryName);
+					Repository repository = app().repositories().getRepository(repositoryName);
 					String submoduleId = JGitUtils.getSubmoduleCommitId(repository, path, entry);
 					repository.close();
 					if (StringUtils.isEmpty(submoduleId)) {
@@ -288,7 +287,7 @@
 			return model;
 		} else {
 			// extract the repository name from the clone url
-			List<String> patterns = GitBlit.getStrings(Keys.git.submoduleUrlPatterns);
+			List<String> patterns = app().settings().getStrings(Keys.git.submoduleUrlPatterns);
 			String submoduleName = StringUtils.extractRepositoryPath(model.url, patterns.toArray(new String[0]));
 
 			// determine the current path for constructing paths relative
@@ -327,7 +326,7 @@
 			// create a unique, ordered set of candidate paths
 			Set<String> paths = new LinkedHashSet<String>(candidates);
 			for (String candidate : paths) {
-				if (GitBlit.self().hasRepository(candidate)) {
+				if (app().repositories().hasRepository(candidate)) {
 					model.hasSubmodule = true;
 					model.gitblitPath = candidate;
 					return model;
diff --git a/src/main/java/com/gitblit/wicket/panels/LogPanel.java b/src/main/java/com/gitblit/wicket/panels/LogPanel.java
index eba0dd3..7c91d22 100644
--- a/src/main/java/com/gitblit/wicket/panels/LogPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/LogPanel.java
@@ -34,7 +34,6 @@
 
 import com.gitblit.BranchGraphServlet;
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RefModel;
 import com.gitblit.utils.JGitUtils;
@@ -57,7 +56,7 @@
 			Repository r, int limit, int pageOffset, boolean showRemoteRefs) {
 		super(wicketId);
 		boolean pageResults = limit <= 0;
-		int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
+		int itemsPerPage = app().settings().getInteger(Keys.web.itemsPerPage, 50);
 		if (itemsPerPage <= 1) {
 			itemsPerPage = 50;
 		}
@@ -77,7 +76,7 @@
 		hasMore = commits.size() >= itemsPerPage;
 
 		final String baseUrl = WicketUtils.getGitblitURL(getRequest());
-		final boolean showGraph = GitBlit.getBoolean(Keys.web.showBranchGraph, true);
+		final boolean showGraph = app().settings().getBoolean(Keys.web.showBranchGraph, true);
 
 		MarkupContainer graph = new WebMarkupContainer("graph");
 		add(graph);
@@ -101,7 +100,7 @@
 					WicketUtils.newRepositoryParameter(repositoryName)));
 		}
 
-		final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+		final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
 		ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
 		DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
 			private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
index ed5780f..1c79760 100644
--- a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
@@ -28,7 +28,6 @@
 import org.apache.wicket.markup.html.panel.Fragment;
 
 import com.gitblit.Constants.AccessRestrictionType;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.SyndicationServlet;
 import com.gitblit.models.RepositoryModel;
@@ -51,8 +50,8 @@
 			final Map<AccessRestrictionType, String> accessRestrictions) {
 		super(wicketId);
 
-		final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
-		final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);
+		final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);
+		final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true);
 
 		// repository swatch
 		Component swatch;
@@ -110,7 +109,7 @@
 		} else {
 			String owner = "";
 			for (String username : entry.owners) {
-				UserModel ownerModel = GitBlit.self().getUserModel(username);
+				UserModel ownerModel = app().users().getUserModel(username);
 
 				if (ownerModel != null) {
 					owner = ownerModel.getDisplayName();
@@ -146,7 +145,7 @@
 
 					@Override
 					public void onClick() {
-						if (GitBlit.self().deleteRepositoryModel(entry)) {
+						if (app().repositories().deleteRepositoryModel(entry)) {
 							// redirect to the owning page
 							if (entry.isPersonalRepository()) {
 								setResponsePage(getPage().getClass(), WicketUtils.newUsernameParameter(entry.projectPath.substring(1)));
diff --git a/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java
index d63f26c..abd4ecd 100644
--- a/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java
@@ -33,7 +33,6 @@
 import org.eclipse.jgit.transport.ReceiveCommand.Type;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RefLogEntry;
 import com.gitblit.models.RepositoryCommit;
@@ -61,7 +60,7 @@
 	public ReflogPanel(String wicketId, final RepositoryModel model, Repository r, int limit, int pageOffset) {
 		super(wicketId);
 		boolean pageResults = limit <= 0;
-		int changesPerPage = GitBlit.getInteger(Keys.web.reflogChangesPerPage, 10);
+		int changesPerPage = app().settings().getInteger(Keys.web.reflogChangesPerPage, 10);
 		if (changesPerPage <= 1) {
 			changesPerPage = 10;
 		}
@@ -111,9 +110,9 @@
 	}
 
 	protected void setup(List<RefLogEntry> changes) {
-		final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+		final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
 
-		String dateFormat = GitBlit.getString(Keys.web.datetimestampLongFormat, "EEEE, MMMM d, yyyy HH:mm Z");
+		String dateFormat = app().settings().getString(Keys.web.datetimestampLongFormat, "EEEE, MMMM d, yyyy HH:mm Z");
 		final TimeZone timezone = getTimeZone();
 		final DateFormat df = new SimpleDateFormat(dateFormat);
 		df.setTimeZone(timezone);
diff --git a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
index dd25c48..756b7db 100644
--- a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
@@ -43,7 +43,6 @@
 import com.gitblit.Constants.AccessPermission;
 import com.gitblit.Constants.PermissionType;
 import com.gitblit.Constants.RegistrantType;
-import com.gitblit.GitBlit;
 import com.gitblit.models.RegistrantAccessPermission;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.DeepCopier;
@@ -140,7 +139,7 @@
 				} else if (RegistrantType.USER.equals(entry.registrantType)) {
 					// user
 					PersonIdent ident = new PersonIdent(entry.registrant, "");
-					UserModel user = GitBlit.self().getUserModel(entry.registrant);
+					UserModel user = app().users().getUserModel(entry.registrant);
 					if (user != null) {
 						ident = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
 					}
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
index 9de387a..8de8492 100644
--- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -43,7 +43,6 @@
 import org.apache.wicket.model.Model;
 
 import com.gitblit.Constants.AccessRestrictionType;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.SyndicationServlet;
 import com.gitblit.models.ProjectModel;
@@ -72,7 +71,7 @@
 		super(wicketId);
 
 		final boolean linksActive = enableLinks;
-		final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);
+		final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true);
 
 		final UserModel user = GitBlitWebSession.get().getUser();
 
@@ -88,10 +87,10 @@
 
 				@Override
 				public void onClick() {
-					GitBlit.self().resetRepositoryListCache();
+					app().repositories().resetRepositoryListCache();
 					setResponsePage(RepositoriesPage.class);
 				}
-			}.setVisible(GitBlit.getBoolean(Keys.git.cacheRepositoryList, true)));
+			}.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));
 			managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
 			add(managementLinks);
 		} else if (showManagement && user != null && user.canCreate()) {
@@ -104,7 +103,7 @@
 			add (new Label("managementPanel").setVisible(false));
 		}
 
-		if (GitBlit.getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
+		if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
 			List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();
 			Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
 			for (RepositoryModel model : models) {
@@ -132,7 +131,7 @@
 			List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
 			for (String root : roots) {
 				List<RepositoryModel> subModels = groups.get(root);
-				ProjectModel project = GitBlit.self().getProjectModel(root);
+				ProjectModel project = app().projects().getProjectModel(root);
 				GroupRepositoryModel group = new GroupRepositoryModel(project == null ? root : project.name, subModels.size());
 				if (project != null) {
 					group.title = project.title;
@@ -148,7 +147,7 @@
 		}
 
 		final String baseUrl = WicketUtils.getGitblitURL(getRequest());
-		final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
+		final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);
 
 		DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
 			private static final long serialVersionUID = 1L;
@@ -174,7 +173,7 @@
 					if (name.startsWith(ModelUtils.getUserRepoPrefix())) {
 						// user page
 						String username = ModelUtils.getUserNameFromRepoPath(name);
-						UserModel user = GitBlit.self().getUserModel(username);
+						UserModel user = app().users().getUserModel(username);
 						row.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()) + " (" + groupRow.count + ")", UserPage.class, WicketUtils.newUsernameParameter(username)));
 						row.add(new Label("groupDescription", getString("gb.personalRepositories")));
 					} else {
@@ -294,7 +293,7 @@
 				if (!ArrayUtils.isEmpty(entry.owners)) {
 					// display first owner
 					for (String username : entry.owners) {
-						UserModel ownerModel = GitBlit.self().getUserModel(username);
+						UserModel ownerModel = app().users().getUserModel(username);
 						if (ownerModel != null) {
 							owner = ownerModel.getDisplayName();
 							break;
@@ -335,7 +334,7 @@
 
 						@Override
 						public void onClick() {
-							if (GitBlit.self().deleteRepositoryModel(entry)) {
+							if (app().repositories().deleteRepositoryModel(entry)) {
 								if (dp instanceof SortableRepositoriesProvider) {
 									info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
 									((SortableRepositoriesProvider) dp).remove(entry);
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java
index ea8693b..2049762 100644
--- a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java
@@ -36,7 +36,6 @@
 
 import com.gitblit.Constants.AccessPermission;
 import com.gitblit.Constants.AccessRestrictionType;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.GitClientApplication;
 import com.gitblit.models.RepositoryModel;
@@ -81,7 +80,7 @@
 
 		HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
 
-		List<RepositoryUrl> repositoryUrls = GitBlit.self().getRepositoryUrls(req, user, repository);
+		List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository);
 		// grab primary url from the top of the list
 		primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
 
@@ -104,7 +103,7 @@
 			add(createRepositoryIndicators(repository));
 		}
 
-		boolean allowAppLinks = GitBlit.getBoolean(Keys.web.allowAppCloneLinks, true);
+		boolean allowAppLinks = app().settings().getBoolean(Keys.web.allowAppCloneLinks, true);
 		if (onlyUrls || !canClone || !allowAppLinks) {
 			// only display the url(s)
 			add(new Label("applicationMenusPanel").setVisible(false));
@@ -163,7 +162,7 @@
 		}
 
 		// access restriction icon and tooltip
-		if (GitBlit.isServingRepositories()) {
+		if (app().runtime().isServingRepositories()) {
 			switch (repository.accessRestriction) {
 			case NONE:
 				urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
@@ -213,7 +212,7 @@
 		final String userAgent = ((WebClientInfo) GitBlitWebSession.get().getClientInfo()).getUserAgent();
 
 		if (user.canClone(repository)) {
-			for (GitClientApplication app : GitBlit.self().getClientApplications()) {
+			for (GitClientApplication app : app().gitblit().getClientApplications()) {
 				if (app.isActive && app.allowsPlatform(userAgent)) {
 					displayedApps.add(app);
 				}
@@ -345,7 +344,7 @@
 	}
 
 	protected Fragment createCopyFragment(String text) {
-		if (GitBlit.getBoolean(Keys.web.allowFlashCopyToClipboard, true)) {
+		if (app().settings().getBoolean(Keys.web.allowFlashCopyToClipboard, true)) {
 			// clippy: flash-based copy & paste
 			Fragment copyFragment = new Fragment("copyFunction", "clippyPanel", this);
 			String baseUrl = WicketUtils.getGitblitURL(getRequest());
@@ -450,12 +449,12 @@
 			fragment.add(wc);
 		}
 
-		boolean allowForking = GitBlit.getBoolean(Keys.web.allowForking, true);
+		boolean allowForking = app().settings().getBoolean(Keys.web.allowForking, true);
 		if (!allowForking || user == null || !user.isAuthenticated) {
 			// must be logged-in to fork, hide all fork controls
 			fragment.add(new Label("forksProhibitedIndicator").setVisible(false));
 		} else {
-			String fork = GitBlit.self().getFork(user.username, repository.name);
+			String fork = app().repositories().getFork(user.username, repository.name);
 			boolean hasFork = fork != null;
 			boolean canFork = user.canFork(repository);
 
diff --git a/src/main/java/com/gitblit/wicket/panels/SearchPanel.java b/src/main/java/com/gitblit/wicket/panels/SearchPanel.java
index bfa38ed..a60cc93 100644
--- a/src/main/java/com/gitblit/wicket/panels/SearchPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/SearchPanel.java
@@ -29,7 +29,6 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 
 import com.gitblit.Constants;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.RefModel;
 import com.gitblit.utils.JGitUtils;
@@ -51,7 +50,7 @@
 			boolean showRemoteRefs) {
 		super(wicketId);
 		boolean pageResults = limit <= 0;
-		int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
+		int itemsPerPage = app().settings().getInteger(Keys.web.itemsPerPage, 50);
 		if (itemsPerPage <= 1) {
 			itemsPerPage = 50;
 		}
diff --git a/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java b/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java
index f567c78..79ddd02 100644
--- a/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/TeamsPanel.java
@@ -26,7 +26,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.TeamModel;
 import com.gitblit.wicket.WicketUtils;
 import com.gitblit.wicket.pages.EditTeamPage;
@@ -40,9 +39,9 @@
 
 		Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
 		adminLinks.add(new BookmarkablePageLink<Void>("newTeam", EditTeamPage.class));
-		add(adminLinks.setVisible(showAdmin && GitBlit.self().supportsTeamMembershipChanges(null)));
+		add(adminLinks.setVisible(showAdmin && app().users().supportsTeamMembershipChanges(null)));
 
-		final List<TeamModel> teams = GitBlit.self().getAllTeams();
+		final List<TeamModel> teams = app().users().getAllTeams();
 		DataView<TeamModel> teamsView = new DataView<TeamModel>("teamRow",
 				new ListDataProvider<TeamModel>(teams)) {
 			private static final long serialVersionUID = 1L;
@@ -74,7 +73,7 @@
 
 					@Override
 					public void onClick() {
-						if (GitBlit.self().deleteTeam(entry.name)) {
+						if (app().users().deleteTeam(entry.name)) {
 							teams.remove(entry);
 							info(MessageFormat.format("Team ''{0}'' deleted.", entry.name));
 						} else {
diff --git a/src/main/java/com/gitblit/wicket/panels/UsersPanel.java b/src/main/java/com/gitblit/wicket/panels/UsersPanel.java
index 545734f..9c1667f 100644
--- a/src/main/java/com/gitblit/wicket/panels/UsersPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/UsersPanel.java
@@ -26,7 +26,6 @@
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
-import com.gitblit.GitBlit;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.wicket.WicketUtils;
@@ -41,10 +40,10 @@
 
 		Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
 		adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class)
-				.setVisible(GitBlit.self().supportsAddUser()));
+				.setVisible(app().users().supportsAddUser()));
 		add(adminLinks.setVisible(showAdmin));
 
-		final List<UserModel> users = GitBlit.self().getAllUsers();
+		final List<UserModel> users = app().users().getAllUsers();
 		DataView<UserModel> usersView = new DataView<UserModel>("userRow",
 				new ListDataProvider<UserModel>(users)) {
 			private static final long serialVersionUID = 1L;
@@ -95,7 +94,7 @@
 
 					@Override
 					public void onClick() {
-						if (GitBlit.self().deleteUser(entry.username)) {
+						if (app().users().deleteUser(entry.username)) {
 							users.remove(entry);
 							info(MessageFormat.format(getString("gb.userDeleted"), entry.username));
 						} else {

--
Gitblit v1.9.1