mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 07:25:44 +01:00
added caching for changesetviewer
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @version 1.6
|
||||
*/
|
||||
public class NotSupportedFeatuerException extends Exception
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = 256498734456613496L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public NotSupportedFeatuerException() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public NotSupportedFeatuerException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.NotSupportedFeatuerException;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.6
|
||||
*/
|
||||
public class ChangesetViewerUtil implements RepositoryHook
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CACHE_NAME = "sonia.cache.repository.changesets";
|
||||
|
||||
/** the logger for ChangesetViewerUtil */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(ChangesetViewerUtil.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repositoryManager
|
||||
* @param cacheManager
|
||||
*/
|
||||
@Inject
|
||||
public ChangesetViewerUtil(RepositoryManager repositoryManager,
|
||||
CacheManager cacheManager)
|
||||
{
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.repositoryManager.addHook(this);
|
||||
this.cache = cacheManager.getCache(ChangesetViewerCacheKey.class,
|
||||
ChangesetPagingResult.class, CACHE_NAME);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TODO: only remove objects from the given repository
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(RepositoryHookEvent event)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("clear cache because repository {} has changed",
|
||||
event.getRepository().getName());
|
||||
}
|
||||
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryId
|
||||
* @param start
|
||||
* @param max
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws NotSupportedFeatuerException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public ChangesetPagingResult getChangesets(String repositoryId, int start,
|
||||
int max)
|
||||
throws RepositoryException, NotSupportedFeatuerException
|
||||
{
|
||||
AssertUtil.assertIsNotEmpty(repositoryId);
|
||||
|
||||
Repository repository = repositoryManager.get(repositoryId);
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
throw new RepositoryNotFoundException(
|
||||
"could not find repository with id ".concat(repositoryId));
|
||||
}
|
||||
|
||||
return getChangesets(repository, start, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param start
|
||||
* @param max
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws NotSupportedFeatuerException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
public ChangesetPagingResult getChangesets(Repository repository, int start,
|
||||
int max)
|
||||
throws RepositoryException, NotSupportedFeatuerException
|
||||
{
|
||||
AssertUtil.assertIsNotNull(repository);
|
||||
|
||||
ChangesetViewer viewer = repositoryManager.getChangesetViewer(repository);
|
||||
|
||||
if (viewer == null)
|
||||
{
|
||||
throw new NotSupportedFeatuerException(
|
||||
"ChangesetViewer is not supported for type ".concat(
|
||||
repository.getType()));
|
||||
}
|
||||
|
||||
ChangesetViewerCacheKey key =
|
||||
new ChangesetViewerCacheKey(repository.getId(), start, max);
|
||||
ChangesetPagingResult result = cache.get(key);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = viewer.getChangesets(start, max);
|
||||
cache.put(key, result);
|
||||
}
|
||||
else if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("fetch changesetviewer results from cache");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<RepositoryHookType> getTypes()
|
||||
{
|
||||
return Arrays.asList(RepositoryHookType.POST_RECEIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAsync()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 11/07/24
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
private class ChangesetViewerCacheKey
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param start
|
||||
* @param max
|
||||
*/
|
||||
public ChangesetViewerCacheKey(String repository, int start, int max)
|
||||
{
|
||||
this.repository = repository;
|
||||
this.start = start;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
//~--- methods ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param obj
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final ChangesetViewerCacheKey other = (ChangesetViewerCacheKey) obj;
|
||||
|
||||
if ((this.repository == null)
|
||||
? (other.repository != null)
|
||||
: !this.repository.equals(other.repository))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.start != other.start)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.max != other.max)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 3;
|
||||
|
||||
hash = 67 * hash + ((this.repository != null)
|
||||
? this.repository.hashCode()
|
||||
: 0);
|
||||
hash = 67 * hash + this.start;
|
||||
hash = 67 * hash + this.max;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private int max;
|
||||
|
||||
/** Field description */
|
||||
private String repository;
|
||||
|
||||
/** Field description */
|
||||
private int start;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Cache<ChangesetViewerCacheKey, ChangesetPagingResult> cache;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManager;
|
||||
}
|
||||
@@ -43,4 +43,23 @@ public class RepositoryNotFoundException extends RepositoryException
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -6583078808900520166L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public RepositoryNotFoundException() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public RepositoryNotFoundException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import sonia.scm.plugin.Plugin;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.plugin.PluginManager;
|
||||
import sonia.scm.plugin.ScriptResourceServlet;
|
||||
import sonia.scm.repository.ChangesetViewerUtil;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.xml.XmlRepositoryManager;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
@@ -217,6 +218,7 @@ public class ScmServletModule extends ServletModule
|
||||
bind(UserManager.class).to(XmlUserManager.class);
|
||||
bind(GroupManager.class).to(XmlGroupManager.class);
|
||||
bind(CGIExecutorFactory.class).to(DefaultCGIExecutorFactory.class);
|
||||
bind(ChangesetViewerUtil.class);
|
||||
|
||||
// bind httpclient
|
||||
bind(HttpClient.class).to(URLHttpClient.class);
|
||||
|
||||
@@ -42,12 +42,14 @@ import com.google.inject.Singleton;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.NotSupportedFeatuerException;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.ChangesetPreProcessor;
|
||||
import sonia.scm.repository.ChangesetViewer;
|
||||
import sonia.scm.repository.ChangesetViewerUtil;
|
||||
import sonia.scm.repository.FileObject;
|
||||
import sonia.scm.repository.FileObjectNameComparator;
|
||||
import sonia.scm.repository.PathNotFoundException;
|
||||
@@ -59,6 +61,7 @@ import sonia.scm.repository.RepositoryBrowser;
|
||||
import sonia.scm.repository.RepositoryException;
|
||||
import sonia.scm.repository.RepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
@@ -114,18 +117,21 @@ public class RepositoryResource
|
||||
* @param repositoryManager
|
||||
* @param securityContextProvider
|
||||
* @param changesetPreProcessorSet
|
||||
* @param changesetViewerUtil
|
||||
*/
|
||||
@Inject
|
||||
public RepositoryResource(
|
||||
ScmConfiguration configuration, RepositoryManager repositoryManager,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
Set<ChangesetPreProcessor> changesetPreProcessorSet)
|
||||
Set<ChangesetPreProcessor> changesetPreProcessorSet,
|
||||
ChangesetViewerUtil changesetViewerUtil)
|
||||
{
|
||||
super(repositoryManager);
|
||||
this.configuration = configuration;
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
this.changesetPreProcessorSet = changesetPreProcessorSet;
|
||||
this.changesetViewerUtil = changesetViewerUtil;
|
||||
setDisableCache(false);
|
||||
}
|
||||
|
||||
@@ -213,17 +219,11 @@ public class RepositoryResource
|
||||
@QueryParam("limit") int limit) throws RepositoryException
|
||||
{
|
||||
Response response = null;
|
||||
Repository repository = repositoryManager.get(id);
|
||||
|
||||
if (repository != null)
|
||||
try
|
||||
{
|
||||
ChangesetViewer changesetViewer =
|
||||
repositoryManager.getChangesetViewer(repository);
|
||||
|
||||
if (changesetViewer != null)
|
||||
{
|
||||
ChangesetPagingResult changesets = changesetViewer.getChangesets(start,
|
||||
limit);
|
||||
ChangesetPagingResult changesets = changesetViewerUtil.getChangesets(id,
|
||||
start, limit);
|
||||
|
||||
if (changesets != null)
|
||||
{
|
||||
@@ -235,14 +235,13 @@ public class RepositoryResource
|
||||
response = Response.ok().build();
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (RepositoryNotFoundException ex)
|
||||
{
|
||||
response = Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (NotSupportedFeatuerException ex)
|
||||
{
|
||||
response = Response.status(Response.Status.NOT_FOUND).build();
|
||||
response = Response.status(Response.Status.BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -566,6 +565,9 @@ public class RepositoryResource
|
||||
/** Field description */
|
||||
private Set<ChangesetPreProcessor> changesetPreProcessorSet;
|
||||
|
||||
/** Field description */
|
||||
private ChangesetViewerUtil changesetViewerUtil;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
|
||||
@@ -134,4 +134,13 @@
|
||||
diskPersistent="false"
|
||||
/>
|
||||
|
||||
<cache
|
||||
name="sonia.cache.repository.changesets"
|
||||
maxElementsInMemory="10000"
|
||||
eternal="false"
|
||||
overflowToDisk="false"
|
||||
timeToLiveSeconds="5400"
|
||||
diskPersistent="false"
|
||||
/>
|
||||
|
||||
</ehcache>
|
||||
|
||||
Reference in New Issue
Block a user