From f76fee63ed9cb3a30d3c0c092d860b1cb93a481b Mon Sep 17 00:00:00 2001
From: Gerard Smyth <gerard.smyth@gmail.com>
Date: Thu, 08 May 2014 13:09:30 -0400
Subject: [PATCH] Updated the SyndicationServlet to provide an additional option to return details of the tags in the repository instead of the commits. This uses a new 'ot' request parameter to indicate the object type of the content to return, which can be ither TAG or COMMIT. If this is not provided, then COMMIT is assumed to maintain backwards compatability. If tags are returned, then the paging parameters, 'l' and 'pg' are still supported, but searching options are currently ignored.

---
 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