James Moger
2014-07-02 c42032df0911f51c81a91a961eff2066b380607c
Extract ticket service into an injectable object with a custom provider
1 files added
11 files modified
293 ■■■■ changed files
src/main/java/com/gitblit/FederationClient.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitBlit.java 140 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/guice/CoreModule.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/guice/ITicketServiceProvider.java 73 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/GitblitManager.java 36 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/servlet/GitblitContext.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/BranchTicketService.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/FileTicketService.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/ITicketService.java 5 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/NullTicketService.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/RedisTicketService.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/FederationClient.java
@@ -97,7 +97,7 @@
        UserManager users = new UserManager(runtime, null).start();
        RepositoryManager repositories = new RepositoryManager(runtime, null, users).start();
        FederationManager federation = new FederationManager(runtime, notifications, repositories).start();
        IGitblit gitblit = new GitblitManager(null, runtime, null, notifications, users, null, repositories, null, federation);
        IGitblit gitblit = new GitblitManager(null, null, runtime, null, notifications, users, null, repositories, null, federation);
        FederationPullService puller = new FederationPullService(gitblit, federation.getFederationRegistrations()) {
            @Override
src/main/java/com/gitblit/GitBlit.java
@@ -15,55 +15,36 @@
 */
package com.gitblit;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.gitblit.manager.GitblitManager;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblit;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.NullTicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.StringUtils;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Singleton;
/**
 * GitBlit is the aggregate manager for the Gitblit webapp.  It provides all
 * management functions and also manages some long-running services.
 * GitBlit is the aggregate manager for the Gitblit webapp.  The parent class provides all
 * functionality.  This class exists to not break existing Groovy push hooks.
 *
 * @author James Moger
 *
 */
@Singleton
@Deprecated
public class GitBlit extends GitblitManager {
    private final Injector injector;
    private ITicketService ticketService;
    @Inject
    public GitBlit(
            Provider<IPublicKeyManager> publicKeyManagerProvider,
            Provider<ITicketService> ticketServiceProvider,
            IRuntimeManager runtimeManager,
            IPluginManager pluginManager,
            INotificationManager notificationManager,
@@ -75,6 +56,7 @@
        super(
                publicKeyManagerProvider,
                ticketServiceProvider,
                runtimeManager,
                pluginManager,
                notificationManager,
@@ -83,117 +65,5 @@
                repositoryManager,
                projectManager,
                federationManager);
        this.injector = Guice.createInjector(getModules());
    }
    @Override
    public GitBlit start() {
        super.start();
        configureTicketService();
        return this;
    }
    @Override
    public GitBlit stop() {
        super.stop();
        ticketService.stop();
        return this;
    }
    protected AbstractModule [] getModules() {
        return new AbstractModule [] { new GitBlitModule()};
    }
    /**
     * Detect renames and reindex as appropriate.
     */
    @Override
    public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
            boolean isCreate) throws GitBlitException {
        RepositoryModel oldModel = null;
        boolean isRename = !isCreate && !repositoryName.equalsIgnoreCase(repository.name);
        if (isRename) {
            oldModel = repositoryManager.getRepositoryModel(repositoryName);
        }
        super.updateRepositoryModel(repositoryName, repository, isCreate);
        if (isRename && ticketService != null) {
            ticketService.rename(oldModel, repository);
        }
    }
    /**
     * Delete the repository and all associated tickets.
     */
    @Override
    public boolean deleteRepository(String repositoryName) {
        RepositoryModel repository = repositoryManager.getRepositoryModel(repositoryName);
        return deleteRepositoryModel(repository);
    }
    @Override
    public boolean deleteRepositoryModel(RepositoryModel model) {
        boolean success = repositoryManager.deleteRepositoryModel(model);
        if (success && ticketService != null) {
            ticketService.deleteAll(model);
        }
        return success;
    }
    /**
     * Returns the configured ticket service.
     *
     * @return a ticket service
     */
    @Override
    public ITicketService getTicketService() {
        return ticketService;
    }
    protected void configureTicketService() {
        String clazz = settings.getString(Keys.tickets.service, NullTicketService.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = NullTicketService.class.getName();
        }
        try {
            Class<? extends ITicketService> serviceClass = (Class<? extends ITicketService>) Class.forName(clazz);
            ticketService = injector.getInstance(serviceClass).start();
            if (ticketService instanceof NullTicketService) {
                logger.warn("No ticket service configured.");
            } else if (ticketService.isReady()) {
                logger.info("{} is ready.", ticketService);
            } else {
                logger.warn("{} is disabled.", ticketService);
            }
        } catch (Exception e) {
            logger.error("failed to create ticket service " + clazz, e);
            ticketService = injector.getInstance(NullTicketService.class).start();
        }
    }
    /**
     * A nested Guice Module is used for constructor dependency injection of
     * complex classes.
     *
     * @author James Moger
     *
     */
    class GitBlitModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(IStoredSettings.class).toInstance(settings);
            bind(IRuntimeManager.class).toInstance(runtimeManager);
            bind(IPluginManager.class).toInstance(pluginManager);
            bind(INotificationManager.class).toInstance(notificationManager);
            bind(IUserManager.class).toInstance(userManager);
            bind(IAuthenticationManager.class).toInstance(authenticationManager);
            bind(IRepositoryManager.class).toInstance(repositoryManager);
            bind(IProjectManager.class).toInstance(projectManager);
            bind(IFederationManager.class).toInstance(federationManager);
            bind(IGitblit.class).toInstance(GitBlit.this);
        }
    }
}
src/main/java/com/gitblit/guice/CoreModule.java
@@ -37,6 +37,7 @@
import com.gitblit.manager.RuntimeManager;
import com.gitblit.manager.ServicesManager;
import com.gitblit.manager.UserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.WorkQueue;
import com.google.inject.AbstractModule;
@@ -56,6 +57,7 @@
        // bind complex providers
        bind(IPublicKeyManager.class).toProvider(IPublicKeyManagerProvider.class);
        bind(ITicketService.class).toProvider(ITicketServiceProvider.class);
        bind(WorkQueue.class).toProvider(WorkQueueProvider.class);
        // core managers
src/main/java/com/gitblit/guice/ITicketServiceProvider.java
New file
@@ -0,0 +1,73 @@
/*
 * 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.NullTicketService;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
/**
 * Provides a lazily-instantiated ITicketService configured from IStoredSettings.
 *
 * @author James Moger
 *
 */
@Singleton
public class ITicketServiceProvider implements Provider<ITicketService> {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final IRuntimeManager runtimeManager;
    private volatile ITicketService service;
    @Inject
    public ITicketServiceProvider(IRuntimeManager runtimeManager) {
        this.runtimeManager = runtimeManager;
    }
    @Override
    public synchronized ITicketService get() {
        if (service != null) {
            return service;
        }
        IStoredSettings settings = runtimeManager.getSettings();
        String clazz = settings.getString(Keys.tickets.service, NullTicketService.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = NullTicketService.class.getName();
        }
        try {
            Class<? extends ITicketService> serviceClass = (Class<? extends ITicketService>) Class.forName(clazz);
            service = runtimeManager.getInjector().getInstance(serviceClass);
        } catch (Exception e) {
            logger.error("failed to create ticket service", e);
            service = runtimeManager.getInjector().getInstance(NullTicketService.class);
        }
        return service;
    }
}
src/main/java/com/gitblit/manager/GitblitManager.java
@@ -109,6 +109,8 @@
    protected final Provider<IPublicKeyManager> publicKeyManagerProvider;
    protected final Provider<ITicketService> ticketServiceProvider;
    protected final IStoredSettings settings;
    protected final IRuntimeManager runtimeManager;
@@ -130,6 +132,7 @@
    @Inject
    public GitblitManager(
            Provider<IPublicKeyManager> publicKeyManagerProvider,
            Provider<ITicketService> ticketServiceProvider,
            IRuntimeManager runtimeManager,
            IPluginManager pluginManager,
            INotificationManager notificationManager,
@@ -140,6 +143,7 @@
            IFederationManager federationManager) {
        this.publicKeyManagerProvider = publicKeyManagerProvider;
        this.ticketServiceProvider = ticketServiceProvider;
        this.settings = runtimeManager.getSettings();
        this.runtimeManager = runtimeManager;
@@ -478,13 +482,9 @@
        }
    }
    /**
     * Throws an exception if trying to get a ticket service.
     *
     */
    @Override
    public ITicketService getTicketService() {
        throw new RuntimeException("This class does not have a ticket service!");
        return ticketServiceProvider.get();
    }
    @Override
@@ -960,10 +960,23 @@
        return repositoryManager.getRepositoryDefaultMetrics(model, repository);
    }
    /**
     * Detect renames and reindex as appropriate.
     */
    @Override
    public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
            boolean isCreate) throws GitBlitException {
        RepositoryModel oldModel = null;
        boolean isRename = !isCreate && !repositoryName.equalsIgnoreCase(repository.name);
        if (isRename) {
            oldModel = repositoryManager.getRepositoryModel(repositoryName);
        }
        repositoryManager.updateRepositoryModel(repositoryName, repository, isCreate);
        if (isRename && ticketServiceProvider.get() != null) {
            ticketServiceProvider.get().rename(oldModel, repository);
        }
    }
    @Override
@@ -976,14 +989,23 @@
        return repositoryManager.canDelete(model);
    }
    /**
     * Delete the repository and all associated tickets.
     */
    @Override
    public boolean deleteRepositoryModel(RepositoryModel model) {
        return repositoryManager.deleteRepositoryModel(model);
        boolean success = repositoryManager.deleteRepositoryModel(model);
        if (success && ticketServiceProvider.get() != null) {
            ticketServiceProvider.get().deleteAll(model);
        }
        return success;
    }
    @Override
    public boolean deleteRepository(String repositoryName) {
        return repositoryManager.deleteRepository(repositoryName);
        // delegate to deleteRepositoryModel() to destroy indexed tickets
        RepositoryModel repository = repositoryManager.getRepositoryModel(repositoryName);
        return deleteRepositoryModel(repository);
    }
    @Override
src/main/java/com/gitblit/servlet/GitblitContext.java
@@ -53,6 +53,7 @@
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;
import com.gitblit.utils.ContainerUtils;
import com.gitblit.utils.StringUtils;
@@ -200,6 +201,7 @@
        startManager(injector, IRepositoryManager.class);
        startManager(injector, IProjectManager.class);
        startManager(injector, IFederationManager.class);
        startManager(injector, ITicketService.class);
        startManager(injector, IGitblit.class);
        startManager(injector, IServicesManager.class);
src/main/java/com/gitblit/tickets/BranchTicketService.java
@@ -30,9 +30,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
@@ -75,6 +72,8 @@
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
 * Implementation of a ticket service based on an orphan branch.  All tickets
@@ -117,6 +116,7 @@
    @Override
    public BranchTicketService start() {
        log.info("{} started", getClass().getSimpleName());
        return this;
    }
src/main/java/com/gitblit/tickets/FileTicketService.java
@@ -27,9 +27,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Repository;
import com.gitblit.Constants;
@@ -45,6 +42,8 @@
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.FileUtils;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
 * Implementation of a ticket service based on a directory within the repository.
@@ -82,6 +81,7 @@
    @Override
    public FileTicketService start() {
        log.info("{} started", getClass().getSimpleName());
        return this;
    }
src/main/java/com/gitblit/tickets/ITicketService.java
@@ -36,6 +36,7 @@
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.extensions.TicketHook;
import com.gitblit.manager.IManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IRepositoryManager;
@@ -63,7 +64,7 @@
 * @author James Moger
 *
 */
public abstract class ITicketService {
public abstract class ITicketService implements IManager {
    public static final String SETTING_UPDATE_DIFFSTATS = "migration.updateDiffstats";
@@ -176,12 +177,14 @@
     * Start the service.
     * @since 1.4.0
     */
    @Override
    public abstract ITicketService start();
    /**
     * Stop the service.
     * @since 1.4.0
     */
    @Override
    public final ITicketService stop() {
        indexer.close();
        ticketsCache.invalidateAll();
src/main/java/com/gitblit/tickets/NullTicketService.java
@@ -19,9 +19,6 @@
import java.util.List;
import java.util.Set;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IRepositoryManager;
@@ -31,6 +28,8 @@
import com.gitblit.models.TicketModel;
import com.gitblit.models.TicketModel.Attachment;
import com.gitblit.models.TicketModel.Change;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
 * Implementation of a ticket service that rejects everything.
@@ -63,6 +62,7 @@
    @Override
    public NullTicketService start() {
        log.info("{} started", getClass().getSimpleName());
        return this;
    }
src/main/java/com/gitblit/tickets/RedisTicketService.java
@@ -22,9 +22,6 @@
import java.util.Set;
import java.util.TreeSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Client;
@@ -46,6 +43,8 @@
import com.gitblit.models.TicketModel.Change;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
 * Implementation of a ticket service based on a Redis key-value store.  All
@@ -85,6 +84,10 @@
    @Override
    public RedisTicketService start() {
        log.info("{} started", getClass().getSimpleName());
        if (!isReady()) {
            log.warn("{} is not ready!", getClass().getSimpleName());
        }
        return this;
    }
src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -105,6 +105,8 @@
    private final Provider<IPublicKeyManager> publicKeyManagerProvider;
    private final Provider<ITicketService> ticketServiceProvider;
    private final IStoredSettings settings;
    private final IRuntimeManager runtimeManager;
@@ -130,6 +132,7 @@
    @Inject
    public GitBlitWebApp(
            Provider<IPublicKeyManager> publicKeyManagerProvider,
            Provider<ITicketService> ticketServiceProvider,
            IRuntimeManager runtimeManager,
            IPluginManager pluginManager,
            INotificationManager notificationManager,
@@ -143,6 +146,7 @@
        super();
        this.publicKeyManagerProvider = publicKeyManagerProvider;
        this.ticketServiceProvider = ticketServiceProvider;
        this.settings = runtimeManager.getSettings();
        this.runtimeManager = runtimeManager;
        this.pluginManager = pluginManager;
@@ -438,7 +442,7 @@
     */
    @Override
    public ITicketService tickets() {
        return gitblit.getTicketService();
        return ticketServiceProvider.get();
    }
    /* (non-Javadoc)