From 3f5b8f5d9203aa7ffb7fbe9cdbaf9dba3da6cae6 Mon Sep 17 00:00:00 2001
From: Hybris95 <hybris_95@hotmail.com>
Date: Thu, 01 May 2014 16:14:15 -0400
Subject: [PATCH] Fixes sort, page building and search functions on "my tickets" page.

---
 src/main/java/com/gitblit/GitBlit.java |  667 ++++++++++++++++++++++++++++--------------------------
 1 files changed, 346 insertions(+), 321 deletions(-)

diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index ca676ff..3db5f08 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/src/main/java/com/gitblit/GitBlit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 gitblit.com.
+ * 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.
@@ -15,412 +15,437 @@
  */
 package com.gitblit;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
+import java.util.Set;
 
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.servlet.ServletContext;
-import javax.servlet.annotation.WebListener;
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
 
-import com.gitblit.dagger.DaggerContextListener;
-import com.gitblit.git.GitServlet;
+import com.gitblit.Constants.AccessPermission;
+import com.gitblit.Constants.Transport;
+import com.gitblit.manager.GitblitManager;
+import com.gitblit.manager.IAuthenticationManager;
 import com.gitblit.manager.IFederationManager;
-import com.gitblit.manager.IGitblitManager;
-import com.gitblit.manager.IManager;
+import com.gitblit.manager.IGitblit;
 import com.gitblit.manager.INotificationManager;
+import com.gitblit.manager.IPluginManager;
 import com.gitblit.manager.IProjectManager;
 import com.gitblit.manager.IRepositoryManager;
 import com.gitblit.manager.IRuntimeManager;
-import com.gitblit.manager.IServicesManager;
-import com.gitblit.manager.ISessionManager;
 import com.gitblit.manager.IUserManager;
-import com.gitblit.utils.ContainerUtils;
+import com.gitblit.manager.ServicesManager;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.RepositoryUrl;
+import com.gitblit.models.UserModel;
+import com.gitblit.tickets.BranchTicketService;
+import com.gitblit.tickets.FileTicketService;
+import com.gitblit.tickets.ITicketService;
+import com.gitblit.tickets.NullTicketService;
+import com.gitblit.tickets.RedisTicketService;
+import com.gitblit.transport.ssh.IPublicKeyManager;
 import com.gitblit.utils.StringUtils;
-import com.gitblit.wicket.GitblitWicketFilter;
 
+import dagger.Module;
 import dagger.ObjectGraph;
+import dagger.Provides;
 
 /**
- * This class is the main entry point for the entire webapp.  It is a singleton
- * created manually by Gitblit GO or dynamically by the WAR/Express servlet
- * container.  This class instantiates and starts all managers followed by
- * instantiating and registering all servlets and filters.
- *
- * Leveraging Servlet 3 and Dagger static dependency injection allows Gitblit to
- * be modular and completely code-driven rather then relying on the fragility of
- * a web.xml descriptor and the static & monolithic design previously used.
+ * GitBlit is the aggregate manager for the Gitblit webapp.  It provides all
+ * management functions and also manages some long-running services.
  *
  * @author James Moger
  *
  */
-@WebListener
-public class GitBlit extends DaggerContextListener {
+public class GitBlit extends GitblitManager {
 
-	private static GitBlit gitblit;
+	private final ObjectGraph injector;
 
-	private final List<IManager> managers = new ArrayList<IManager>();
+	private final ServicesManager servicesManager;
 
-	private final IStoredSettings goSettings;
+	private ITicketService ticketService;
 
-	private final File goBaseFolder;
+	public GitBlit(
+			IRuntimeManager runtimeManager,
+			IPluginManager pluginManager,
+			INotificationManager notificationManager,
+			IUserManager userManager,
+			IAuthenticationManager authenticationManager,
+			IPublicKeyManager publicKeyManager,
+			IRepositoryManager repositoryManager,
+			IProjectManager projectManager,
+			IFederationManager federationManager) {
 
-	/**
-	 * Construct a Gitblit WAR/Express context.
-	 */
-	public GitBlit() {
-		this.goSettings = null;
-		this.goBaseFolder = null;
-		gitblit = this;
+		super(runtimeManager,
+				pluginManager,
+				notificationManager,
+				userManager,
+				authenticationManager,
+				publicKeyManager,
+				repositoryManager,
+				projectManager,
+				federationManager);
+
+		this.injector = ObjectGraph.create(getModules());
+
+		this.servicesManager = new ServicesManager(this);
 	}
 
-	/**
-	 * Construct a Gitblit GO context.
-	 *
-	 * @param settings
-	 * @param baseFolder
-	 */
-	public GitBlit(IStoredSettings settings, File baseFolder) {
-		this.goSettings = settings;
-		this.goBaseFolder = baseFolder;
-		gitblit = this;
-	}
-
-	/**
-	 * This method is only used for unit and integration testing.
-	 *
-	 * @param managerClass
-	 * @return a manager
-	 */
-	@SuppressWarnings("unchecked")
-	public static <X extends IManager> X getManager(Class<X> managerClass) {
-		for (IManager manager : gitblit.managers) {
-			if (managerClass.isAssignableFrom(manager.getClass())) {
-				return (X) manager;
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Returns Gitblit's Dagger injection modules.
-	 */
 	@Override
+	public GitBlit start() {
+		super.start();
+		logger.info("Starting services manager...");
+		servicesManager.start();
+		configureTicketService();
+		return this;
+	}
+
+	@Override
+	public GitBlit stop() {
+		super.stop();
+		servicesManager.stop();
+		ticketService.stop();
+		return this;
+	}
+
+	@Override
+	public boolean isServingRepositories() {
+		return servicesManager.isServingRepositories();
+	}
+
 	protected Object [] getModules() {
-		return new Object [] { new DaggerModule() };
+		return new Object [] { new GitBlitModule()};
+	}
+
+	protected boolean acceptPush(Transport byTransport) {
+		if (byTransport == null) {
+			logger.info("Unknown transport, push rejected!");
+			return false;
+		}
+
+		Set<Transport> transports = new HashSet<Transport>();
+		for (String value : getSettings().getStrings(Keys.git.acceptedPushTransports)) {
+			Transport transport = Transport.fromString(value);
+			if (transport == null) {
+				logger.info(String.format("Ignoring unknown registered transport %s", value));
+				continue;
+			}
+
+			transports.add(transport);
+		}
+
+		if (transports.isEmpty()) {
+			// no transports are explicitly specified, all are acceptable
+			return true;
+		}
+
+		// verify that the transport is permitted
+		return transports.contains(byTransport);
 	}
 
 	/**
-	 * Prepare runtime settings and start all manager instances.
+	 * Returns a list of repository URLs and the user access permission.
+	 *
+	 * @param request
+	 * @param user
+	 * @param repository
+	 * @return a list of repository urls
 	 */
 	@Override
-	protected void beforeServletInjection(ServletContext context) {
-		ObjectGraph injector = getInjector(context);
+	public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
+		if (user == null) {
+			user = UserModel.ANONYMOUS;
+		}
+		String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);
 
-		// create the runtime settings object
-		IStoredSettings runtimeSettings = injector.get(IStoredSettings.class);
-		final File baseFolder;
+		List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();
 
-		if (goSettings != null) {
-			// Gitblit GO
-			baseFolder = configureGO(context, goSettings, goBaseFolder, runtimeSettings);
-		} else {
-			// servlet container
-			WebXmlSettings webxmlSettings = new WebXmlSettings(context);
-			String contextRealPath = context.getRealPath("/");
-			File contextFolder = (contextRealPath != null) ? new File(contextRealPath) : null;
+		// http/https url
+		if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
+			AccessPermission permission = user.getRepositoryPermission(repository).permission;
+			if (permission.exceeds(AccessPermission.NONE)) {
+				Transport transport = Transport.fromString(request.getScheme());
+				if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(transport)) {
+					// downgrade the repo permission for this transport
+					// because it is not an acceptable PUSH transport
+					permission = AccessPermission.CLONE;
+				}
+				list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission));
+			}
+		}
 
-			if (!StringUtils.isEmpty(System.getenv("OPENSHIFT_DATA_DIR"))) {
-				// RedHat OpenShift
-				baseFolder = configureExpress(context, webxmlSettings, contextFolder, runtimeSettings);
+		// ssh daemon url
+		String sshDaemonUrl = servicesManager.getSshDaemonUrl(request, user, repository);
+		if (!StringUtils.isEmpty(sshDaemonUrl)) {
+			AccessPermission permission = user.getRepositoryPermission(repository).permission;
+			if (permission.exceeds(AccessPermission.NONE)) {
+				if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(Transport.SSH)) {
+					// downgrade the repo permission for this transport
+					// because it is not an acceptable PUSH transport
+					permission = AccessPermission.CLONE;
+				}
+
+				list.add(new RepositoryUrl(sshDaemonUrl, permission));
+			}
+		}
+
+		// git daemon url
+		String gitDaemonUrl = servicesManager.getGitDaemonUrl(request, user, repository);
+		if (!StringUtils.isEmpty(gitDaemonUrl)) {
+			AccessPermission permission = servicesManager.getGitDaemonAccessPermission(user, repository);
+			if (permission.exceeds(AccessPermission.NONE)) {
+				if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(Transport.GIT)) {
+					// downgrade the repo permission for this transport
+					// because it is not an acceptable PUSH transport
+					permission = AccessPermission.CLONE;
+				}
+				list.add(new RepositoryUrl(gitDaemonUrl, permission));
+			}
+		}
+
+		// add all other urls
+		// {0} = repository
+		// {1} = username
+		for (String url : settings.getStrings(Keys.web.otherUrls)) {
+			if (url.contains("{1}")) {
+				// external url requires username, only add url IF we have one
+				if (!StringUtils.isEmpty(username)) {
+					list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
+				}
 			} else {
-				// standard WAR
-				baseFolder = configureWAR(context, webxmlSettings, contextFolder, runtimeSettings);
+				// external url does not require username
+				list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null));
 			}
-
-			// Test for Tomcat forward-slash/%2F issue and auto-adjust settings
-			ContainerUtils.CVE_2007_0450.test(runtimeSettings);
 		}
 
-		// Manually configure IRuntimeManager
-		logManager(IRuntimeManager.class);
-		IRuntimeManager runtime = injector.get(IRuntimeManager.class);
-		runtime.setBaseFolder(baseFolder);
-		runtime.getStatus().isGO = goSettings != null;
-		runtime.getStatus().servletContainer = context.getServerInfo();
-		runtime.start();
-		managers.add(runtime);
+		// sort transports by highest permission and then by transport security
+		Collections.sort(list, new Comparator<RepositoryUrl>() {
 
-		// start all other managers
-		startManager(injector, INotificationManager.class);
-		startManager(injector, IUserManager.class);
-		startManager(injector, ISessionManager.class);
-		startManager(injector, IRepositoryManager.class);
-		startManager(injector, IProjectManager.class);
-		startManager(injector, IGitblitManager.class);
-		startManager(injector, IFederationManager.class);
-		startManager(injector, IServicesManager.class);
+			@Override
+			public int compare(RepositoryUrl o1, RepositoryUrl o2) {
+				if (!o1.isExternal() && o2.isExternal()) {
+					// prefer Gitblit over external
+					return -1;
+				} else if (o1.isExternal() && !o2.isExternal()) {
+					// prefer Gitblit over external
+					return 1;
+				} else if (o1.isExternal() && o2.isExternal()) {
+					// sort by Transport ordinal
+					return o1.transport.compareTo(o2.transport);
+				} else if (o1.permission.exceeds(o2.permission)) {
+					// prefer highest permission
+					return -1;
+				} else if (o2.permission.exceeds(o1.permission)) {
+					// prefer highest permission
+					return 1;
+				}
 
-		logger.info("");
-		logger.info("All managers started.");
-		logger.info("");
-	}
+				// prefer more secure transports
+				return o1.transport.compareTo(o2.transport);
+			}
+		});
 
-	protected <X extends IManager> X startManager(ObjectGraph injector, Class<X> clazz) {
-		logManager(clazz);
-		X x = injector.get(clazz);
-		x.start();
-		managers.add(x);
-		return x;
-	}
-
-	protected void logManager(Class<? extends IManager> clazz) {
-		logger.info("");
-		logger.info("----[{}]----", clazz.getName());
+		return list;
 	}
 
 	/**
-	 * Instantiate and inject all filters and servlets into the container using
-	 * the servlet 3 specification.
+	 * Detect renames and reindex as appropriate.
 	 */
 	@Override
-	protected void injectServlets(ServletContext context) {
-		// access restricted servlets
-		serve(context, Constants.GIT_PATH, GitServlet.class, GitFilter.class);
-		serve(context, Constants.PAGES, PagesServlet.class, PagesFilter.class);
-		serve(context, Constants.RPC_PATH, RpcServlet.class, RpcFilter.class);
-		serve(context, Constants.ZIP_PATH, DownloadZipServlet.class, DownloadZipFilter.class);
-		serve(context, Constants.SYNDICATION_PATH, SyndicationServlet.class, SyndicationFilter.class);
+	public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
+			boolean isCreate) throws GitBlitException {
+		RepositoryModel oldModel = null;
+		boolean isRename = !isCreate && !repositoryName.equalsIgnoreCase(repository.name);
+		if (isRename) {
+			oldModel = repositoryManager.getRepositoryModel(repositoryName);
+		}
 
-		// servlets
-		serve(context, Constants.FEDERATION_PATH, FederationServlet.class);
-		serve(context, Constants.SPARKLESHARE_INVITE_PATH, SparkleShareInviteServlet.class);
-		serve(context, Constants.BRANCH_GRAPH_PATH, BranchGraphServlet.class);
-		file(context, "/robots.txt", RobotsTxtServlet.class);
-		file(context, "/logo.png", LogoServlet.class);
+		super.updateRepositoryModel(repositoryName, repository, isCreate);
 
-		// optional force basic authentication
-		filter(context, "/*", EnforceAuthenticationFilter.class, null);
-
-		// Wicket
-		String toIgnore = StringUtils.flattenStrings(getRegisteredPaths(), ",");
-		Map<String, String> params = new HashMap<String, String>();
-		params.put(GitblitWicketFilter.FILTER_MAPPING_PARAM, "/*");
-		params.put(GitblitWicketFilter.IGNORE_PATHS_PARAM, toIgnore);
-		filter(context, "/*", GitblitWicketFilter.class, params);
+		if (isRename && ticketService != null) {
+			ticketService.rename(oldModel, repository);
+		}
 	}
 
 	/**
-	 * Gitblit is being shutdown either because the servlet container is
-	 * shutting down or because the servlet container is re-deploying Gitblit.
+	 * Delete the user and all associated public ssh keys.
 	 */
 	@Override
-	protected void destroyContext(ServletContext context) {
-		logger.info("Gitblit context destroyed by servlet container.");
-		for (IManager manager : managers) {
-			logger.debug("stopping {}", manager.getClass().getSimpleName());
-			manager.stop();
+	public boolean deleteUser(String username) {
+		UserModel user = userManager.getUserModel(username);
+		return deleteUserModel(user);
+	}
+
+	@Override
+	public boolean deleteUserModel(UserModel model) {
+		boolean success = userManager.deleteUserModel(model);
+		if (success) {
+			getPublicKeyManager().removeAllKeys(model.username);
 		}
+		return success;
 	}
 
 	/**
-	 * Configures Gitblit GO
-	 *
-	 * @param context
-	 * @param settings
-	 * @param baseFolder
-	 * @param runtimeSettings
-	 * @return the base folder
+	 * Delete the repository and all associated tickets.
 	 */
-	protected File configureGO(
-			ServletContext context,
-			IStoredSettings goSettings,
-			File goBaseFolder,
-			IStoredSettings runtimeSettings) {
-
-		logger.debug("configuring Gitblit GO");
-
-		// merge the stored settings into the runtime settings
-		//
-		// if runtimeSettings is also a FileSettings w/o a specified target file,
-		// the target file for runtimeSettings is set to "localSettings".
-		runtimeSettings.merge(goSettings);
-		File base = goBaseFolder;
-		return base;
+	@Override
+	public boolean deleteRepository(String repositoryName) {
+		RepositoryModel repository = repositoryManager.getRepositoryModel(repositoryName);
+		return deleteRepositoryModel(repository);
 	}
 
+	@Override
+	public boolean deleteRepositoryModel(RepositoryModel model) {
+		boolean success = repositoryManager.deleteRepositoryModel(model);
+		if (success && ticketService != null) {
+			ticketService.deleteAll(model);
+		}
+		return success;
+	}
 
 	/**
-	 * Configures a standard WAR instance of Gitblit.
+	 * Returns the configured ticket service.
 	 *
-	 * @param context
-	 * @param webxmlSettings
-	 * @param contextFolder
-	 * @param runtimeSettings
-	 * @return the base folder
+	 * @return a ticket service
 	 */
-	protected File configureWAR(
-			ServletContext context,
-			WebXmlSettings webxmlSettings,
-			File contextFolder,
-			IStoredSettings runtimeSettings) {
+	@Override
+	public ITicketService getTicketService() {
+		return ticketService;
+	}
 
-		// Gitblit is running in a standard servlet container
-		logger.debug("configuring Gitblit WAR");
-		logger.info("WAR contextFolder is " + ((contextFolder != null) ? contextFolder.getAbsolutePath() : "<empty>"));
-
-		String path = webxmlSettings.getString(Constants.baseFolder, Constants.contextFolder$ + "/WEB-INF/data");
-
-		if (path.contains(Constants.contextFolder$) && contextFolder == null) {
-			// warn about null contextFolder (issue-199)
-			logger.error("");
-			logger.error(MessageFormat.format("\"{0}\" depends on \"{1}\" but \"{2}\" is returning NULL for \"{1}\"!",
-					Constants.baseFolder, Constants.contextFolder$, context.getServerInfo()));
-			logger.error(MessageFormat.format("Please specify a non-parameterized path for <context-param> {0} in web.xml!!", Constants.baseFolder));
-			logger.error(MessageFormat.format("OR configure your servlet container to specify a \"{0}\" parameter in the context configuration!!", Constants.baseFolder));
-			logger.error("");
+	protected void configureTicketService() {
+		String clazz = settings.getString(Keys.tickets.service, NullTicketService.class.getName());
+		if (StringUtils.isEmpty(clazz)) {
+			clazz = NullTicketService.class.getName();
 		}
-
 		try {
-			// try to lookup JNDI env-entry for the baseFolder
-			InitialContext ic = new InitialContext();
-			Context env = (Context) ic.lookup("java:comp/env");
-			String val = (String) env.lookup("baseFolder");
-			if (!StringUtils.isEmpty(val)) {
-				path = val;
+			Class<? extends ITicketService> serviceClass = (Class<? extends ITicketService>) Class.forName(clazz);
+			ticketService = injector.get(serviceClass).start();
+			if (ticketService instanceof NullTicketService) {
+				logger.warn("No ticket service configured.");
+			} else if (ticketService.isReady()) {
+				logger.info("{} is ready.", ticketService);
+			} else {
+				logger.warn("{} is disabled.", ticketService);
 			}
-		} catch (NamingException n) {
-			logger.error("Failed to get JNDI env-entry: " + n.getExplanation());
+		} catch (Exception e) {
+			logger.error("failed to create ticket service " + clazz, e);
+			ticketService = injector.get(NullTicketService.class).start();
 		}
-
-		File base = com.gitblit.utils.FileUtils.resolveParameter(Constants.contextFolder$, contextFolder, path);
-		base.mkdirs();
-
-		// try to extract the data folder resource to the baseFolder
-		File localSettings = new File(base, "gitblit.properties");
-		if (!localSettings.exists()) {
-			extractResources(context, "/WEB-INF/data/", base);
-		}
-
-		// delegate all config to baseFolder/gitblit.properties file
-		FileSettings fileSettings = new FileSettings(localSettings.getAbsolutePath());
-
-		// merge the stored settings into the runtime settings
-		//
-		// if runtimeSettings is also a FileSettings w/o a specified target file,
-		// the target file for runtimeSettings is set to "localSettings".
-		runtimeSettings.merge(fileSettings);
-
-		return base;
 	}
 
 	/**
-	 * Configures an OpenShift instance of Gitblit.
+	 * A nested Dagger graph is used for constructor dependency injection of
+	 * complex classes.
 	 *
-	 * @param context
-	 * @param webxmlSettings
-	 * @param contextFolder
-	 * @param runtimeSettings
-	 * @return the base folder
+	 * @author James Moger
+	 *
 	 */
-	private File configureExpress(
-			ServletContext context,
-			WebXmlSettings webxmlSettings,
-			File contextFolder,
-			IStoredSettings runtimeSettings) {
+	@Module(
+			library = true,
+			injects = {
+					IStoredSettings.class,
 
-		// Gitblit is running in OpenShift/JBoss
-		logger.debug("configuring Gitblit Express");
-		String openShift = System.getenv("OPENSHIFT_DATA_DIR");
-		File base = new File(openShift);
-		logger.info("EXPRESS contextFolder is " + contextFolder.getAbsolutePath());
+					// core managers
+					IRuntimeManager.class,
+					IPluginManager.class,
+					INotificationManager.class,
+					IUserManager.class,
+					IAuthenticationManager.class,
+					IRepositoryManager.class,
+					IProjectManager.class,
+					IFederationManager.class,
 
-		// Copy the included scripts to the configured groovy folder
-		String path = webxmlSettings.getString(Keys.groovy.scriptsFolder, "groovy");
-		File localScripts = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, base, path);
-		if (!localScripts.exists()) {
-			File warScripts = new File(contextFolder, "/WEB-INF/data/groovy");
-			if (!warScripts.equals(localScripts)) {
-				try {
-					com.gitblit.utils.FileUtils.copy(localScripts, warScripts.listFiles());
-				} catch (IOException e) {
-					logger.error(MessageFormat.format(
-							"Failed to copy included Groovy scripts from {0} to {1}",
-							warScripts, localScripts));
+					// the monolithic manager
+					IGitblit.class,
+
+					// ticket services
+					NullTicketService.class,
+					FileTicketService.class,
+					BranchTicketService.class,
+					RedisTicketService.class
 				}
-			}
+			)
+	class GitBlitModule {
+
+		@Provides @Singleton IStoredSettings provideSettings() {
+			return settings;
 		}
 
-		// merge the WebXmlSettings into the runtime settings (for backwards-compatibilty)
-		runtimeSettings.merge(webxmlSettings);
+		@Provides @Singleton IRuntimeManager provideRuntimeManager() {
+			return runtimeManager;
+		}
 
-		// settings are to be stored in openshift/gitblit.properties
-		File localSettings = new File(base, "gitblit.properties");
-		FileSettings fileSettings = new FileSettings(localSettings.getAbsolutePath());
+		@Provides @Singleton IPluginManager providePluginManager() {
+			return pluginManager;
+		}
 
-		// merge the stored settings into the runtime settings
-		//
-		// if runtimeSettings is also a FileSettings w/o a specified target file,
-		// the target file for runtimeSettings is set to "localSettings".
-		runtimeSettings.merge(fileSettings);
+		@Provides @Singleton INotificationManager provideNotificationManager() {
+			return notificationManager;
+		}
 
-		return base;
-	}
+		@Provides @Singleton IUserManager provideUserManager() {
+			return userManager;
+		}
 
-	protected void extractResources(ServletContext context, String path, File toDir) {
-		for (String resource : context.getResourcePaths(path)) {
-			// extract the resource to the directory if it does not exist
-			File f = new File(toDir, resource.substring(path.length()));
-			if (!f.exists()) {
-				InputStream is = null;
-				OutputStream os = null;
-				try {
-					if (resource.charAt(resource.length() - 1) == '/') {
-						// directory
-						f.mkdirs();
-						extractResources(context, resource, f);
-					} else {
-						// file
-						f.getParentFile().mkdirs();
-						is = context.getResourceAsStream(resource);
-						os = new FileOutputStream(f);
-						byte [] buffer = new byte[4096];
-						int len = 0;
-						while ((len = is.read(buffer)) > -1) {
-							os.write(buffer, 0, len);
-						}
-					}
-				} catch (FileNotFoundException e) {
-					logger.error("Failed to find resource \"" + resource + "\"", e);
-				} catch (IOException e) {
-					logger.error("Failed to copy resource \"" + resource + "\" to " + f, e);
-				} finally {
-					if (is != null) {
-						try {
-							is.close();
-						} catch (IOException e) {
-							// ignore
-						}
-					}
-					if (os != null) {
-						try {
-							os.close();
-						} catch (IOException e) {
-							// ignore
-						}
-					}
-				}
-			}
+		@Provides @Singleton IAuthenticationManager provideAuthenticationManager() {
+			return authenticationManager;
+		}
+
+		@Provides @Singleton IRepositoryManager provideRepositoryManager() {
+			return repositoryManager;
+		}
+
+		@Provides @Singleton IProjectManager provideProjectManager() {
+			return projectManager;
+		}
+
+		@Provides @Singleton IFederationManager provideFederationManager() {
+			return federationManager;
+		}
+
+		@Provides @Singleton IGitblit provideGitblit() {
+			return GitBlit.this;
+		}
+
+		@Provides @Singleton NullTicketService provideNullTicketService() {
+			return new NullTicketService(
+					runtimeManager,
+					pluginManager,
+					notificationManager,
+					userManager,
+					repositoryManager);
+		}
+
+		@Provides @Singleton FileTicketService provideFileTicketService() {
+			return new FileTicketService(
+					runtimeManager,
+					pluginManager,
+					notificationManager,
+					userManager,
+					repositoryManager);
+		}
+
+		@Provides @Singleton BranchTicketService provideBranchTicketService() {
+			return new BranchTicketService(
+					runtimeManager,
+					pluginManager,
+					notificationManager,
+					userManager,
+					repositoryManager);
+		}
+
+		@Provides @Singleton RedisTicketService provideRedisTicketService() {
+			return new RedisTicketService(
+					runtimeManager,
+					pluginManager,
+					notificationManager,
+					userManager,
+					repositoryManager);
 		}
 	}
 }

--
Gitblit v1.9.1