From aa1361d04cfe09f90e7d8bece90c00dd6e4185bb Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 03 Jul 2014 16:57:47 -0400
Subject: [PATCH] Replace Dagger with Guice 4.0 beta and update Guava to 16.0.1

---
 src/main/java/com/gitblit/GitBlit.java |  266 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 159 insertions(+), 107 deletions(-)

diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index fa681ac..df2f502 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/src/main/java/com/gitblit/GitBlit.java
@@ -17,12 +17,18 @@
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
-import javax.inject.Singleton;
+import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 
 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;
@@ -37,17 +43,13 @@
 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 dagger.Module;
-import dagger.ObjectGraph;
-import dagger.Provides;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 
 /**
  * GitBlit is the aggregate manager for the Gitblit webapp.  It provides all
@@ -58,12 +60,13 @@
  */
 public class GitBlit extends GitblitManager {
 
-	private final ObjectGraph injector;
+	private final Injector injector;
 
 	private final ServicesManager servicesManager;
 
 	private ITicketService ticketService;
 
+	@Inject
 	public GitBlit(
 			IRuntimeManager runtimeManager,
 			IPluginManager pluginManager,
@@ -85,7 +88,7 @@
 				projectManager,
 				federationManager);
 
-		this.injector = ObjectGraph.create(getModules());
+		this.injector = Guice.createInjector(getModules());
 
 		this.servicesManager = new ServicesManager(this);
 	}
@@ -107,8 +110,54 @@
 		return this;
 	}
 
-	protected Object [] getModules() {
-		return new Object [] { new GitBlitModule()};
+	@Override
+	public boolean isServingRepositories() {
+		return servicesManager.isServingRepositories();
+	}
+
+	@Override
+	public boolean isServingHTTP() {
+		return servicesManager.isServingHTTP();
+	}
+
+	@Override
+	public boolean isServingGIT() {
+		return servicesManager.isServingGIT();
+	}
+
+	@Override
+	public boolean isServingSSH() {
+		return servicesManager.isServingSSH();
+	}
+
+	protected AbstractModule [] getModules() {
+		return new AbstractModule [] { 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);
 	}
 
 	/**
@@ -132,6 +181,12 @@
 		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));
 			}
 		}
@@ -141,6 +196,12 @@
 		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));
 			}
 		}
@@ -150,6 +211,11 @@
 		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));
 			}
 		}
@@ -168,6 +234,52 @@
 				list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null));
 			}
 		}
+
+		// sort transports by highest permission and then by transport security
+		Collections.sort(list, new Comparator<RepositoryUrl>() {
+
+			@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;
+				}
+
+				// prefer more secure transports
+				return o1.transport.compareTo(o2.transport);
+			}
+		});
+
+		// consider the user's transport preference
+		RepositoryUrl preferredUrl = null;
+		Transport preferredTransport = user.getPreferences().getTransport();
+		if (preferredTransport != null) {
+			Iterator<RepositoryUrl> itr = list.iterator();
+			while (itr.hasNext()) {
+				RepositoryUrl url = itr.next();
+				if (url.transport.equals(preferredTransport)) {
+					itr.remove();
+					preferredUrl = url;
+					break;
+				}
+			}
+		}
+		if (preferredUrl != null) {
+			list.add(0, preferredUrl);
+		}
+
 		return list;
 	}
 
@@ -191,6 +303,24 @@
 	}
 
 	/**
+	 * Delete the user and all associated public ssh keys.
+	 */
+	@Override
+	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;
+	}
+
+	/**
 	 * Delete the repository and all associated tickets.
 	 */
 	@Override
@@ -203,7 +333,7 @@
 	public boolean deleteRepositoryModel(RepositoryModel model) {
 		boolean success = repositoryManager.deleteRepositoryModel(model);
 		if (success && ticketService != null) {
-			return ticketService.deleteAll(model);
+			ticketService.deleteAll(model);
 		}
 		return success;
 	}
@@ -225,7 +355,7 @@
 		}
 		try {
 			Class<? extends ITicketService> serviceClass = (Class<? extends ITicketService>) Class.forName(clazz);
-			ticketService = injector.get(serviceClass).start();
+			ticketService = injector.getInstance(serviceClass).start();
 			if (ticketService instanceof NullTicketService) {
 				logger.warn("No ticket service configured.");
 			} else if (ticketService.isReady()) {
@@ -235,109 +365,31 @@
 			}
 		} catch (Exception e) {
 			logger.error("failed to create ticket service " + clazz, e);
-			ticketService = injector.get(NullTicketService.class).start();
+			ticketService = injector.getInstance(NullTicketService.class).start();
 		}
 	}
 
 	/**
-	 * A nested Dagger graph is used for constructor dependency injection of
+	 * A nested Guice Module is used for constructor dependency injection of
 	 * complex classes.
 	 *
 	 * @author James Moger
 	 *
 	 */
-	@Module(
-			library = true,
-			injects = {
-					IStoredSettings.class,
+	class GitBlitModule extends AbstractModule {
 
-					// core managers
-					IRuntimeManager.class,
-					INotificationManager.class,
-					IUserManager.class,
-					IAuthenticationManager.class,
-					IRepositoryManager.class,
-					IProjectManager.class,
-					IFederationManager.class,
-
-					// the monolithic manager
-					IGitblit.class,
-
-					// ticket services
-					NullTicketService.class,
-					FileTicketService.class,
-					BranchTicketService.class,
-					RedisTicketService.class
-				}
-			)
-	class GitBlitModule {
-
-		@Provides @Singleton IStoredSettings provideSettings() {
-			return settings;
-		}
-
-		@Provides @Singleton IRuntimeManager provideRuntimeManager() {
-			return runtimeManager;
-		}
-
-		@Provides @Singleton INotificationManager provideNotificationManager() {
-			return notificationManager;
-		}
-
-		@Provides @Singleton IUserManager provideUserManager() {
-			return userManager;
-		}
-
-		@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,
-					notificationManager,
-					userManager,
-					repositoryManager);
-		}
-
-		@Provides @Singleton FileTicketService provideFileTicketService() {
-			return new FileTicketService(
-					runtimeManager,
-					notificationManager,
-					userManager,
-					repositoryManager);
-		}
-
-		@Provides @Singleton BranchTicketService provideBranchTicketService() {
-			return new BranchTicketService(
-					runtimeManager,
-					notificationManager,
-					userManager,
-					repositoryManager);
-		}
-
-		@Provides @Singleton RedisTicketService provideRedisTicketService() {
-			return new RedisTicketService(
-					runtimeManager,
-					notificationManager,
-					userManager,
-					repositoryManager);
+		@Override
+		protected void configure() {
+			bind(IStoredSettings.class).toInstance(settings);
+			bind(IRuntimeManager.class).toInstance(runtimeManager);
+			bind(IPluginManager.class).toInstance(pluginManager);
+			bind(INotificationManager.class).toInstance(notificationManager);
+			bind(IUserManager.class).toInstance(userManager);
+			bind(IAuthenticationManager.class).toInstance(authenticationManager);
+			bind(IRepositoryManager.class).toInstance(repositoryManager);
+			bind(IProjectManager.class).toInstance(projectManager);
+			bind(IFederationManager.class).toInstance(federationManager);
+			bind(IGitblit.class).toInstance(GitBlit.this);
 		}
 	}
 }

--
Gitblit v1.9.1