diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnCollectionRenderer.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnCollectionRenderer.java index 3665a67506..34f6a75cb8 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnCollectionRenderer.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnCollectionRenderer.java @@ -33,23 +33,42 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.io.Closeables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Ordering; import com.google.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.server.dav.CollectionRenderer; +import org.tmatesoft.svn.core.internal.server.dav.DAVPathUtil; import org.tmatesoft.svn.core.internal.server.dav.DAVResource; +import org.tmatesoft.svn.core.internal.server.dav.DAVResourceURI; +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryProvider; import sonia.scm.template.Template; import sonia.scm.template.TemplateEngine; import sonia.scm.template.TemplateEngineFactory; +import sonia.scm.url.RepositoryUrlProvider; +import sonia.scm.url.UrlProvider; +import sonia.scm.url.UrlProviderFactory; +import sonia.scm.util.HttpUtil; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; import java.io.StringWriter; +import java.util.Iterator; +import java.util.List; + /** * * @author Sebastian Sdorra @@ -61,18 +80,31 @@ public class SvnCollectionRenderer implements CollectionRenderer private static final String RESOURCE_SVNINDEX = "sonia/scm/svn.index.mustache"; + /** + * the logger for SvnCollectionRenderer + */ + private static final Logger logger = + LoggerFactory.getLogger(SvnCollectionRenderer.class); + //~--- constructors --------------------------------------------------------- /** * Constructs ... * * + * + * @param configuration * @param templateEngineFactory + * @param repositoryProvider */ @Inject - public SvnCollectionRenderer(TemplateEngineFactory templateEngineFactory) + public SvnCollectionRenderer(ScmConfiguration configuration, + TemplateEngineFactory templateEngineFactory, + RepositoryProvider repositoryProvider) { + this.configuration = configuration; this.templateEngineFactory = templateEngineFactory; + this.repositoryProvider = repositoryProvider; } //~--- methods -------------------------------------------------------------- @@ -98,19 +130,354 @@ public class SvnCollectionRenderer implements CollectionRenderer { Template template = engine.getTemplate(RESOURCE_SVNINDEX); - template.execute(writer, new Object()); + template.execute(writer, createRepositoryWrapper(resource)); } catch (IOException ex) { - throw new SVNException(SVNErrorMessage.UNKNOWN_ERROR_MESSAGE); + logger.error("could not render directory", ex); + + throw new SVNException(SVNErrorMessage.UNKNOWN_ERROR_MESSAGE, ex); } writer.flush(); buffer.append(writer.toString()); } + /** + * Method description + * + * + * @param resource + * + * @return + * + * @throws SVNException + */ + private RepositoryWrapper createRepositoryWrapper(DAVResource resource) + throws SVNException + { + Builder entries = ImmutableList.builder(); + + DAVResourceURI uri = resource.getResourceURI(); + String path = uri.getPath(); + + if (!HttpUtil.SEPARATOR_PATH.equals(path)) + { + String completePath = HttpUtil.append(uri.getContext(), path); + String parent = DAVPathUtil.removeTail(completePath, true); + + entries.add(new DirectoryEntry("..", parent, true)); + } + + for (Iterator iterator = resource.getEntries().iterator(); + iterator.hasNext(); ) + { + SVNDirEntry entry = (SVNDirEntry) iterator.next(); + + entries.add(new DirectoryEntry(resource, entry)); + } + + UrlProvider urlProvider = + UrlProviderFactory.createUrlProvider(configuration.getBaseUrl(), + UrlProviderFactory.TYPE_WUI); + + //J- + return new RepositoryWrapper( + urlProvider.getRepositoryUrlProvider(), + repositoryProvider.get(), + resource, + new DirectoryOrdering().immutableSortedCopy(entries.build()) + ); + //J+ + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 13/11/10 + * @author Enter your name here... + */ + private static class DirectoryEntry + { + + /** + * Constructs ... + * + * + * @param resource + * @param entry + */ + public DirectoryEntry(DAVResource resource, SVNDirEntry entry) + { + this.name = entry.getName(); + this.url = createUrl(resource, entry); + this.directory = entry.getKind() == SVNNodeKind.DIR; + } + + /** + * Constructs ... + * + * + * @param name + * @param url + * @param directory + */ + public DirectoryEntry(String name, String url, boolean directory) + { + this.name = name; + this.url = url; + this.directory = directory; + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + /** + * Method description + * + * + * @return + */ + public String getUrl() + { + return url; + } + + /** + * Method description + * + * + * @return + */ + public boolean isDirectory() + { + return directory; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param resource + * @param entry + * + * @return + */ + private String createUrl(DAVResource resource, SVNDirEntry entry) + { + StringBuilder buffer = new StringBuilder(); + + buffer.append(resource.getResourceURI().getContext()); + + String path = resource.getResourceURI().getPath(); + + if (!HttpUtil.SEPARATOR_PATH.equals(path)) + { + buffer.append(path); + } + + buffer.append(DAVPathUtil.standardize(entry.getName())); + + if (isDirectory()) + { + buffer.append(HttpUtil.SEPARATOR_PATH); + } + + return buffer.toString(); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final boolean directory; + + /** Field description */ + private final String name; + + /** Field description */ + private final String url; + } + + + /** + * Class description + * + * + * @version Enter version here..., 13/11/10 + * @author Enter your name here... + */ + private static class DirectoryOrdering extends Ordering + { + + /** + * Method description + * + * + * @param left + * @param right + * + * @return + */ + @Override + public int compare(DirectoryEntry left, DirectoryEntry right) + { + int result; + + if (left.isDirectory() &&!right.isDirectory()) + { + result = -1; + } + else if (!left.isDirectory() && right.isDirectory()) + { + result = 1; + } + else + { + if ("..".equals(left.getName())) + { + result = -1; + } + else if ("..".equals(right.getName())) + { + result = 1; + } + else + { + result = left.getName().compareTo(right.getName()); + } + } + + return result; + } + } + + + /** + * Class description + * + * + * @version Enter version here..., 13/11/10 + * @author Enter your name here... + */ + private static class RepositoryWrapper + { + + /** + * Constructs ... + * + * + * + * @param repositoryUrlProvider + * @param repository + * @param resource + * @param entries + */ + public RepositoryWrapper(RepositoryUrlProvider repositoryUrlProvider, + Repository repository, DAVResource resource, List entries) + { + this.repositoryUrlProvider = repositoryUrlProvider; + this.repository = repository; + this.resource = resource; + this.entries = entries; + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getCommitViewLink() + { + return repositoryUrlProvider.getChangesetUrl(repository.getId(), 0, 20); + } + + /** + * Method description + * + * + * @return + */ + public List getEntries() + { + return entries; + } + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return repository.getName(); + } + + /** + * Method description + * + * + * @return + */ + public Repository getRepository() + { + return repository; + } + + /** + * Method description + * + * + * @return + */ + public String getSourceViewLink() + { + return repositoryUrlProvider.getBrowseUrl(repository.getId(), + resource.getResourceURI().getPath(), null); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final List entries; + + /** Field description */ + private final Repository repository; + + /** Field description */ + private final RepositoryUrlProvider repositoryUrlProvider; + + /** Field description */ + private final DAVResource resource; + } + + //~--- fields --------------------------------------------------------------- + /** Field description */ + private final ScmConfiguration configuration; + + /** Field description */ + private final RepositoryProvider repositoryProvider; + /** Field description */ private final TemplateEngineFactory templateEngineFactory; } diff --git a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.index.mustache b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.index.mustache index 76808f828b..11e521b547 100644 --- a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.index.mustache +++ b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.index.mustache @@ -33,7 +33,7 @@ - SCM :: Manager - Subversion Repository + SCM :: Manager - Subversion Repository - {{name}}