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