package org.jggug.hudson.plugins.gcrawler.scm; import static org.tmatesoft.svn.core.SVNNodeKind.DIR; import static org.tmatesoft.svn.core.SVNNodeKind.FILE; import static org.tmatesoft.svn.core.SVNURL.parseURIDecoded; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNClientManager; public class SubversionRepository implements RepositoryWrapper { static { DAVRepositoryFactory.setup(); SVNRepositoryFactoryImpl.setup(); } private SVNRepository repository; public SubversionRepository(String repositoryURL) throws RepositoryException { this(repositoryURL, false); } public SubversionRepository(String repositoryURL, boolean isFixedUrl) throws RepositoryException { try { SVNURL svnUrl = SVNURL.parseURIDecoded(repositoryURL); repository = SVNClientManager.newInstance().createRepository(svnUrl, false); } catch (SVNException e) { throw new RepositoryException(e); } if (isFixedUrl) return; try { for (SVNDirEntry entry : dir("")) { if (entry.getKind() == DIR && entry.getName().equals("trunk")) { repository = SVNClientManager.newInstance().createRepository(parseURIDecoded(repositoryURL + "trunk"), false); return; } } throw new TrunkNotFoundException(); } catch (SVNException e) { try { repository = SVNClientManager.newInstance().createRepository(parseURIDecoded(repositoryURL + "/trunk"), false); } catch (SVNException e1) { throw new RepositoryException(e1); } } } public FileInfo findFile(String name) throws FileNotFoundException, RepositoryException { boolean hasTrunk = repository.getLocation().toString().endsWith("trunk"); return findFile((hasTrunk ? "" : "trunk"), name); } private List<SVNDirEntry> dir(String path) throws SVNException { List<SVNDirEntry> entries = new ArrayList<SVNDirEntry>(); repository.getDir(path, -1, false, entries); return entries; } private FileInfo findFile(String parent, String name) throws FileNotFoundException, RepositoryException { List<SVNDirEntry> entries = new ArrayList<SVNDirEntry>(); try { repository.getDir(parent, -1, false, entries); Collections.sort(entries, FileFirstSVNDirEntryComparator.C); for (SVNDirEntry entry : entries) { if (entry.getKind() == FILE) { if (entry.getName().equals(name)) { return getFile((StringUtils.isEmpty(parent) ? "" : parent.concat("/")).concat(entry.getRelativePath())); } } else if (entry.getKind() == DIR) { try { return findFile((StringUtils.isEmpty(parent) ? "" : parent + "/") + entry.getName(), name); } catch (FileNotFoundException e) {} } } } catch (SVNException e) { throw new RepositoryException(e); } throw new FileNotFoundException(name); } public boolean existsFileByPattern(Pattern pattern) throws RepositoryException { boolean hasTrunk = repository.getLocation().toString().endsWith("trunk"); return existsFileByPattern((hasTrunk ? "" : "trunk"), pattern); } private boolean existsFileByPattern(String parent, Pattern pattern) throws RepositoryException { List<SVNDirEntry> entries = new ArrayList<SVNDirEntry>(); try { repository.getDir(parent, -1, false, entries); Collections.sort(entries, FileFirstSVNDirEntryComparator.C); for (SVNDirEntry entry : entries) { if (entry.getKind() == FILE) { if (pattern.matcher(entry.getURL().toString()).matches()) { return true; } } else if (entry.getKind() == DIR) { boolean exists = existsFileByPattern( (StringUtils.isEmpty(parent) ? "" : parent + "/") + entry.getName(), pattern); if (exists) { return true; } } } } catch (SVNException e) { throw new RepositoryException(e); } return false; } public FileInfo getFile(String path) throws FileNotFoundException, RepositoryException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { repository.getFile(path, -1, null, out); FileInfo result = new FileInfo(); String url = repository.getLocation().toString(); url += url.endsWith("/") ? path : "/".concat(path); result.setUrl(url); result.setContent(new String(out.toByteArray(), "UTF-8")); return result; } catch (SVNException e) { throw new RepositoryException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public long getLatestRevision() { try { return repository.getLatestRevision(); } catch (SVNException e) { throw new RuntimeException(e); } } protected static class FileFirstSVNDirEntryComparator implements Comparator<SVNDirEntry> { protected static final FileFirstSVNDirEntryComparator C = new FileFirstSVNDirEntryComparator(); private FileFirstSVNDirEntryComparator() {} public int compare(SVNDirEntry l, SVNDirEntry r) { if (l.getKind() == FILE) { if (r.getKind() == FILE) { return l.compareTo(r); } return -1; } if (r.getKind() == FILE) { return 1; } return l.compareTo(r); } } }