Use Guice to bring up the SSH daemon and its configuration
We also now create the SSH command objects as request scoped items from the Guice Injector. This permits the commands to obtain any Guice managed object via an injection annotation, making it easier to thread through server state information to the injected command. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
114
src/main/java/com/google/gerrit/server/GerritConfigProvider.java
Normal file
114
src/main/java/com/google/gerrit/server/GerritConfigProvider.java
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright (C) 2009 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.data.GerritConfig;
|
||||
import com.google.gerrit.client.data.GitwebLink;
|
||||
import com.google.gerrit.client.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.ssh.GerritSshDaemon;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.gwtorm.client.SchemaFactory;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.ProvisionException;
|
||||
|
||||
import org.spearce.jgit.lib.RepositoryConfig;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
class GerritConfigProvider implements Provider<GerritConfig> {
|
||||
private static boolean isIPv6(final InetAddress ip) {
|
||||
return ip instanceof Inet6Address
|
||||
&& ip.getHostName().equals(ip.getHostAddress());
|
||||
}
|
||||
|
||||
private final GerritServer server;
|
||||
private final SchemaFactory<ReviewDb> schema;
|
||||
private GerritSshDaemon sshd;
|
||||
|
||||
@Inject
|
||||
GerritConfigProvider(final GerritServer gs) {
|
||||
server = gs;
|
||||
schema = gs.getSchemaFactory();
|
||||
}
|
||||
|
||||
@Inject(optional = true)
|
||||
void setGerritSshDaemon(final GerritSshDaemon d) {
|
||||
sshd = d;
|
||||
}
|
||||
|
||||
private GerritConfig create() throws OrmException {
|
||||
final RepositoryConfig cfg = server.getGerritConfig();
|
||||
final GerritConfig config = new GerritConfig();
|
||||
config.setCanonicalUrl(server.getCanonicalURL());
|
||||
config.setUseContributorAgreements(cfg.getBoolean("auth",
|
||||
"contributoragreements", false));
|
||||
config.setGitDaemonUrl(cfg.getString("gerrit", null, "canonicalgiturl"));
|
||||
config.setUseRepoDownload(cfg.getBoolean("repo", null,
|
||||
"showdownloadcommand", false));
|
||||
config.setUseContactInfo(server.getContactStoreURL() != null);
|
||||
config.setAllowRegisterNewEmail(server.isOutgoingMailEnabled());
|
||||
config.setLoginType(server.getLoginType());
|
||||
|
||||
final String gitwebUrl = cfg.getString("gitweb", null, "url");
|
||||
if (gitwebUrl != null) {
|
||||
config.setGitwebLink(new GitwebLink(gitwebUrl));
|
||||
}
|
||||
|
||||
final ReviewDb db = schema.open();
|
||||
try {
|
||||
for (final ApprovalCategory c : db.approvalCategories().all()) {
|
||||
config.add(new ApprovalType(c, db.approvalCategoryValues().byCategory(
|
||||
c.getId()).toList()));
|
||||
}
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
|
||||
final InetSocketAddress addr = sshd != null ? sshd.getAddress() : null;
|
||||
if (addr != null) {
|
||||
final InetAddress ip = addr.getAddress();
|
||||
String host;
|
||||
if (ip != null && ip.isAnyLocalAddress()) {
|
||||
host = "";
|
||||
} else if (isIPv6(ip)) {
|
||||
host = "[" + addr.getHostName() + "]";
|
||||
} else {
|
||||
host = addr.getHostName();
|
||||
}
|
||||
if (addr.getPort() != 22) {
|
||||
host += ":" + addr.getPort();
|
||||
}
|
||||
config.setSshdAddress(host);
|
||||
}
|
||||
|
||||
Common.setGerritConfig(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GerritConfig get() {
|
||||
try {
|
||||
return create();
|
||||
} catch (OrmException e) {
|
||||
throw new ProvisionException("Cannot construct GerritConfig", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,6 @@
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.data.AccountCache;
|
||||
import com.google.gerrit.client.data.ApprovalType;
|
||||
import com.google.gerrit.client.data.GerritConfig;
|
||||
import com.google.gerrit.client.data.GitwebLink;
|
||||
import com.google.gerrit.client.data.GroupCache;
|
||||
import com.google.gerrit.client.data.ProjectCache;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
@@ -247,13 +244,6 @@ public class GerritServer {
|
||||
basepath = null;
|
||||
}
|
||||
|
||||
final ReviewDb c = db.open();
|
||||
try {
|
||||
loadGerritConfig(c);
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
|
||||
Common.setSchemaFactory(db);
|
||||
Common.setProjectCache(new ProjectCache());
|
||||
Common.setAccountCache(new AccountCache());
|
||||
@@ -694,32 +684,6 @@ public class GerritServer {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadGerritConfig(final ReviewDb db) throws OrmException {
|
||||
final GerritConfig r = new GerritConfig();
|
||||
r.setCanonicalUrl(getCanonicalURL());
|
||||
r.setUseContributorAgreements(getGerritConfig().getBoolean("auth",
|
||||
"contributoragreements", false));
|
||||
r.setGitDaemonUrl(getGerritConfig().getString("gerrit", null,
|
||||
"canonicalgiturl"));
|
||||
r.setUseRepoDownload(getGerritConfig().getBoolean("repo", null,
|
||||
"showdownloadcommand", false));
|
||||
r.setUseContactInfo(getContactStoreURL() != null);
|
||||
r.setAllowRegisterNewEmail(isOutgoingMailEnabled());
|
||||
r.setLoginType(getLoginType());
|
||||
|
||||
final String gitwebUrl = getGerritConfig().getString("gitweb", null, "url");
|
||||
if (gitwebUrl != null) {
|
||||
r.setGitwebLink(new GitwebLink(gitwebUrl));
|
||||
}
|
||||
|
||||
for (final ApprovalCategory c : db.approvalCategories().all()) {
|
||||
r.add(new ApprovalType(c, db.approvalCategoryValues().byCategory(
|
||||
c.getId()).toList()));
|
||||
}
|
||||
|
||||
Common.setGerritConfig(r);
|
||||
}
|
||||
|
||||
public boolean isOutgoingMailEnabled() {
|
||||
return getGerritConfig().getBoolean("sendemail", null, "enable", true);
|
||||
}
|
||||
@@ -829,7 +793,7 @@ public class GerritServer {
|
||||
return emailReg;
|
||||
}
|
||||
|
||||
private SystemConfig.LoginType getLoginType() {
|
||||
public SystemConfig.LoginType getLoginType() {
|
||||
String type = getGerritConfig().getString("auth", null, "type");
|
||||
if (type == null) {
|
||||
return SystemConfig.LoginType.OPENID;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2009 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.data.GerritConfig;
|
||||
import com.google.gwtjsonrpc.server.XsrfException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Scopes;
|
||||
|
||||
/** Starts {@link GerritServer} with standard dependencies. */
|
||||
public class GerritServerModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
try {
|
||||
bind(GerritServer.class).toInstance(GerritServer.getInstance(true));
|
||||
} catch (OrmException e) {
|
||||
addError(e);
|
||||
} catch (XsrfException e) {
|
||||
addError(e);
|
||||
}
|
||||
|
||||
bind(ContactStore.class).toProvider(EncryptedContactStoreProvider.class);
|
||||
bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
|
||||
bind(GerritConfig.class).toProvider(GerritConfigProvider.class).in(
|
||||
Scopes.SINGLETON);
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,11 @@ package com.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.git.WorkQueue;
|
||||
import com.google.gerrit.server.patch.PatchDetailServiceImpl;
|
||||
import com.google.gerrit.server.ssh.GerritSshDaemon;
|
||||
import com.google.gerrit.server.ssh.SshDaemonModule;
|
||||
import com.google.gerrit.server.ssh.SshServlet;
|
||||
import com.google.gwtexpui.server.CacheControlFilter;
|
||||
import com.google.gwtjsonrpc.client.RemoteJsonService;
|
||||
import com.google.gwtjsonrpc.server.XsrfException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.BindingAnnotation;
|
||||
import com.google.inject.ConfigurationException;
|
||||
import com.google.inject.Guice;
|
||||
@@ -32,6 +31,7 @@ import com.google.inject.Scopes;
|
||||
import com.google.inject.servlet.GuiceServletContextListener;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -123,27 +123,10 @@ public class GerritServletConfig extends GuiceServletContextListener {
|
||||
};
|
||||
}
|
||||
|
||||
private static Module createDatabaseModule() {
|
||||
return new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
try {
|
||||
bind(GerritServer.class).toInstance(GerritServer.getInstance(true));
|
||||
} catch (OrmException e) {
|
||||
addError(e);
|
||||
} catch (XsrfException e) {
|
||||
addError(e);
|
||||
}
|
||||
|
||||
bind(ContactStore.class)
|
||||
.toProvider(EncryptedContactStoreProvider.class);
|
||||
bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final Injector injector =
|
||||
Guice.createInjector(createDatabaseModule(), createServletModule());
|
||||
Guice.createInjector(createServletModule(),
|
||||
new GerritServerModule(),
|
||||
new SshDaemonModule());
|
||||
|
||||
@Override
|
||||
protected Injector getInjector() {
|
||||
@@ -153,12 +136,30 @@ public class GerritServletConfig extends GuiceServletContextListener {
|
||||
@Override
|
||||
public void contextInitialized(final ServletContextEvent event) {
|
||||
super.contextInitialized(event);
|
||||
|
||||
try {
|
||||
injector.getInstance(GerritSshDaemon.class).start();
|
||||
} catch (ConfigurationException e) {
|
||||
event.getServletContext().log("Unable to start SSHD", e);
|
||||
} catch (ProviderException e) {
|
||||
event.getServletContext().log("Unable to start SSHD", e);
|
||||
} catch (IOException e) {
|
||||
event.getServletContext().log("Unable to start SSHD", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(final ServletContextEvent event) {
|
||||
try {
|
||||
final GerritServer gs = injector.getInstance(Key.get(GerritServer.class));
|
||||
injector.getInstance(GerritSshDaemon.class).stop();
|
||||
} catch (ConfigurationException e) {
|
||||
// Assume it never started.
|
||||
} catch (ProviderException e) {
|
||||
// Assume it never started.
|
||||
}
|
||||
|
||||
try {
|
||||
final GerritServer gs = injector.getInstance(GerritServer.class);
|
||||
gs.closeDataSource();
|
||||
} catch (ConfigurationException ce) {
|
||||
// Assume it never started.
|
||||
|
||||
@@ -44,13 +44,16 @@ import javax.servlet.http.HttpServletResponse;
|
||||
@Singleton
|
||||
public class HostPageServlet extends HttpServlet {
|
||||
private final GerritServer server;
|
||||
private final GerritConfig config;
|
||||
|
||||
private String canonicalUrl;
|
||||
private boolean wantSSL;
|
||||
private Document hostDoc;
|
||||
|
||||
@Inject
|
||||
HostPageServlet(final GerritServer gs) {
|
||||
HostPageServlet(final GerritServer gs, final GerritConfig gc) {
|
||||
server = gs;
|
||||
config = gc;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,7 +222,6 @@ public class HostPageServlet extends HttpServlet {
|
||||
|
||||
final Account.Id me = new GerritCall(server, req, rsp).getAccountId();
|
||||
final Account account = Common.getAccountCache().get(me);
|
||||
final GerritConfig config = SystemInfoServiceImpl.getGerritConfig();
|
||||
|
||||
final Document peruser = HtmlDomUtil.clone(hostDoc);
|
||||
injectJson(peruser, "gerrit_gerritconfig", config);
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.google.gerrit.client.data.SshHostKey;
|
||||
import com.google.gerrit.client.data.SystemInfoService;
|
||||
import com.google.gerrit.client.reviewdb.ContributorAgreement;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.ssh.GerritSshDaemon;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
@@ -53,35 +52,17 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
private static final JSch JSCH = new JSch();
|
||||
|
||||
private final GerritServer server;
|
||||
private final GerritSshDaemon sshd;
|
||||
private final GerritConfig config;
|
||||
private final List<PublicKey> hostKeys;
|
||||
|
||||
@Inject
|
||||
SystemInfoServiceImpl(final GerritServer gs) {
|
||||
SystemInfoServiceImpl(final GerritServer gs, final GerritSshDaemon daemon,
|
||||
final GerritConfig gc) {
|
||||
server = gs;
|
||||
}
|
||||
|
||||
public static GerritConfig getGerritConfig() {
|
||||
final GerritConfig cfg = Common.getGerritConfig();
|
||||
synchronized (cfg) {
|
||||
if (cfg.getSshdAddress() == null) {
|
||||
final InetSocketAddress addr = GerritSshDaemon.getAddress();
|
||||
if (addr != null) {
|
||||
final InetAddress ip = addr.getAddress();
|
||||
String host;
|
||||
if (ip != null && ip.isAnyLocalAddress()) {
|
||||
host = "";
|
||||
} else if (isIPv6(ip)) {
|
||||
host = "[" + addr.getHostName() + "]";
|
||||
} else {
|
||||
host = addr.getHostName();
|
||||
}
|
||||
if (addr.getPort() != 22) {
|
||||
host += ":" + addr.getPort();
|
||||
}
|
||||
cfg.setSshdAddress(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cfg;
|
||||
sshd = daemon;
|
||||
config = gc;
|
||||
hostKeys = sortHostKeys();
|
||||
}
|
||||
|
||||
private static boolean isIPv6(final InetAddress ip) {
|
||||
@@ -90,7 +71,7 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
}
|
||||
|
||||
public void loadGerritConfig(final AsyncCallback<GerritConfig> callback) {
|
||||
callback.onSuccess(getGerritConfig());
|
||||
callback.onSuccess(config);
|
||||
}
|
||||
|
||||
public void contributorAgreements(
|
||||
@@ -109,9 +90,8 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
|
||||
public void daemonHostKeys(final AsyncCallback<List<SshHostKey>> callback) {
|
||||
final String hostIdent = hostIdent();
|
||||
final List<PublicKey> keys = sortKeys();
|
||||
final ArrayList<SshHostKey> r = new ArrayList<SshHostKey>(keys.size());
|
||||
for (final PublicKey pub : keys) {
|
||||
final ArrayList<SshHostKey> r = new ArrayList<SshHostKey>(hostKeys.size());
|
||||
for (final PublicKey pub : hostKeys) {
|
||||
try {
|
||||
final HostKey hk = toHostKey(hostIdent, pub);
|
||||
r.add(new SshHostKey(hk.getHost(), hk.getType() + " " + hk.getKey(), hk
|
||||
@@ -124,9 +104,9 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
callback.onSuccess(r);
|
||||
}
|
||||
|
||||
private static List<PublicKey> sortKeys() {
|
||||
private List<PublicKey> sortHostKeys() {
|
||||
final List<PublicKey> r = new ArrayList<PublicKey>(2);
|
||||
r.addAll(GerritSshDaemon.getHostKeys());
|
||||
r.addAll(sshd.getHostKeys());
|
||||
Collections.sort(r, new Comparator<PublicKey>() {
|
||||
@Override
|
||||
public int compare(final PublicKey a, final PublicKey b) {
|
||||
@@ -142,7 +122,7 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
return r;
|
||||
return Collections.unmodifiableList(r);
|
||||
}
|
||||
|
||||
private HostKey toHostKey(final String hostIdent, final PublicKey pub)
|
||||
@@ -157,7 +137,7 @@ class SystemInfoServiceImpl implements SystemInfoService {
|
||||
final HttpServletRequest req =
|
||||
GerritJsonServlet.getCurrentCall().getHttpServletRequest();
|
||||
|
||||
InetSocketAddress addr = GerritSshDaemon.getAddress();
|
||||
InetSocketAddress addr = sshd.getAddress();
|
||||
InetAddress ip = addr.getAddress();
|
||||
if (ip.isAnyLocalAddress()) {
|
||||
try {
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.gerrit.server.BaseServiceImplementation;
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
|
||||
import org.apache.sshd.common.SshException;
|
||||
import org.apache.sshd.server.CommandFactory.Command;
|
||||
@@ -48,6 +50,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/** Basic command implementation invoked by {@link GerritCommandFactory}. */
|
||||
@RequestScoped
|
||||
abstract class AbstractCommand implements Command, SessionAware {
|
||||
private static final String ENC = "UTF-8";
|
||||
|
||||
@@ -59,7 +62,8 @@ abstract class AbstractCommand implements Command, SessionAware {
|
||||
protected OutputStream err;
|
||||
protected ExitCallback exit;
|
||||
protected ServerSession session;
|
||||
protected GerritServer server;
|
||||
@Inject
|
||||
protected GerritServer server;
|
||||
protected ReviewDb db;
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -16,6 +16,7 @@ package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.rpc.Common;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@@ -41,14 +42,17 @@ class AdminShowConnections extends AbstractCommand {
|
||||
|
||||
PrintWriter p;
|
||||
|
||||
@Inject
|
||||
private GerritSshDaemon daemon;
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure, UnsupportedEncodingException {
|
||||
assertIsAdministrator();
|
||||
p = toPrintWriter(out);
|
||||
|
||||
final IoAcceptor acceptor = GerritSshDaemon.getIoAcceptor();
|
||||
final IoAcceptor acceptor = daemon.getIoAcceptor();
|
||||
if (acceptor == null) {
|
||||
throw new Failure(1, "fatal: sshd not running");
|
||||
throw new Failure(1, "fatal: sshd no longer running");
|
||||
}
|
||||
|
||||
final List<IoSession> list =
|
||||
|
||||
@@ -14,66 +14,43 @@
|
||||
|
||||
package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.sshd.server.CommandFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/** Creates a command implementation based on the client input. */
|
||||
class GerritCommandFactory implements CommandFactory {
|
||||
private final GerritServer server;
|
||||
private final HashMap<String, Factory> commands;
|
||||
@Singleton
|
||||
public class GerritCommandFactory implements CommandFactory {
|
||||
private final Injector injector;
|
||||
private final HashMap<String, Provider<? extends AbstractCommand>> commands;
|
||||
|
||||
GerritCommandFactory(final GerritServer gs) {
|
||||
server = gs;
|
||||
commands = new HashMap<String, Factory>();
|
||||
@Inject
|
||||
GerritCommandFactory(final Injector i) {
|
||||
injector = i;
|
||||
commands = new HashMap<String, Provider<? extends AbstractCommand>>();
|
||||
|
||||
commands.put("gerrit-upload-pack", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new Upload();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-receive-pack", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new Receive();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-flush-caches", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new AdminFlushCaches();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-ls-projects", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new ListProjects();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-show-caches", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new AdminShowCaches();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-show-connections", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new AdminShowConnections();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-show-queue", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new AdminShowQueue();
|
||||
}
|
||||
});
|
||||
commands.put("gerrit-replicate", new Factory() {
|
||||
public AbstractCommand create() {
|
||||
return new AdminReplicate();
|
||||
}
|
||||
});
|
||||
bind("gerrit-upload-pack", Upload.class);
|
||||
bind("gerrit-receive-pack", Receive.class);
|
||||
bind("gerrit-flush-caches", AdminFlushCaches.class);
|
||||
bind("gerrit-ls-projects", ListProjects.class);
|
||||
bind("gerrit-show-caches", AdminShowCaches.class);
|
||||
bind("gerrit-show-connections", AdminShowConnections.class);
|
||||
bind("gerrit-show-queue", AdminShowQueue.class);
|
||||
bind("gerrit-replicate", AdminReplicate.class);
|
||||
|
||||
alias("gerrit-upload-pack", "git-upload-pack");
|
||||
alias("gerrit-receive-pack", "git-receive-pack");
|
||||
}
|
||||
|
||||
private void bind(final String cmd, final Class<? extends AbstractCommand> imp) {
|
||||
commands.put(cmd, injector.getProvider(imp));
|
||||
}
|
||||
|
||||
private void alias(final String from, final String to) {
|
||||
commands.put(to, commands.get(from));
|
||||
}
|
||||
@@ -107,15 +84,14 @@ class GerritCommandFactory implements CommandFactory {
|
||||
}
|
||||
|
||||
final AbstractCommand c = create(cmd);
|
||||
c.server = server;
|
||||
c.setCommandLine(cmd, args);
|
||||
return c;
|
||||
}
|
||||
|
||||
private AbstractCommand create(final String cmd) {
|
||||
final Factory f = commands.get(cmd);
|
||||
final Provider<? extends AbstractCommand> f = commands.get(cmd);
|
||||
if (f != null) {
|
||||
return f.create();
|
||||
return f.get();
|
||||
}
|
||||
return new AbstractCommand() {
|
||||
@Override
|
||||
@@ -124,8 +100,4 @@ class GerritCommandFactory implements CommandFactory {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected static interface Factory {
|
||||
AbstractCommand create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.gerrit.server.GerritServer;
|
||||
import com.google.gwtjsonrpc.server.XsrfException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@@ -48,6 +48,7 @@ import org.apache.sshd.common.session.AbstractSession;
|
||||
import org.apache.sshd.common.signature.SignatureDSA;
|
||||
import org.apache.sshd.common.signature.SignatureRSA;
|
||||
import org.apache.sshd.common.util.SecurityUtils;
|
||||
import org.apache.sshd.server.CommandFactory;
|
||||
import org.apache.sshd.server.ServerChannel;
|
||||
import org.apache.sshd.server.SessionFactory;
|
||||
import org.apache.sshd.server.UserAuth;
|
||||
@@ -65,7 +66,6 @@ import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
@@ -95,62 +95,13 @@ import java.util.List;
|
||||
* Port 8010
|
||||
* </pre>
|
||||
*/
|
||||
@Singleton
|
||||
public class GerritSshDaemon extends SshServer {
|
||||
private static final int DEFAULT_PORT = 29418;
|
||||
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(GerritSshDaemon.class);
|
||||
|
||||
private static GerritSshDaemon sshd;
|
||||
private static InetSocketAddress preferredAddress;
|
||||
private static Collection<PublicKey> hostKeys = Collections.emptyList();
|
||||
|
||||
public static synchronized void startSshd() throws OrmException,
|
||||
XsrfException, SocketException {
|
||||
final GerritServer srv = GerritServer.getInstance();
|
||||
final GerritSshDaemon daemon = new GerritSshDaemon(srv);
|
||||
final String addressList = daemon.addressList();
|
||||
try {
|
||||
sshd = daemon;
|
||||
preferredAddress = null;
|
||||
hostKeys = computeHostKeys();
|
||||
|
||||
if (hostKeys.isEmpty()) {
|
||||
throw new IOException("No SSHD host key");
|
||||
}
|
||||
daemon.start();
|
||||
|
||||
log.info("Started Gerrit SSHD on " + addressList);
|
||||
} catch (IOException e) {
|
||||
sshd = null;
|
||||
preferredAddress = null;
|
||||
hostKeys = Collections.emptyList();
|
||||
|
||||
final String msg = "Cannot start Gerrit SSHD on " + addressList;
|
||||
log.error(msg, e);
|
||||
final SocketException e2;
|
||||
e2 = new SocketException(msg);
|
||||
e2.initCause(e);
|
||||
throw e2;
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<PublicKey> computeHostKeys() {
|
||||
final KeyPairProvider p = sshd.getKeyPairProvider();
|
||||
final List<PublicKey> keys = new ArrayList<PublicKey>(2);
|
||||
addPublicKey(keys, p, KeyPairProvider.SSH_DSS);
|
||||
addPublicKey(keys, p, KeyPairProvider.SSH_RSA);
|
||||
return Collections.unmodifiableList(keys);
|
||||
}
|
||||
|
||||
private static void addPublicKey(final Collection<PublicKey> out,
|
||||
final KeyPairProvider p, final String type) {
|
||||
final KeyPair pair = p.loadKey(type);
|
||||
if (pair != null && pair.getPublic() != null) {
|
||||
out.add(pair.getPublic());
|
||||
}
|
||||
}
|
||||
|
||||
private static String format(final SocketAddress addr) {
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
final InetSocketAddress inetAddr = (InetSocketAddress) addr;
|
||||
@@ -166,55 +117,16 @@ public class GerritSshDaemon extends SshServer {
|
||||
return addr.toString();
|
||||
}
|
||||
|
||||
public static synchronized void stopSshd() {
|
||||
if (sshd != null) {
|
||||
try {
|
||||
sshd.stop();
|
||||
log.info("Stopped Gerrit SSHD");
|
||||
} finally {
|
||||
sshd = null;
|
||||
preferredAddress = null;
|
||||
hostKeys = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
private final List<SocketAddress> listen;
|
||||
private final InetSocketAddress preferredAddress;
|
||||
private final boolean reuseAddress;
|
||||
private final boolean keepAlive;
|
||||
private final Collection<PublicKey> hostKeys;
|
||||
private volatile IoAcceptor acceptor;
|
||||
|
||||
public static synchronized IoAcceptor getIoAcceptor() {
|
||||
return sshd != null ? sshd.acceptor : null;
|
||||
}
|
||||
|
||||
public static synchronized Collection<PublicKey> getHostKeys() {
|
||||
return hostKeys;
|
||||
}
|
||||
|
||||
public static synchronized InetSocketAddress getAddress() {
|
||||
if (sshd != null && preferredAddress == null) {
|
||||
preferredAddress = computePreferredAddress();
|
||||
}
|
||||
return preferredAddress;
|
||||
}
|
||||
|
||||
private static InetSocketAddress computePreferredAddress() {
|
||||
for (final SocketAddress addr : sshd.listen) {
|
||||
if (!(addr instanceof InetSocketAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InetSocketAddress inetAddr = (InetSocketAddress) addr;
|
||||
if (inetAddr.getAddress().isLoopbackAddress()) {
|
||||
continue;
|
||||
}
|
||||
return inetAddr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<SocketAddress> listen;
|
||||
private IoAcceptor acceptor;
|
||||
private boolean reuseAddress;
|
||||
private boolean keepAlive;
|
||||
|
||||
private GerritSshDaemon(final GerritServer srv) {
|
||||
@Inject
|
||||
public GerritSshDaemon(final GerritServer srv,
|
||||
final CommandFactory commandFactory) {
|
||||
setPort(22/* never used */);
|
||||
|
||||
final RepositoryConfig cfg = srv.getGerritConfig();
|
||||
@@ -234,7 +146,7 @@ public class GerritSshDaemon extends SshServer {
|
||||
initCompression();
|
||||
initUserAuth(srv);
|
||||
setKeyPairProvider(initHostKey(srv));
|
||||
setCommandFactory(new GerritCommandFactory(srv));
|
||||
setCommandFactory(commandFactory);
|
||||
setShellFactory(new NoShell());
|
||||
setSessionFactory(new SessionFactory() {
|
||||
@Override
|
||||
@@ -251,12 +163,30 @@ public class GerritSshDaemon extends SshServer {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
|
||||
hostKeys = computeHostKeys();
|
||||
preferredAddress = computePreferredAddress();
|
||||
}
|
||||
|
||||
public Collection<PublicKey> getHostKeys() {
|
||||
return hostKeys;
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return preferredAddress;
|
||||
}
|
||||
|
||||
public IoAcceptor getIoAcceptor() {
|
||||
return acceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
public synchronized void start() throws IOException {
|
||||
if (acceptor == null) {
|
||||
checkConfig();
|
||||
if (hostKeys.isEmpty()) {
|
||||
throw new IOException("No SSHD host key");
|
||||
}
|
||||
|
||||
final NioSocketAcceptor ain = new NioSocketAcceptor();
|
||||
final SessionFactory handler = getSessionFactory();
|
||||
@@ -265,20 +195,54 @@ public class GerritSshDaemon extends SshServer {
|
||||
ain.setReuseAddress(reuseAddress);
|
||||
ain.bind(listen);
|
||||
acceptor = ain;
|
||||
|
||||
log.info("Started Gerrit SSHD on " + addressList());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
public synchronized void stop() {
|
||||
if (acceptor != null) {
|
||||
try {
|
||||
acceptor.dispose();
|
||||
log.info("Stopped Gerrit SSHD");
|
||||
} finally {
|
||||
acceptor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<PublicKey> computeHostKeys() {
|
||||
final KeyPairProvider p = getKeyPairProvider();
|
||||
final List<PublicKey> keys = new ArrayList<PublicKey>(2);
|
||||
addPublicKey(keys, p, KeyPairProvider.SSH_DSS);
|
||||
addPublicKey(keys, p, KeyPairProvider.SSH_RSA);
|
||||
return Collections.unmodifiableList(keys);
|
||||
}
|
||||
|
||||
private static void addPublicKey(final Collection<PublicKey> out,
|
||||
final KeyPairProvider p, final String type) {
|
||||
final KeyPair pair = p.loadKey(type);
|
||||
if (pair != null && pair.getPublic() != null) {
|
||||
out.add(pair.getPublic());
|
||||
}
|
||||
}
|
||||
|
||||
private InetSocketAddress computePreferredAddress() {
|
||||
for (final SocketAddress addr : listen) {
|
||||
if (!(addr instanceof InetSocketAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InetSocketAddress inetAddr = (InetSocketAddress) addr;
|
||||
if (inetAddr.getAddress().isLoopbackAddress()) {
|
||||
continue;
|
||||
}
|
||||
return inetAddr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String addressList() {
|
||||
final StringBuilder r = new StringBuilder();
|
||||
for (Iterator<SocketAddress> i = listen.iterator(); i.hasNext();) {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2009 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
import org.apache.sshd.server.CommandFactory;
|
||||
|
||||
/** Configures standard dependencies for {@link GerritSshDaemon}. */
|
||||
public class SshDaemonModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(GerritSshDaemon.class);
|
||||
bind(CommandFactory.class).to(GerritCommandFactory.class);
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,7 @@
|
||||
|
||||
package com.google.gerrit.server.ssh;
|
||||
|
||||
import com.google.gwtjsonrpc.server.XsrfException;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -23,10 +22,7 @@ import java.io.PrintWriter;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -53,24 +49,11 @@ import javax.servlet.http.HttpServletResponse;
|
||||
@SuppressWarnings("serial")
|
||||
@Singleton
|
||||
public class SshServlet extends HttpServlet {
|
||||
@Override
|
||||
public void init(final ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
try {
|
||||
GerritSshDaemon.startSshd();
|
||||
} catch (SocketException e) {
|
||||
throw new ServletException(e);
|
||||
} catch (OrmException e) {
|
||||
throw new ServletException(e);
|
||||
} catch (XsrfException e) {
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
private final GerritSshDaemon sshd;
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
GerritSshDaemon.stopSshd();
|
||||
super.destroy();
|
||||
@Inject
|
||||
SshServlet(final GerritSshDaemon daemon) {
|
||||
sshd = daemon;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,7 +63,7 @@ public class SshServlet extends HttpServlet {
|
||||
rsp.setHeader("Pragma", "no-cache");
|
||||
rsp.setHeader("Cache-Control", "no-cache, must-revalidate");
|
||||
|
||||
final InetSocketAddress addr = GerritSshDaemon.getAddress();
|
||||
final InetSocketAddress addr = sshd.getAddress();
|
||||
final String out;
|
||||
if (addr != null) {
|
||||
final InetAddress ip = addr.getAddress();
|
||||
|
||||
Reference in New Issue
Block a user