Browse Source

Extract services manager into a top-level injectable manager

tags/v1.7.0
James Moger 10 years ago
parent
commit
7d3a31514a

+ 0
- 181
src/main/java/com/gitblit/GitBlit.java View File

@@ -25,10 +25,7 @@ import java.util.List;
import java.util.Set;

import com.google.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;
@@ -39,9 +36,7 @@ import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.manager.ServicesManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.NullTicketService;
@@ -62,8 +57,6 @@ public class GitBlit extends GitblitManager {

private final Injector injector;

private final ServicesManager servicesManager;

private ITicketService ticketService;

@Inject
@@ -89,15 +82,11 @@ public class GitBlit extends GitblitManager {
federationManager);

this.injector = Guice.createInjector(getModules());

this.servicesManager = new ServicesManager(this);
}

@Override
public GitBlit start() {
super.start();
logger.info("Starting services manager...");
servicesManager.start();
configureTicketService();
return this;
}
@@ -105,184 +94,14 @@ public class GitBlit extends GitblitManager {
@Override
public GitBlit stop() {
super.stop();
servicesManager.stop();
ticketService.stop();
return this;
}

@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);
}

/**
* Returns a list of repository URLs and the user access permission.
*
* @param request
* @param user
* @param repository
* @return a list of repository urls
*/
@Override
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
if (user == null) {
user = UserModel.ANONYMOUS;
}
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);

List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();

// http/https url
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));
}
}

// ssh daemon url
String sshDaemonUrl = servicesManager.getSshDaemonUrl(request, user, repository);
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));
}
}

// git daemon url
String gitDaemonUrl = servicesManager.getGitDaemonUrl(request, user, repository);
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));
}
}

// add all other urls
// {0} = repository
// {1} = username
for (String url : settings.getStrings(Keys.web.otherUrls)) {
if (url.contains("{1}")) {
// external url requires username, only add url IF we have one
if (!StringUtils.isEmpty(username)) {
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
}
} else {
// external url does not require username
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;
}

/**
* Detect renames and reindex as appropriate.
*/

+ 9
- 0
src/main/java/com/gitblit/guice/CoreModule.java View File

@@ -31,18 +31,21 @@ import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IServicesManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.manager.NotificationManager;
import com.gitblit.manager.PluginManager;
import com.gitblit.manager.ProjectManager;
import com.gitblit.manager.RepositoryManager;
import com.gitblit.manager.RuntimeManager;
import com.gitblit.manager.ServicesManager;
import com.gitblit.manager.UserManager;
import com.gitblit.transport.ssh.FileKeyManager;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.MemoryKeyManager;
import com.gitblit.transport.ssh.NullKeyManager;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.WorkQueue;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;

@@ -59,6 +62,9 @@ public class CoreModule extends AbstractModule {

bind(IStoredSettings.class).toInstance(new FileSettings());

// bind complex providers
bind(WorkQueue.class).toProvider(WorkQueueProvider.class);
// core managers
bind(IRuntimeManager.class).to(RuntimeManager.class).in(Singleton.class);
bind(IPluginManager.class).to(PluginManager.class).in(Singleton.class);
@@ -71,6 +77,9 @@ public class CoreModule extends AbstractModule {

// the monolithic manager
bind(IGitblit.class).to(GitBlit.class).in(Singleton.class);

// manager for long-running daemons and services
bind(IServicesManager.class).to(ServicesManager.class);
}

@Provides

+ 57
- 0
src/main/java/com/gitblit/guice/WorkQueueProvider.java View File

@@ -0,0 +1,57 @@
/*
* Copyright 2014 gitblit.com.
*
* 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.gitblit.guice;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.utils.IdGenerator;
import com.gitblit.utils.WorkQueue;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

/**
* Provides a lazily-instantiated WorkQueue configured from IStoredSettings.
*
* @author James Moger
*
*/
@Singleton
public class WorkQueueProvider implements Provider<WorkQueue> {

private final IRuntimeManager runtimeManager;

private volatile WorkQueue workQueue;

@Inject
public WorkQueueProvider(IRuntimeManager runtimeManager) {
this.runtimeManager = runtimeManager;
}

@Override
public synchronized WorkQueue get() {
if (workQueue != null) {
return workQueue;
}

IStoredSettings settings = runtimeManager.getSettings();
int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1);
IdGenerator idGenerator = new IdGenerator();
workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize);
return workQueue;
}
}

+ 0
- 84
src/main/java/com/gitblit/manager/GitblitManager.java View File

@@ -49,12 +49,10 @@ import ro.fortsoft.pf4j.Version;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.GitBlitException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -68,7 +66,6 @@ import com.gitblit.models.PluginRegistry.PluginRelease;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.SearchResult;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
@@ -79,7 +76,6 @@ import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.SshKey;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.JsonUtils;
import com.gitblit.utils.ObjectCache;
import com.gitblit.utils.StringUtils;
@@ -350,66 +346,6 @@ public class GitblitManager implements IGitblit {
}
}

/**
* Returns a list of repository URLs and the user access permission.
*
* @param request
* @param user
* @param repository
* @return a list of repository urls
*/
@Override
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
if (user == null) {
user = UserModel.ANONYMOUS;
}
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);

List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();
// http/https url
if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
AccessPermission permission = user.getRepositoryPermission(repository).permission;
if (permission.exceeds(AccessPermission.NONE)) {
list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission));
}
}

// add all other urls
// {0} = repository
// {1} = username
for (String url : settings.getStrings(Keys.web.otherUrls)) {
if (url.contains("{1}")) {
// external url requires username, only add url IF we have one
if (!StringUtils.isEmpty(username)) {
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
}
} else {
// external url does not require username
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null));
}
}
return list;
}

protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) {
String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
if (StringUtils.isEmpty(gitblitUrl)) {
gitblitUrl = HttpUtils.getGitblitURL(request);
}
StringBuilder sb = new StringBuilder();
sb.append(gitblitUrl);
sb.append(Constants.R_PATH);
sb.append(repository.name);

// inject username into repository url if authentication is required
if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
&& !StringUtils.isEmpty(username)) {
sb.insert(sb.indexOf("://") + 3, username + "@");
}
return sb.toString();
}


/**
* Returns the list of custom client applications to be used for the
* repository url panel;
@@ -597,26 +533,6 @@ public class GitblitManager implements IGitblit {
return runtimeManager.getSettingsModel();
}

@Override
public boolean isServingRepositories() {
return runtimeManager.isServingRepositories();
}

@Override
public boolean isServingHTTP() {
return runtimeManager.isServingHTTP();
}

@Override
public boolean isServingGIT() {
return runtimeManager.isServingGIT();
}

@Override
public boolean isServingSSH() {
return runtimeManager.isServingSSH();
}

@Override
public TimeZone getTimezone() {
return runtimeManager.getTimezone();

+ 0
- 15
src/main/java/com/gitblit/manager/IGitblit.java View File

@@ -16,14 +16,10 @@
package com.gitblit.manager;

import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.gitblit.GitBlitException;
import com.gitblit.models.GitClientApplication;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.ITicketService;
@@ -39,17 +35,6 @@ public interface IGitblit extends IManager,
IProjectManager,
IFederationManager {

/**
* Returns a list of repository URLs and the user access permission.
*
* @param request
* @param user
* @param repository
* @return a list of repository urls
* @since 1.4.0
*/
List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository);

/**
* Creates a complete user object.
*

+ 0
- 36
src/main/java/com/gitblit/manager/IRuntimeManager.java View File

@@ -50,42 +50,6 @@ public interface IRuntimeManager extends IManager {
*/
Locale getLocale();

/**
* Determine if this Gitblit instance is actively serving git repositories
* or if it is merely a repository viewer.
*
* @return true if Gitblit is serving repositories
* @since 1.4.0
*/
boolean isServingRepositories();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over HTTP.
*
* @return true if Gitblit is serving repositories over HTTP
* @since 1.6.0
*/
boolean isServingHTTP();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the GIT Daemon protocol.
*
* @return true if Gitblit is serving repositories over the GIT Daemon protocol
* @since 1.6.0
*/
boolean isServingGIT();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the SSH protocol.
*
* @return true if Gitblit is serving repositories over the SSH protocol
* @since 1.6.0
*/
boolean isServingSSH();

/**
* Determine if this Gitblit instance is running in debug mode
*

+ 75
- 0
src/main/java/com/gitblit/manager/IServicesManager.java View File

@@ -0,0 +1,75 @@
/*
* Copyright 2014 gitblit.com.
*
* 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.gitblit.manager;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.UserModel;

public interface IServicesManager extends IManager {

/**
* Determine if this Gitblit instance is actively serving git repositories
* or if it is merely a repository viewer.
*
* @return true if Gitblit is serving repositories
* @since 1.7.0
*/
boolean isServingRepositories();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over HTTP.
*
* @return true if Gitblit is serving repositories over HTTP
* @since 1.7.0
*/
boolean isServingHTTP();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the GIT Daemon protocol.
*
* @return true if Gitblit is serving repositories over the GIT Daemon protocol
* @since 1.7.0
*/
boolean isServingGIT();

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the SSH protocol.
*
* @return true if Gitblit is serving repositories over the SSH protocol
* @since 1.7.0
*/
boolean isServingSSH();

/**
* Returns a list of repository URLs and the user access permission.
*
* @param request
* @param user
* @param repository
* @return a list of repository urls
* @since 1.7.0
*/
List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository);

}

+ 12
- 14
src/main/java/com/gitblit/manager/RepositoryManager.java View File

@@ -1937,21 +1937,19 @@ public class RepositoryManager implements IRepositoryManager {
}

protected void confirmWriteAccess() {
if (runtimeManager.isServingRepositories()) {
try {
if (!getRepositoriesFolder().exists()) {
getRepositoriesFolder().mkdirs();
}
File file = File.createTempFile(".test-", ".txt", getRepositoriesFolder());
file.delete();
} catch (Exception e) {
logger.error("");
logger.error(Constants.BORDER2);
logger.error("Please check filesystem permissions!");
logger.error("FAILED TO WRITE TO REPOSITORIES FOLDER!!", e);
logger.error(Constants.BORDER2);
logger.error("");
try {
if (!getRepositoriesFolder().exists()) {
getRepositoriesFolder().mkdirs();
}
File file = File.createTempFile(".test-", ".txt", getRepositoriesFolder());
file.delete();
} catch (Exception e) {
logger.error("");
logger.error(Constants.BORDER2);
logger.error("Please check filesystem permissions!");
logger.error("FAILED TO WRITE TO REPOSITORIES FOLDER!!", e);
logger.error(Constants.BORDER2);
logger.error("");
}
}
}

+ 3
- 48
src/main/java/com/gitblit/manager/RuntimeManager.java View File

@@ -22,8 +22,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import com.google.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -34,8 +32,11 @@ import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
import com.gitblit.models.SettingModel;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;

@Singleton
public class RuntimeManager implements IRuntimeManager {

private final Logger logger = LoggerFactory.getLogger(getClass());
@@ -123,52 +124,6 @@ public class RuntimeManager implements IRuntimeManager {
return settingsModel;
}

/**
* Determine if this Gitblit instance is actively serving git repositories
* or if it is merely a repository viewer.
*
* @return true if Gitblit is serving repositories
*/
@Override
public boolean isServingRepositories() {
return isServingHTTP()
|| isServingGIT()
|| isServingSSH();
}

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the HTTP protocol.
*
* @return true if Gitblit is serving repositories over the HTTP protocol
*/
@Override
public boolean isServingHTTP() {
return settings.getBoolean(Keys.git.enableGitServlet, true);
}

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the Git Daemon protocol.
*
* @return true if Gitblit is serving repositories over the Git Daemon protocol
*/
@Override
public boolean isServingGIT() {
return settings.getInteger(Keys.git.daemonPort, 0) > 0;
}

/**
* Determine if this Gitblit instance is actively serving git repositories
* over the SSH protocol.
*
* @return true if Gitblit is serving repositories over the SSH protocol
*/
@Override
public boolean isServingSSH() {
return settings.getInteger(Keys.git.sshPort, 0) > 0;
}

/**
* Returns the preferred timezone for the Gitblit instance.
*

+ 212
- 14
src/main/java/com/gitblit/manager/ServicesManager.java View File

@@ -18,9 +18,15 @@ package com.gitblit.manager;
import java.io.IOException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -30,9 +36,11 @@ import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationToken;
import com.gitblit.Constants.Transport;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.fanout.FanoutNioService;
@@ -40,14 +48,18 @@ import com.gitblit.fanout.FanoutService;
import com.gitblit.fanout.FanoutSocketService;
import com.gitblit.models.FederationModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.UserModel;
import com.gitblit.service.FederationPullService;
import com.gitblit.transport.git.GitDaemon;
import com.gitblit.transport.ssh.SshDaemon;
import com.gitblit.utils.IdGenerator;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
import com.gitblit.utils.WorkQueue;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

/**
* Services manager manages long-running services/processes that either have no
@@ -57,32 +69,35 @@ import com.gitblit.utils.WorkQueue;
* @author James Moger
*
*/
public class ServicesManager implements IManager {
@Singleton
public class ServicesManager implements IServicesManager {

private final Logger logger = LoggerFactory.getLogger(getClass());

private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(5);

private final Provider<WorkQueue> workQueueProvider;

private final IStoredSettings settings;

private final IGitblit gitblit;

private final IdGenerator idGenerator;

private final WorkQueue workQueue;

private FanoutService fanoutService;

private GitDaemon gitDaemon;

private SshDaemon sshDaemon;

public ServicesManager(IGitblit gitblit) {
this.settings = gitblit.getSettings();
@Inject
public ServicesManager(
Provider<WorkQueue> workQueueProvider,
IStoredSettings settings,
IGitblit gitblit) {

this.workQueueProvider = workQueueProvider;

this.settings = settings;
this.gitblit = gitblit;
int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1);
this.idGenerator = new IdGenerator();
this.workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize);
}

@Override
@@ -107,24 +122,181 @@ public class ServicesManager implements IManager {
if (sshDaemon != null) {
sshDaemon.stop();
}
workQueue.stop();
workQueueProvider.get().stop();
return this;
}

protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) {
String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
if (StringUtils.isEmpty(gitblitUrl)) {
gitblitUrl = HttpUtils.getGitblitURL(request);
}
StringBuilder sb = new StringBuilder();
sb.append(gitblitUrl);
sb.append(Constants.R_PATH);
sb.append(repository.name);

// inject username into repository url if authentication is required
if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
&& !StringUtils.isEmpty(username)) {
sb.insert(sb.indexOf("://") + 3, username + "@");
}
return sb.toString();
}

/**
* Returns a list of repository URLs and the user access permission.
*
* @param request
* @param user
* @param repository
* @return a list of repository urls
*/
@Override
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
if (user == null) {
user = UserModel.ANONYMOUS;
}
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);

List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();

// http/https url
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));
}
}

// ssh daemon url
String sshDaemonUrl = getSshDaemonUrl(request, user, repository);
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));
}
}

// git daemon url
String gitDaemonUrl = getGitDaemonUrl(request, user, repository);
if (!StringUtils.isEmpty(gitDaemonUrl)) {
AccessPermission permission = 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));
}
}

// add all other urls
// {0} = repository
// {1} = username
for (String url : settings.getStrings(Keys.web.otherUrls)) {
if (url.contains("{1}")) {
// external url requires username, only add url IF we have one
if (!StringUtils.isEmpty(username)) {
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
}
} else {
// external url does not require username
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;
}

/* (non-Javadoc)
* @see com.gitblit.manager.IServicesManager#isServingRepositories()
*/
@Override
public boolean isServingRepositories() {
return isServingHTTP()
|| isServingGIT()
|| isServingSSH();
}

/* (non-Javadoc)
* @see com.gitblit.manager.IServicesManager#isServingHTTP()
*/
@Override
public boolean isServingHTTP() {
return settings.getBoolean(Keys.git.enableGitServlet, true);
}

/* (non-Javadoc)
* @see com.gitblit.manager.IServicesManager#isServingGIT()
*/
@Override
public boolean isServingGIT() {
return gitDaemon != null && gitDaemon.isRunning();
}

/* (non-Javadoc)
* @see com.gitblit.manager.IServicesManager#isServingSSH()
*/
@Override
public boolean isServingSSH() {
return sshDaemon != null && sshDaemon.isRunning();
}
@@ -158,6 +330,32 @@ public class ServicesManager implements IManager {
}
}

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 : settings.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);
}

protected void configureGitDaemon() {
int port = settings.getInteger(Keys.git.daemonPort, 0);
String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost");
@@ -179,7 +377,7 @@ public class ServicesManager implements IManager {
String bindInterface = settings.getString(Keys.git.sshBindInterface, "localhost");
if (port > 0) {
try {
sshDaemon = new SshDaemon(gitblit, workQueue);
sshDaemon = new SshDaemon(gitblit, workQueueProvider.get());
sshDaemon.start();
} catch (IOException e) {
sshDaemon = null;
@@ -285,7 +483,7 @@ public class ServicesManager implements IManager {
*/
protected String getHostname(HttpServletRequest request) {
String hostname = request.getServerName();
String canonicalUrl = gitblit.getSettings().getString(Keys.web.canonicalUrl, null);
String canonicalUrl = settings.getString(Keys.web.canonicalUrl, null);
if (!StringUtils.isEmpty(canonicalUrl)) {
try {
URI uri = new URI(canonicalUrl);

+ 2
- 0
src/main/java/com/gitblit/servlet/GitblitContext.java View File

@@ -51,6 +51,7 @@ import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IServicesManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.ContainerUtils;
@@ -200,6 +201,7 @@ public class GitblitContext extends GuiceServletContextListener {
startManager(injector, IProjectManager.class);
startManager(injector, IFederationManager.class);
startManager(injector, IGitblit.class);
startManager(injector, IServicesManager.class);

// start the plugin manager last so that plugins can depend on
// deterministic access to all other managers in their start() methods

+ 16
- 4
src/main/java/com/gitblit/wicket/GitBlitWebApp.java View File

@@ -21,9 +21,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.apache.wicket.Application;
import org.apache.wicket.Request;
import org.apache.wicket.Response;
@@ -46,6 +43,7 @@ import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IServicesManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
@@ -92,6 +90,8 @@ import com.gitblit.wicket.pages.TicketsPage;
import com.gitblit.wicket.pages.TreePage;
import com.gitblit.wicket.pages.UserPage;
import com.gitblit.wicket.pages.UsersPage;
import com.google.inject.Inject;
import com.google.inject.Singleton;

@Singleton
public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {
@@ -124,6 +124,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {

private final IGitblit gitblit;

private final IServicesManager services;

@Inject
public GitBlitWebApp(
IRuntimeManager runtimeManager,
@@ -135,7 +137,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {
IRepositoryManager repositoryManager,
IProjectManager projectManager,
IFederationManager federationManager,
IGitblit gitblit) {
IGitblit gitblit,
IServicesManager services) {

super();
this.settings = runtimeManager.getSettings();
@@ -149,6 +152,7 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {
this.projectManager = projectManager;
this.federationManager = federationManager;
this.gitblit = gitblit;
this.services = services;
}

@Override
@@ -420,6 +424,14 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {
return gitblit;
}

/* (non-Javadoc)
* @see com.gitblit.wicket.Webapp#services()
*/
@Override
public IServicesManager services() {
return services;
}

/* (non-Javadoc)
* @see com.gitblit.wicket.Webapp#tickets()
*/

+ 3
- 0
src/main/java/com/gitblit/wicket/GitblitWicketApp.java View File

@@ -14,6 +14,7 @@ import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IServicesManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
@@ -65,6 +66,8 @@ public interface GitblitWicketApp {

public abstract IGitblit gitblit();

public abstract IServicesManager services();

public abstract ITicketService tickets();

public abstract TimeZone getTimezone();

+ 1
- 1
src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java View File

@@ -55,7 +55,7 @@ public class EmptyRepositoryPage extends RepositoryPage {
}
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository);
List<RepositoryUrl> repositoryUrls = app().services().getRepositoryUrls(req, user, repository);
RepositoryUrl primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
String url = primaryUrl != null ? primaryUrl.url : "";

+ 1
- 1
src/main/java/com/gitblit/wicket/pages/TicketPage.java View File

@@ -1505,7 +1505,7 @@ public class TicketPage extends RepositoryPage {
*/
protected RepositoryUrl getRepositoryUrl(UserModel user, RepositoryModel repository) {
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
List<RepositoryUrl> urls = app().gitblit().getRepositoryUrls(req, user, repository);
List<RepositoryUrl> urls = app().services().getRepositoryUrls(req, user, repository);
if (ArrayUtils.isEmpty(urls)) {
return null;
}

+ 4
- 4
src/main/java/com/gitblit/wicket/pages/UserPage.java View File

@@ -104,7 +104,7 @@ public class UserPage extends RootPage {
if (isMyProfile) {
addPreferences(user);
if (app().gitblit().isServingSSH()) {
if (app().services().isServingSSH()) {
// show the SSH key management tab
addSshKeys(user);
} else {
@@ -248,14 +248,14 @@ public class UserPage extends RootPage {
emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail()));
List<Transport> availableTransports = new ArrayList<>();
if (app().gitblit().isServingSSH()) {
if (app().services().isServingSSH()) {
availableTransports.add(Transport.SSH);
}
if (app().gitblit().isServingHTTP()) {
if (app().services().isServingHTTP()) {
availableTransports.add(Transport.HTTPS);
availableTransports.add(Transport.HTTP);
}
if (app().gitblit().isServingGIT()) {
if (app().services().isServingGIT()) {
availableTransports.add(Transport.GIT);
}

+ 2
- 2
src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java View File

@@ -80,7 +80,7 @@ public class RepositoryUrlPanel extends BasePanel {
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();
List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository);
List<RepositoryUrl> repositoryUrls = app().services().getRepositoryUrls(req, user, repository);
// grab primary url from the top of the list
primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
@@ -165,7 +165,7 @@ public class RepositoryUrlPanel extends BasePanel {
if (repository.isMirror) {
urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png",
getString("gb.isMirror")));
} else if (app().gitblit().isServingRepositories()) {
} else if (app().services().isServingRepositories()) {
switch (repository.accessRestriction) {
case NONE:
urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));

+ 0
- 20
src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java View File

@@ -82,26 +82,6 @@ public class MockRuntimeManager implements IRuntimeManager {
return Locale.getDefault();
}

@Override
public boolean isServingRepositories() {
return true;
}

@Override
public boolean isServingHTTP() {
return true;
}

@Override
public boolean isServingGIT() {
return true;
}

@Override
public boolean isServingSSH() {
return true;
}

@Override
public boolean isDebugMode() {
return true;

Loading…
Cancel
Save