/* * Copyright (c) 2005-2016 Flamingo Kirill Grouchnikov. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o 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. * * o Neither the name of Flamingo Kirill Grouchnikov 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 COPYRIGHT OWNER 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. */ package org.pushingpixels.flamingo.api.bcb.core; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.pushingpixels.flamingo.api.bcb.BreadcrumbBarCallBack; import org.pushingpixels.flamingo.api.bcb.BreadcrumbBarException; import org.pushingpixels.flamingo.api.bcb.BreadcrumbItem; import org.pushingpixels.flamingo.api.bcb.JBreadcrumbBar; import org.pushingpixels.flamingo.api.common.StringValuePair; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.SVNWCUtil; /** * Breadcrumb bar that allows browsing a single local / remote SVN repository. * The implementation uses <a href="http://www.svnkit.com">SVNKit</a> library. * Make sure to read the <a * href="http://www.svnkit.com/licensing/index.html">licensing terms</a> before * using this component in your application. * * @author Kirill Grouchnikov */ public class BreadcrumbSvnSelector extends JBreadcrumbBar<String> { /** * SVN-specific implementation of the {@link BreadcrumbBarCallBack}. * * @author Kirill Grouchnikov */ public static class PathCallback extends BreadcrumbBarCallBack<String> { /** * Repository URL. */ private String url; /** * User name. */ private String userName; /** * Password. */ private String password; /** * The actual SVN repository. */ private SVNRepository repository; /** * Creates a new callback. * * @param url * Repository URL. * @param userName * User name. * @param password * Password. */ public PathCallback(String url, String userName, String password) { this.url = url; this.userName = userName; this.password = password; } /* * (non-Javadoc) * * @see org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#setup() */ @Override public void setup() throws BreadcrumbBarException { DAVRepositoryFactory.setup(); SVNRepositoryFactoryImpl.setup(); FSRepositoryFactory.setup(); try { this.repository = SVNRepositoryFactory.create(SVNURL .parseURIEncoded(this.url)); ISVNAuthenticationManager authManager = SVNWCUtil .createDefaultAuthenticationManager(this.userName, this.password); this.repository.setAuthenticationManager(authManager); } catch (SVNException svne) { if (this.throwsExceptions) { throw new BreadcrumbBarException(svne); } } } /* * (non-Javadoc) * * @see * org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#getPathChoices(java. * util.List) */ @Override public List<StringValuePair<String>> getPathChoices( List<BreadcrumbItem<String>> path) throws BreadcrumbBarException { String lastPath = (path == null) ? "" : path.get(path.size() - 1) .getData(); try { return BreadcrumbSvnSelector.getPathChoices(this.repository, lastPath); } catch (SVNException svne) { if (this.throwsExceptions) { throw new BreadcrumbBarException(svne); } return null; } } /* * (non-Javadoc) * * @see * org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#getLeafs(java.util.List) */ @Override public List<StringValuePair<String>> getLeafs( List<BreadcrumbItem<String>> path) throws BreadcrumbBarException { String lastPath = (path == null) ? "" : path.get(path.size() - 1) .getData(); try { return BreadcrumbSvnSelector .getLeafs(this.repository, lastPath); } catch (SVNException svne) { svne.printStackTrace(); return null; } } /* * (non-Javadoc) * * @see * org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#getLeafContent(java. * lang.Object) */ @Override public InputStream getLeafContent(String leaf) throws BreadcrumbBarException { try { return BreadcrumbSvnSelector.getLeafContent(this.repository, leaf); } catch (SVNException svne) { return null; } } } /** * Creates a new empty breadcrumb bar that is not connected to any SVN * repository. */ public BreadcrumbSvnSelector() { super(null); } /** * Creates a new breadcrumb bar to browse the specified SVN repository. The * actual connection is done off EDT so that the application remains * responsive. * * @param url * Repository URL. * @param userName * User name. * @param password * Password. */ public BreadcrumbSvnSelector(String url, String userName, String password) { super(new PathCallback(url, userName, password)); } /** * Sets the connection parameters. The breadcrumb bar path is reset to the * root of thew specified SVN repository. * * @param url * Repository URL. * @param userName * User name. * @param password * Password. */ public void setConnectionParams(String url, String userName, String password) { this.setConnectionParams(url, userName, password, false); } /** * Sets the connection parameters. The breadcrumb bar path is reset to the * root of thew specified SVN repository. * * @param url * Repository URL. * @param userName * User name. * @param password * Password. * @param throwsException * Indicates whether the inner exceptions should be reported to * the registered exception handlers. */ public void setConnectionParams(String url, String userName, String password, boolean throwsException) { this.callback = new PathCallback(url, userName, password); this.callback.setup(); this.callback.setThrowsExceptions(throwsException); this.setPath(new LinkedList<BreadcrumbItem<String>>()); } /** * Returns the contents of the specified repository file. * * @param repository * SVN repository. * @param leaf * Full path to the file. * @return Contents of the specified repository file. * @throws SVNException */ @SuppressWarnings("unchecked") protected static InputStream getLeafContent(SVNRepository repository, String leaf) throws SVNException { Map fileProperties = new HashMap(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); repository.getFile(leaf, -1, SVNProperties.wrap(fileProperties), baos); return new ByteArrayInputStream(baos.toByteArray()); } /** * Returns a list of all the files in the specified folder. * * @param repository * SVN repository. * @param path * Full path to the folder. * @return List of all the files in the specified folder. * @throws SVNException */ @SuppressWarnings("unchecked") protected static List<StringValuePair<String>> getLeafs( SVNRepository repository, String path) throws SVNException { List<StringValuePair<String>> result = new ArrayList<StringValuePair<String>>(); Collection entries = repository.getDir(path, -1, null, (Collection) null); Iterator iterator = entries.iterator(); while (iterator.hasNext()) { SVNDirEntry entry = (SVNDirEntry) iterator.next(); if (entry.getKind() == SVNNodeKind.FILE) { String prefix = ((path == null) || (path.length() == 0)) ? "" : path + "/"; StringValuePair<String> leafInfo = new StringValuePair<String>( entry.getName(), prefix + entry.getName()); leafInfo.set("size", entry.getSize()); leafInfo.set("author", entry.getAuthor()); leafInfo.set("date", entry.getDate()); leafInfo.set("revision", entry.getRevision()); result.add(leafInfo); } } Collections.sort(result, new Comparator<StringValuePair<String>>() { public int compare(StringValuePair<String> o1, StringValuePair<String> o2) { return o1.getKey().compareTo(o2.getKey()); } }); return result; } /** * Returns a list of all the foldes in the specified folder. * * @param repository * SVN repository. * @param path * Full path to the folder. * @return List of all the folders in the specified folder. * @throws SVNException */ @SuppressWarnings("unchecked") protected static List<StringValuePair<String>> getPathChoices( SVNRepository repository, String path) throws SVNException { List<StringValuePair<String>> result = new ArrayList<StringValuePair<String>>(); Collection entries = repository.getDir(path, -1, null, (Collection) null); Iterator iterator = entries.iterator(); while (iterator.hasNext()) { SVNDirEntry entry = (SVNDirEntry) iterator.next(); if (entry.getKind() == SVNNodeKind.DIR) { String prefix = ((path == null) || (path.length() == 0)) ? "" : path + "/"; result.add(new StringValuePair<String>(entry.getName(), prefix + entry.getName())); } } Collections.sort(result, new Comparator<StringValuePair<String>>() { public int compare(StringValuePair<String> o1, StringValuePair<String> o2) { return o1.getKey().compareTo(o2.getKey()); } }); return result; } }