/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package br.uff.ic.oceano.core.tools.vcs; import br.uff.ic.oceano.core.control.ApplicationConstants; import br.uff.ic.oceano.core.exception.VCSException; import br.uff.ic.oceano.core.factory.ObjectFactory; import br.uff.ic.oceano.core.model.ConfigurationItem; import br.uff.ic.oceano.core.model.ProjectUser; import br.uff.ic.oceano.core.model.Revision; import br.uff.ic.oceano.core.model.SoftwareProject; import br.uff.ic.oceano.util.file.PathUtil; import br.uff.ic.oceano.ostra.model.Item; import br.uff.ic.oceano.ostra.model.VersionedItem; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.OutputStream; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import org.tmatesoft.svn.core.*; 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.internal.wc.DefaultSVNOptions; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.*; /** * * @author DanCastellani */ public class SVN_By_SVNKit implements VCS { private static final String name = "SVN"; private static final String rationale = "Subversion is a Version Control System"; private static Boolean FSRepositoryInitialized = false; private static Boolean DAVRepositoryInitialized = false; private static Boolean SVNRepositoryInitialized = false; private SVNClientManager getSVNClientManager(ProjectUser projectUser) { final DefaultSVNOptions myOptions = new DefaultSVNOptions(); if (projectUser.isAnonymous()) { return SVNClientManager.newInstance(myOptions); } else { return SVNClientManager.newInstance(myOptions, projectUser.getLogin(), projectUser.getPassword()); } } private ISVNAuthenticationManager getISVNAuthenticationManager(ProjectUser projectUser) { if (projectUser.isAnonymous()) { return SVNWCUtil.createDefaultAuthenticationManager(); } else { return SVNWCUtil.createDefaultAuthenticationManager(projectUser.getLogin(), projectUser.getPassword()); } } public Long getNumberOfHEADRevision(ProjectUser projectUser) throws VCSException { SVN_By_CommandLineInterface svn = ObjectFactory.getObjectWithDataBaseDependencies(SVN_By_CommandLineInterface.class); return svn.getNumberOfHEADRevision(projectUser); } public Revision doCheckout(Revision revision, ProjectUser projectUser, boolean createDirectory) throws VCSException { System.out.print("------------> preparing checkout... "); initRepositoryFactory(revision.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUser); try { SVNURL url; url = SVNURL.parseURIDecoded(revision.getProject().getRepositoryUrl()); if (createDirectory) { if (revision.getNumber() == null) { revision.setLocalPath(ApplicationConstants.DIR_BASE_CHECKOUTS + revision.getProject().getConfigurationItem().getName() + "-rHEAD"); } else { revision.setLocalPath(ApplicationConstants.DIR_BASE_CHECKOUTS + revision.getProject().getConfigurationItem().getName() + "-r" + revision.getNumber()); } } // else { // The directory is already bem setted // } File dir = new File(revision.getLocalPath()); if (dir.exists()) { if (dir.list() != null) { if (ApplicationConstants.DIRECTORY_MUST_BE_EMPITY_TO_CHECKOUT) { return revision; } else { throw new VCSException("O diretório [" + revision.getLocalPath() + "] deve estar vazio"); } } } else { dir.mkdir(); } clientManager.createRepository(url, true); SVNRevision svnRevision = SVNRevision.HEAD; if (revision.getNumber() != null) { svnRevision = SVNRevision.create(revision.getNumber()); } System.out.print(" begin checkout... "); clientManager.getUpdateClient().doCheckout(url, dir, SVNRevision.UNDEFINED, svnRevision, true); System.out.println(" done!"); } catch (SVNException ex) { Logger.getLogger(SVN_By_SVNKit.class.getName()).log(Level.SEVERE, null, ex); throw new VCSException(ex); } return revision; } public Revision doUpdate(Revision revision, ProjectUser projectUser, boolean updateFolderName) throws VCSException { System.out.print("------------> preparing update... "); initRepositoryFactory(revision.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUser); try { SVNURL url; url = SVNURL.parseURIDecoded(revision.getProject().getRepositoryUrl()); File dir = new File(revision.getLocalPath()); if (!dir.exists()) { throw new VCSException("O diretório [" + revision.getLocalPath() + "] deve ter uma revisão."); } clientManager.createRepository(url, true); // clientManager.getUpdateClient().doCheckout(url, dir, SVNRevision.UNDEFINED, SVNRevision.HEAD, true); System.out.print(" begin update... "); clientManager.getUpdateClient().doUpdate(dir, SVNRevision.create(revision.getNumber()), true); if (updateFolderName) { //change folder name to know the revision number revision.setLocalPath(revision.getLocalPath().substring(0, revision.getLocalPath().lastIndexOf("-r")) + "-r" + revision.getNumber()); dir.renameTo(new File(revision.getLocalPath())); } } catch (SVNException ex) { Logger.getLogger(SVN_By_SVNKit.class.getName()).log(Level.SEVERE, null, ex); throw new VCSException(ex); } System.out.println(" done!"); return revision; } public String getName() { return name; } public String getRationale() { return rationale; } public Set<Revision> getRevisions(SoftwareProject project, ProjectUser projectUser) throws VCSException { initRepositoryFactory(project.getRepositoryUrl()); Revision revision; Set<Revision> revisions = new LinkedHashSet<Revision>(); Set<VersionedItem> files; // DAVRepositoryFactory.setup(); long startRevision = 0; long endRevision = -1; Calendar cal; SVNRepository repository = null; Set changedPathsSet; Iterator changedPaths; try { repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(project.getRepositoryUrl())); ISVNAuthenticationManager authManager = getISVNAuthenticationManager(projectUser); if (projectUser.isAnonymous()) { authManager = SVNWCUtil.createDefaultAuthenticationManager(); } else { authManager = SVNWCUtil.createDefaultAuthenticationManager(projectUser.getLogin(), projectUser.getPassword()); } repository.setAuthenticationManager(authManager); Collection logEntries = null; logEntries = repository.log(new String[]{""}, null, startRevision, endRevision, true, true); SVNLogEntry logEntry; Iterator entries = logEntries.iterator(); while (entries.hasNext()) { logEntry = (SVNLogEntry) entries.next(); revision = new Revision(); revision.setProject(project); revision.setNumber(logEntry.getRevision()); revision.setCommiter(logEntry.getAuthor()); cal = Calendar.getInstance(); cal.setTime(logEntry.getDate()); revision.setCommitDate(cal); revision.setMessage(logEntry.getMessage()); if (logEntry.getChangedPaths().size() > 0) { changedPathsSet = logEntry.getChangedPaths().keySet(); changedPaths = changedPathsSet.iterator(); files = new LinkedHashSet<VersionedItem>(); while (changedPaths.hasNext()) { SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry.getChangedPaths().get(changedPaths.next()); //ignores entries from other paths than the project's path if (!entryPath.getPath().startsWith(repository.getRepositoryPath(""))) { continue; } int init = project.getRepositoryUrl().indexOf(repository.getRepositoryRoot(true).getPath()); init += repository.getRepositoryRoot(true).getPath().length(); final int basePathLenght = project.getRepositoryUrl().substring(init).length(); // System.out.println("basePath = " + project.getRepositoryUrl().substring(init)); // System.out.println("fullFilePath = " + entryPath.getPath()); String filePath = entryPath.getPath(); // System.out.println("filePath.length() - basePathLenght=" + (filePath.length() - basePathLenght)); if ((filePath.length() - basePathLenght) > 0) { filePath = entryPath.getPath().substring(basePathLenght); VersionedItem vi = new VersionedItem(); vi.setItem(new Item(filePath)); vi.setRevision(revision); vi.setType(entryPath.getType()); files.add(vi); } } //files change in loop and so its hashcode revision.setChangedFiles(files); // System.out.println("files = " + files); } revisions.add(revision); } } catch (SVNException ex) { throw new VCSException(ex); } return revisions; } public Revision getRevision(SoftwareProject project, ProjectUser projectUser, Calendar calendar) throws VCSException { initRepositoryFactory(project.getRepositoryUrl()); try { Revision revision = new Revision(); revision.setProject(project); long startRevision = 0; long endRevision = -1; Calendar cal; Set changedPathsSet; Iterator changedPaths; SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(project.getRepositoryUrl())); ISVNAuthenticationManager authManager = getISVNAuthenticationManager(projectUser); repository.setAuthenticationManager(authManager); Collection logEntries = repository.log(new String[]{""}, null, startRevision, endRevision, true, true); SVNLogEntry logEntry, auxlogEntry; Iterator entries = logEntries.iterator(); logEntry = (SVNLogEntry) entries.next(); auxlogEntry = logEntry; while (entries.hasNext() && ((calendar.getTime().compareTo(logEntry.getDate())) >= 0)) { logEntry = (SVNLogEntry) entries.next(); if ((calendar.getTime().compareTo(logEntry.getDate())) >= 0) { auxlogEntry = logEntry; } } logEntry = auxlogEntry; revision.setNumber(logEntry.getRevision()); revision.setCommiter(logEntry.getAuthor()); cal = Calendar.getInstance(); cal.setTime(logEntry.getDate()); revision.setCommitDate(cal); if (logEntry.getChangedPaths().size() > 0) { changedPathsSet = logEntry.getChangedPaths().keySet(); changedPaths = changedPathsSet.iterator(); Set<VersionedItem> files = new LinkedHashSet<VersionedItem>(); while (changedPaths.hasNext()) { SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry.getChangedPaths().get(changedPaths.next()); int init = project.getRepositoryUrl().indexOf(repository.getRepositoryRoot(true).getPath()); init += repository.getRepositoryRoot(true).getPath().length(); final int basePathLenght = project.getRepositoryUrl().substring(init).length(); String filePath = entryPath.getPath(); if ((filePath.length() - basePathLenght) > 0) { filePath = entryPath.getPath().substring(basePathLenght); VersionedItem vi = new VersionedItem(); vi.setItem(new Item(filePath)); vi.setRevision(revision); vi.setType(entryPath.getType()); files.add(vi); } } revision.setChangedFiles(files); } return revision; } catch (Exception e) { throw new VCSException(e); } } public Revision getRevision(SoftwareProject project, ProjectUser projectUser, Long revisionNumber) throws VCSException { initRepositoryFactory(project.getRepositoryUrl()); try { Revision revision = new Revision(); revision.setProject(project); ISVNAuthenticationManager authManager = getISVNAuthenticationManager(projectUser); SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(project.getRepositoryUrl())); repository.setAuthenticationManager(authManager); //Collection logEntries = repository.log(new String[]{""}, null, revisionNumber, revisionNumber, true, false); final List<SVNLogEntry> logEntries = new LinkedList<SVNLogEntry>(); String[] paths = new String[]{""}; String[] properties = null;//to get all properties ISVNLogEntryHandler handler = new ISVNLogEntryHandler() { public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { logEntries.add(logEntry); } }; boolean getChangedPaths = true; boolean getMergedNodes = true; repository.log(paths,revisionNumber, revisionNumber,getChangedPaths,false,1, getMergedNodes, properties,handler); if (logEntries == null || logEntries.isEmpty()) { return null; } /*else if (logEntries.size() > 1) { throw new Exception("Too many log entries on revision " + revisionNumber); }*/ SVNLogEntry logEntry = (SVNLogEntry) logEntries.iterator().next(); revision.setNumber(logEntry.getRevision()); revision.setCommiter(logEntry.getAuthor()); Calendar cal = Calendar.getInstance(); cal.setTime(logEntry.getDate()); revision.setCommitDate(cal); Set changedPathsSet = logEntry.getChangedPaths().keySet(); Iterator changedPaths = changedPathsSet.iterator(); Set<VersionedItem> files = new LinkedHashSet<VersionedItem>(); while (changedPaths.hasNext()) { SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry.getChangedPaths().get(changedPaths.next()); int init = project.getRepositoryUrl().indexOf(repository.getRepositoryRoot(true).getPath()); init += repository.getRepositoryRoot(true).getPath().length(); final int basePathLenght = project.getRepositoryUrl().substring(init).length(); String filePath = entryPath.getPath(); if ((filePath.length() - basePathLenght) > 0) { filePath = entryPath.getPath().substring(basePathLenght); VersionedItem vi = new VersionedItem(); vi.setItem(new Item(filePath)); vi.setRevision(revision); vi.setType(entryPath.getType()); files.add(vi); } } revision.setChangedFiles(files); return revision; } catch (Exception e) { throw new VCSException(e); } } public synchronized void initRepositoryFactory(final String repositoryUrl) { if (repositoryUrl.matches("^file://.*$") && !FSRepositoryInitialized) { System.out.println("----------------> Initializing FSRepositoryFactory"); FSRepositoryFactory.setup(); FSRepositoryInitialized = true; } else if (repositoryUrl.matches("^https?://.*$") && !DAVRepositoryInitialized) { System.out.println("----------------> Initializing DAVRepositoryFactory"); DAVRepositoryFactory.setup(); DAVRepositoryInitialized = true; } else if (repositoryUrl.matches("^svn(\\+.+)?://.*$") && !SVNRepositoryInitialized) { System.out.println("----------------> Initializing SVNRepositoryFactory"); SVNRepositoryFactoryImpl.setup(); DAVRepositoryInitialized = true; } } public OutputStream doDiff(ProjectUser projectUser, String urlMainBranch, String urlSecondaryBranch, Long numberRevision) throws VCSException { System.out.print("------------> preparing doDiff... "); OutputStream resultDiff = null; initRepositoryFactory(projectUser.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUser); try { //calculo responsavel em fazer o diff SVNDiffClient diffClient = clientManager.getDiffClient(); resultDiff = new ByteArrayOutputStream(); SVNURL repo1 = SVNURL.parseURIEncoded(urlMainBranch); SVNURL repo2 = SVNURL.parseURIEncoded(urlSecondaryBranch); SVNRevision svnRevision = SVNRevision.create(numberRevision.longValue()); System.out.print(" begin doDiff... "); diffClient.doDiff(repo1, svnRevision, repo2, svnRevision, SVNDepth.INFINITY, true, resultDiff); } catch (SVNException ex) { Logger.getLogger(SVN_By_SVNKit.class.getName()).log(Level.SEVERE, null, ex); throw new VCSException(ex); } System.out.println(" done!"); return resultDiff; } public List<String> getBranches(SoftwareProject project, ProjectUser projectUser) throws VCSException { System.out.print("------------> preparing getBranches... "); List<String> branchList = new ArrayList<String>(); initRepositoryFactory(project.getRepositoryUrl()); try { ISVNAuthenticationManager aManager = getISVNAuthenticationManager(projectUser); ConfigurationItem ci = project.getConfigurationItem(); String urlBranch = PathUtil.getWellFormedURL(ci.getBaseUrl(), ci.getBranchPath()); SVNURL url = SVNURL.parseURIEncoded(urlBranch); SVNRepository repos = SVNRepositoryFactory.create(url); repos.setAuthenticationManager(aManager); System.out.print(" begin getBranches... "); System.out.println("urlBranch: " + urlBranch); long headRevision = repos.getLatestRevision(); Collection<SVNDirEntry> entriesList = repos.getDir("", headRevision, null, (Collection) null); branchList.add(ci.getTrunkPath()); //branchList.add("trunk"); for (SVNDirEntry entry : entriesList) { branchList.add(entry.getName()); System.out.println("Entrada: " + entry.getName()); } } catch (SVNException ex) { Logger.getLogger(SVN_By_SVNKit.class.getName()).log(Level.SEVERE, null, ex); throw new VCSException(ex); } System.out.println(" done!"); return branchList; } public void doFullRevert(File[] paths) throws VCSException { SVNWCClient cliente; ISVNAuthenticationManager auth = null; cliente = new SVNWCClient(auth, null); try { cliente.doRevert(paths, SVNDepth.INFINITY, null); } catch (SVNException ex) { Logger.getLogger(SVN_By_SVNKit.class.getName()).log(Level.SEVERE, null, ex); throw new VCSException(ex); } } public void doCopyTo(String pathWorkspace, ProjectUser projectUser, String urlDst) throws VCSException { initRepositoryFactory(projectUser.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUser); SVNURL sVNurlDst = null; try { sVNurlDst = SVNURL.parseURIDecoded(urlDst); } catch (SVNException ex) { throw new VCSException(ex); } SVNCopySource copySource = new SVNCopySource(SVNRevision.WORKING, SVNRevision.HEAD, new File(pathWorkspace)); SVNCopySource[] copySources = new SVNCopySource[]{copySource}; try { clientManager.getCopyClient().doCopy(copySources, sVNurlDst, false, true, true, "Message Commit CopyTo", null); } catch (SVNException ex) { throw new VCSException(ex); } } public Long doCommit(String pathWorkspace, ProjectUser projectUserChanged, String commitMessage) throws VCSException { initRepositoryFactory(projectUserChanged.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUserChanged); try { return clientManager.getCommitClient().doCommit(new File[]{new File(pathWorkspace)}, true, commitMessage, null, null, true, true, SVNDepth.INFINITY).getNewRevision(); } catch (SVNException ex) { throw new VCSException(ex); } } public Long doSwitchTo(String pathWorkspace, ProjectUser projectUserChanged, String urlTarget) throws VCSException { initRepositoryFactory(projectUserChanged.getProject().getRepositoryUrl()); SVNClientManager clientManager = getSVNClientManager(projectUserChanged); try { return clientManager.getUpdateClient().doSwitch(new File(pathWorkspace), SVNURL.parseURIDecoded(urlTarget), SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, false, true); } catch (SVNException ex) { throw new VCSException(ex); } } public Long doCheckout(File createdFileToworkspace, ProjectUser projectUser) throws VCSException { initRepositoryFactory(projectUser.getProject().getRepositoryUrl()); DefaultSVNOptions myOptions = new DefaultSVNOptions(); myOptions.setInteractiveConflictResolution(false); ISVNAuthenticationManager authenticationManager = getISVNAuthenticationManager(projectUser); SVNClientManager clientManager = SVNClientManager.newInstance(myOptions, authenticationManager); try { return clientManager.getUpdateClient().doCheckout(SVNURL.parseURIDecoded(projectUser.getProject().getRepositoryUrl()), createdFileToworkspace, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, true); } catch (SVNException ex) { throw new VCSException(ex); } } }