From bf4fc5c25ec31566b0fc1ee2e5e8bc15e5512893 Mon Sep 17 00:00:00 2001
From: David Ostrovsky <david@ostrovsky.org>
Date: Thu, 10 Apr 2014 18:58:08 -0400
Subject: [PATCH] Add support for NIO2 IoSession

---
 src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java |  120 +++++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
index 672f024..597b9ea 100644
--- a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
+++ b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -16,18 +16,23 @@
 
 import java.io.IOException;
 import java.io.StringWriter;
+import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import javax.inject.Provider;
 
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;
 import org.kohsuke.args4j.Argument;
 
+import com.gitblit.git.GitblitReceivePackFactory;
+import com.gitblit.git.GitblitUploadPackFactory;
+import com.gitblit.git.RepositoryResolver;
+import com.gitblit.transport.ssh.AbstractGitCommand;
 import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.SshSession;
 import com.gitblit.utils.cli.SubcommandHandler;
 import com.google.common.base.Charsets;
 import com.google.common.base.Strings;
@@ -42,28 +47,34 @@
   @Argument(index = 1, multiValued = true, metaVar = "ARG")
   private List<String> args = new ArrayList<String>();
 
-  private Set<Provider<Command>> commands;
-  private Map<String, Provider<Command>> map;
+  private Set<Class<? extends Command>> commands;
+  private Map<String, Class<? extends Command>> map;
+  private Map<String, Command> root;
 
-  public DispatchCommand() {}
-
-  public DispatchCommand(Map<String, Provider<Command>> map) {
-    this.map = map;
+  public DispatchCommand() {
+	  commands = new HashSet<Class<? extends Command>>();
   }
 
-  public void setMap(Map<String, Provider<Command>> m) {
-    map = m;
+  public void registerDispatcher(String name, Command cmd) {
+	  if (root == null) {
+		  root = Maps.newHashMap();
+	  }
+	  root.put(name, cmd);
   }
 
-  public DispatchCommand(Set<Provider<Command>> commands) {
-    this.commands = commands;
+  public void registerCommand(Class<? extends Command> cmd) {
+	  if (!cmd.isAnnotationPresent(CommandMetaData.class)) {
+		  throw new RuntimeException(MessageFormat.format("{0} must be annotated with {1}!",
+				  cmd.getName(), CommandMetaData.class.getName()));
+	  }
+	  commands.add(cmd);
   }
 
-  private Map<String, Provider<Command>> getMap() {
+  private Map<String, Class<? extends Command>> getMap() {
     if (map == null) {
       map = Maps.newHashMapWithExpectedSize(commands.size());
-      for (Provider<Command> cmd : commands) {
-        CommandMetaData meta = cmd.get().getClass().getAnnotation(CommandMetaData.class);
+      for (Class<? extends Command> cmd : commands) {
+        CommandMetaData meta = cmd.getAnnotation(CommandMetaData.class);
         map.put(meta.name(), cmd);
       }
     }
@@ -80,15 +91,7 @@
         throw new UnloggedFailure(1, msg.toString());
       }
 
-      final Provider<Command> p = getMap().get(commandName);
-      if (p == null) {
-        String msg =
-            (getName().isEmpty() ? "Gitblit" : getName()) + ": "
-                + commandName + ": not found";
-        throw new UnloggedFailure(1, msg);
-      }
-
-      final Command cmd = p.get();
+      Command cmd = getCommand();
       if (cmd instanceof BaseCommand) {
         BaseCommand bc = (BaseCommand) cmd;
         if (getName().isEmpty()) {
@@ -97,11 +100,11 @@
           bc.setName(getName() + " " + commandName);
         }
         bc.setArguments(args.toArray(new String[args.size()]));
-      } else if (!args.isEmpty()) {
-        throw new UnloggedFailure(1, commandName + " does not take arguments");
       }
 
-      provideStateTo(cmd);
+      provideBaseStateTo(cmd);
+      provideGitState(cmd);
+      reset();
       //atomicCmd.set(cmd);
       cmd.start(env);
 
@@ -116,6 +119,28 @@
     }
   }
 
+  private Command getCommand() throws UnloggedFailure {
+	if (root != null && root.containsKey(commandName)) {
+		return root.get(commandName);
+	}
+	final Class<? extends Command> c = getMap().get(commandName);
+      if (c == null) {
+        String msg =
+            (getName().isEmpty() ? "Gitblit" : getName()) + ": "
+                + commandName + ": not found";
+        throw new UnloggedFailure(1, msg);
+      }
+
+      Command cmd = null;
+      try {
+    	  cmd = c.newInstance();
+      } catch (Exception e) {
+    	  throw new UnloggedFailure(1, MessageFormat.format("Failed to instantiate {0} command", commandName));
+      }
+	return cmd;
+  }
+
+  @Override
   protected String usage() {
     final StringBuilder usage = new StringBuilder();
     usage.append("Available commands");
@@ -127,15 +152,15 @@
     usage.append("\n");
 
     int maxLength = -1;
-    Map<String, Provider<Command>> m = getMap();
+    Map<String, Class<? extends Command>> m = getMap();
     for (String name : m.keySet()) {
       maxLength = Math.max(maxLength, name.length());
     }
     String format = "%-" + maxLength + "s   %s";
     for (String name : Sets.newTreeSet(m.keySet())) {
-      final Provider<Command> p = m.get(name);
+      final Class<? extends Command> c = m.get(name);
       usage.append("   ");
-      CommandMetaData meta = p.get().getClass().getAnnotation(CommandMetaData.class);
+      CommandMetaData meta = c.getAnnotation(CommandMetaData.class);
       if (meta != null) {
         usage.append(String.format(format, name,
             Strings.nullToEmpty(meta.description())));
@@ -153,4 +178,39 @@
     usage.append("\n");
     return usage.toString();
   }
+
+  // This is needed because we are not using provider or
+  // clazz.newInstance() for DispatchCommand
+  private void reset() {
+	  args = new ArrayList<String>();
+  }
+
+  private void provideGitState(Command cmd) {
+	  if (cmd instanceof AbstractGitCommand) {
+		AbstractGitCommand a = (AbstractGitCommand) cmd;
+		a.setRepositoryResolver(repositoryResolver);
+		a.setUploadPackFactory(gitblitUploadPackFactory);
+		a.setReceivePackFactory(gitblitReceivePackFactory);
+	  } else if (cmd instanceof DispatchCommand) {
+		DispatchCommand d = (DispatchCommand)cmd;
+		d.setRepositoryResolver(repositoryResolver);
+		d.setUploadPackFactory(gitblitUploadPackFactory);
+		d.setReceivePackFactory(gitblitReceivePackFactory);
+	  }
+  }
+
+  private RepositoryResolver<SshSession> repositoryResolver;
+  public void setRepositoryResolver(RepositoryResolver<SshSession> repositoryResolver) {
+	  this.repositoryResolver = repositoryResolver;
+  }
+
+  private GitblitUploadPackFactory<SshSession> gitblitUploadPackFactory;
+  public void setUploadPackFactory(GitblitUploadPackFactory<SshSession> gitblitUploadPackFactory) {
+	  this.gitblitUploadPackFactory = gitblitUploadPackFactory;
+  }
+
+  private GitblitReceivePackFactory<SshSession> gitblitReceivePackFactory;
+  public void setReceivePackFactory(GitblitReceivePackFactory<SshSession> gitblitReceivePackFactory) {
+	  this.gitblitReceivePackFactory = gitblitReceivePackFactory;
+  }
 }

--
Gitblit v1.9.1