diff --git a/scm-core/src/main/java/sonia/scm/repository/Branch.java b/scm-core/src/main/java/sonia/scm/repository/Branch.java new file mode 100644 index 0000000000..e15d76a7f1 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/Branch.java @@ -0,0 +1,145 @@ +/** + * 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.common.base.Objects; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + * @since 1.18 + */ +@XmlRootElement(name="branch") +@XmlAccessorType(XmlAccessType.FIELD) +public final class Branch implements Serializable +{ + + /** + * Constructs ... + * + */ + public Branch() {} + + /** + * Constructs ... + * + * + * @param name + */ + public Branch(String name) + { + this.name = name; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final Branch other = (Branch) obj; + + return Objects.equal(name, other.name); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(name); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + //J- + return Objects.toStringHelper(this) + .add("name", name) + .toString(); + //J+ + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String name; +} diff --git a/scm-core/src/main/java/sonia/scm/repository/Branches.java b/scm-core/src/main/java/sonia/scm/repository/Branches.java new file mode 100644 index 0000000000..624d37cbb7 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/Branches.java @@ -0,0 +1,190 @@ +/** + * 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.common.base.Objects; +import com.google.common.collect.Lists; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Iterator; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + * @since 1.18 + */ +@XmlRootElement(name="branches") +@XmlAccessorType(XmlAccessType.FIELD) +public final class Branches implements Iterable +{ + + /** + * Constructs ... + * + */ + public Branches() {} + + /** + * Constructs ... + * + * + * @param branches + */ + public Branches(Branch... branches) + { + this.branches = Lists.newArrayList(branches); + } + + /** + * Constructs ... + * + * + * @param branches + */ + public Branches(List branches) + { + this.branches = branches; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final Branches other = (Branches) obj; + + return Objects.equal(branches, other.branches); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(branches); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Iterator iterator() + { + return getBranches().iterator(); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + //J- + return Objects.toStringHelper(this) + .add("branches", branches) + .toString(); + //J+ + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public List getBranches() + { + if (branches == null) + { + branches = Lists.newArrayList(); + } + + return branches; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param branches + */ + public void setBranches(List branches) + { + this.branches = branches; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlElement(name="branch") + private List branches; +} diff --git a/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java new file mode 100644 index 0000000000..f009fb0136 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java @@ -0,0 +1,280 @@ +/** + * 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.api; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.cache.Cache; +import sonia.scm.cache.CacheManager; +import sonia.scm.repository.Branch; +import sonia.scm.repository.Branches; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryCacheKey; +import sonia.scm.repository.RepositoryException; +import sonia.scm.repository.spi.BlameCommand; +import sonia.scm.repository.spi.BranchesCommand; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +/** + * + * @author Sebastian Sdorra + */ +public final class BranchesCommandBuilder +{ + + /** name of the cache */ + static final String CACHE_NAME = "sonia.cache.cmd.branches"; + + /** + * the logger for BranchesCommandBuilder + */ + private static final Logger logger = + LoggerFactory.getLogger(BranchesCommandBuilder.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs a new {@link BlameCommandBuilder}, this constructor should + * only be called from the {@link RepositoryService}. + * + * @param cacheManager cache manager + * @param blameCommand implementation of the {@link BlameCommand} + * @param branchesCommand + * @param repository repository to query + * @param preProcessorUtil + */ + BranchesCommandBuilder(CacheManager cacheManager, + BranchesCommand branchesCommand, Repository repository) + { + this.cache = cacheManager.getCache(CacheKey.class, Branches.class, + CACHE_NAME); + this.branchesCommand = branchesCommand; + this.repository = repository; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + * @throws RepositoryException + */ + public Branches getBranches() throws RepositoryException, IOException + { + Branches branches = null; + + if (disableCache) + { + if (logger.isDebugEnabled()) + { + logger.debug("get branches for repository {} with disabled cache", + repository.getName()); + } + + branches = getBranchesFromCommand(); + } + else + { + CacheKey key = new CacheKey(repository); + + branches = cache.get(key); + + if (branches == null) + { + if (logger.isDebugEnabled()) + { + logger.debug("get branches for repository {}", repository.getName()); + } + + branches = getBranchesFromCommand(); + + if (branches != null) + { + cache.put(key, branches); + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("get branches for repository {} from cache", + repository.getName()); + } + } + + return branches; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Disables the cache for tags. This means that every {@link Branch} + * is directly retrieved from the {@link Repository}. Note: Disabling + * the cache cost a lot of performance and could be much more slower. + * + * + * @param disableCache true to disable the cache + * + * @return {@code this} + */ + public BranchesCommandBuilder setDisableCache(boolean disableCache) + { + this.disableCache = disableCache; + + return this; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + * @throws RepositoryException + */ + private Branches getBranchesFromCommand() + throws RepositoryException, IOException + { + return new Branches(branchesCommand.getBranches()); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Key for caching branches; + * + * + * @version Enter version here..., 12/07/05 + * @author Enter your name here... + */ + static class CacheKey implements RepositoryCacheKey + { + + /** + * Constructs ... + * + * + * @param repository + */ + public CacheKey(Repository repository) + { + this.repositoryId = repository.getId(); + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final CacheKey other = (CacheKey) obj; + + return Objects.equal(repositoryId, other.repositoryId); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(repositoryId); + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getRepositoryId() + { + return repositoryId; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String repositoryId; + } + + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private BranchesCommand branchesCommand; + + /** Field description */ + private Cache cache; + + /** Field description */ + private boolean disableCache = false; + + /** Field description */ + private Repository repository; +} diff --git a/scm-core/src/main/java/sonia/scm/repository/api/Command.java b/scm-core/src/main/java/sonia/scm/repository/api/Command.java index a2063a0cae..4f9b0d8fe1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/Command.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/Command.java @@ -46,5 +46,10 @@ public enum Command /** * @since 1.18 */ - TAGS + TAGS, + + /** + * @since 1.18 + */ + BRANCHES; } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java index b30dbd5794..23825d0ee5 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java @@ -48,6 +48,7 @@ import sonia.scm.HandlerEvent; import sonia.scm.cache.Cache; import sonia.scm.cache.CacheManager; import sonia.scm.repository.BlameResult; +import sonia.scm.repository.Branches; import sonia.scm.repository.BrowserResult; import sonia.scm.repository.ChangesetPagingResult; import sonia.scm.repository.PermissionType; @@ -313,6 +314,9 @@ public final class RepositoryServiceFactory ChangesetPagingResult.class, LogCommandBuilder.CACHE_NAME); this.tagsCache = cacheManager.getCache(TagsCommandBuilder.CacheKey.class, Tags.class, TagsCommandBuilder.CACHE_NAME); + this.branchesCache = + cacheManager.getCache(BranchesCommandBuilder.CacheKey.class, + Branches.class, BranchesCommandBuilder.CACHE_NAME); } //~--- methods ------------------------------------------------------------ @@ -373,6 +377,7 @@ public final class RepositoryServiceFactory browseCache.removeAll(filter); logCache.removeAll(filter); tagsCache.removeAll(filter); + branchesCache.removeAll(filter); } //~--- fields ------------------------------------------------------------- @@ -380,6 +385,9 @@ public final class RepositoryServiceFactory /** Field description */ private Cache blameCache; + /** Field description */ + private Cache branchesCache; + /** Field description */ private Cache browseCache; diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java new file mode 100644 index 0000000000..19ff289752 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java @@ -0,0 +1,63 @@ +/** + * 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.spi; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.repository.Branch; +import sonia.scm.repository.RepositoryException; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.List; + +/** + * + * @author Sebastian Sdorra + * @since 1.18 + */ +public interface BranchesCommand +{ + + /** + * Method description + * + * + * @return + * + * @throws IOException + * @throws RepositoryException + */ + public List getBranches() throws RepositoryException, IOException; +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java index 1ac925c706..e75b0e9aea 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java @@ -91,6 +91,17 @@ public abstract class RepositoryServiceProvider implements Closeable throw new CommandNotSupportedException(Command.BLAME); } + /** + * Method description + * + * + * @return + */ + public BranchesCommand getBranchesCommand() + { + throw new CommandNotSupportedException(Command.BRANCHES); + } + /** * Method description *