Use Guice to create custom arg4j OptionHandler instances

This permits us to inject Guice managed objects into any ObjectHandler
via assisted factory injection, which permits them to perform database
queries during option parsing by accessing the per-request ReviewDb.

Change-Id: I14a6b5296d8d77b5e3966846bbaa58f6e8ebb09a
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-08-28 16:11:13 -07:00
parent 0c2143054c
commit e590be9e6d
8 changed files with 196 additions and 14 deletions

View File

@@ -54,6 +54,9 @@ public abstract class BaseCommand implements Command {
private ExitCallback exit;
@Inject
private CmdLineParser.Factory cmdLineParserFactory;
@Inject
private RequestCleanup cleanup;
@@ -180,7 +183,7 @@ public abstract class BaseCommand implements Command {
/** Construct a new parser for this command's received command line. */
protected CmdLineParser newCmdLineParser() {
return new CmdLineParser(this);
return cmdLineParserFactory.create(this);
}
/**

View File

@@ -16,13 +16,21 @@ package com.google.gerrit.server.ssh;
import static com.google.inject.Scopes.SINGLETON;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.pgm.CmdLineParser;
import com.google.gerrit.pgm.OptionHandlerFactory;
import com.google.gerrit.pgm.OptionHandlerUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.RemotePeer;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.GerritRequestModule;
import com.google.gerrit.server.ssh.commands.DefaultCommandModule;
import com.google.gerrit.server.ssh.commands.PatchSetIdHandler;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.SessionScoped;
@@ -31,6 +39,7 @@ import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSession;
import org.kohsuke.args4j.spi.OptionHandler;
import java.net.SocketAddress;
@@ -45,6 +54,7 @@ public class SshModule extends FactoryModule {
configureSessionScope();
configureRequestScope();
configureCmdLineParser();
bind(SshInfo.class).to(SshDaemon.class).in(SINGLETON);
factory(DispatchCommand.Factory.class);
@@ -85,4 +95,23 @@ public class SshModule extends FactoryModule {
SshScopes.REQUEST);
bind(CurrentUser.class).to(IdentifiedUser.class);
}
private void configureCmdLineParser() {
factory(CmdLineParser.Factory.class);
registerOptionHandler(PatchSet.Id.class, PatchSetIdHandler.class);
}
private <T> void registerOptionHandler(Class<T> type,
Class<? extends OptionHandler<T>> impl) {
final Key<OptionHandlerFactory<T>> key = OptionHandlerUtil.keyFor(type);
final TypeLiteral<OptionHandlerFactory<T>> factoryType =
new TypeLiteral<OptionHandlerFactory<T>>() {};
final TypeLiteral<? extends OptionHandler<T>> implType =
TypeLiteral.get(impl);
bind(key).toProvider(FactoryProvider.newFactory(factoryType, implType));
}
}

View File

@@ -46,13 +46,9 @@ import java.util.Collections;
import java.util.List;
public class ApproveCommand extends BaseCommand {
static {
CmdLineParser.registerHandler(PatchSet.Id.class, PatchSetIdHandler.class);
}
@Override
protected final CmdLineParser newCmdLineParser() {
final CmdLineParser parser = new CmdLineParser(this);
final CmdLineParser parser = super.newCmdLineParser();
for (CmdOption c : optionList) {
parser.addOption(c, c);
}

View File

@@ -15,6 +15,8 @@
package com.google.gerrit.server.ssh.commands;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
@@ -24,8 +26,10 @@ import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
public class PatchSetIdHandler extends OptionHandler<PatchSet.Id> {
public PatchSetIdHandler(final CmdLineParser parser, final OptionDef option,
final Setter<? super PatchSet.Id> setter) {
@SuppressWarnings("unchecked")
@Inject
public PatchSetIdHandler(@Assisted final CmdLineParser parser,
@Assisted final OptionDef option, @Assisted final Setter setter) {
super(parser, option, setter);
}