/* * DrakkarKeel - An Enterprise Collaborative Search Platform * * The contents of this file are subject under the terms described in the * DRAKKARKEEL_LICENSE file included in this distribution; you may not use this * file except in compliance with the License. * * 2013-2014 DrakkarKeel Platform. */ package drakkar.oar.svn; import drakkar.oar.Response; import drakkar.oar.facade.event.FacadeDesktopEvent; import drakkar.oar.facade.event.FacadeDesktopListener; import static drakkar.oar.util.KeyMessage.*; import static drakkar.oar.util.KeyTransaction.*; import drakkar.oar.util.NotifyAction; import drakkar.oar.util.OutputMonitor; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; 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.SVNProperty; 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.SVNRevision; import org.tmatesoft.svn.core.wc.SVNWCUtil; /** * Clase que contiene métodos de acceso a un repositorio SVN */ public class SVNController { //identificador string: nombre del repositorio //SVNData: datos de ese repositorio guardados en la BD private Map<String, SVNData> svnRepositoriesDB = new HashMap<>(); FacadeDesktopListener listener; /** * * @param listener */ public SVNController(FacadeDesktopListener listener) { this.listener = listener; } /** * Verifies if a repository exists in a given url * * @param url * @param name * @param password * @return */ public boolean existRepository(String url, String name, String password) { setupLibrary(); SVNRepository repository = null; try { /* * Creates an instance of SVNRepository to work with the repository. * All user's requests to the repository are relative to the * repository location used to create this SVNRepository. * SVNURL is a wrapper for URL strings that refer to repository locations. */ repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); } catch (SVNException svne) { /* * Perhaps a malformed URL is the cause of this exception */ String message = "Error while creating an SVNRepository for location " + url + "\n" + svne.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); return false; } ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password); repository.setAuthenticationManager(authManager); try { repository.testConnection(); OutputMonitor.printLine("Repository Root: " + repository.getRepositoryRoot(true), OutputMonitor.INFORMATION_MESSAGE); repository.closeSession(); } catch (SVNException ex) { String message = "Error: " + ex.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); return false; } return true; } /** * Get the number of documents of an SVN repository * * @param url * @param name * @param password * @return */ public int getRepositorySize(String url, String name, String password) { SVNRepository repository = null; int count = 0; try { repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); } catch (SVNException svne) { String message = "Error while creating an SVNRepository for location '" + "\n" + url + "': " + "\n" + svne.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password); repository.setAuthenticationManager(authManager); SVNNodeKind nodeKind = null; try { nodeKind = repository.checkPath("", -1); } catch (SVNException ex) { String message = "Error " + ex.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); } if (nodeKind == SVNNodeKind.NONE) { String message = "There is no entry at '" + url + "'."; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } else if (nodeKind == SVNNodeKind.FILE) { String message = "The entry at '" + url + "' is a file while a directory was expected."; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } try { /* * Get the number of files in the repository */ count = listEntries(repository, "", count); } catch (SVNException ex) { String message = "Error: " + ex.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } return count; } /** * Gets the file's content located in an SVN Repository * * @param url address of the repository (Example: https://your-c7096bbd5b:8443/svn/MyRepository/) * @param user user name for authenticate in the SVN repository * @param password password for authenticate in the SVN repository * @param filePath path of the file to open (/SVNDemo/src/util/MainSearch.java) * @param outPath file where will be save the file * * */ public void displayFile(String url, String user, String password, String filePath, String outPath) { SVNRepository repository = null; setupLibrary(); try { /* * Creates an instance of SVNRepository to work with the repository. * All user's requests to the repository are relative to the * repository location used to create this SVNRepository. * SVNURL is a wrapper for URL strings that refer to repository locations. */ repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); } catch (SVNException svne) { /* * Perhaps a malformed URL is the cause of this exception */ String message = "Error while creating an SVNRepository for location " + url; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } /* * User's authentication information (name/password) is provided via an * ISVNAuthenticationManager instance. SVNWCUtil creates a default * authentication manager given user's name and password. * * Default authentication manager first attempts to use provided user name * and password and then falls back to the credentials stored in the * default Subversion credentials storage that is located in Subversion * configuration area. If you'd like to use provided user name and password * only you may use BasicAuthenticationManager class instead of default * authentication manager: * * authManager = new BasicAuthenticationsManager(userName, userPassword); * * You may also skip this point - anonymous access will be used. */ ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(user, password); repository.setAuthenticationManager(authManager); /* * This Map will be used to get the file properties. Each Map key is a * property name and the value associated with the key is the property * value. */ SVNProperties fileProperties = new SVNProperties(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { /* * Checks up if the specified path really corresponds to a file. If * doesn't the program exits. SVNNodeKind is that one who says what is * located at a path in a revision. -1 means the latest revision. */ SVNNodeKind nodeKind = repository.checkPath(filePath, -1); if (nodeKind == SVNNodeKind.NONE) { String message = "There is no entry at '" + url + "'."; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } else if (nodeKind == SVNNodeKind.DIR) { String message = "The entry at '" + url + "' is a directory while a file was expected."; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } /* * Gets the contents and properties of the file located at filePath * in the repository at the latest revision (which is meant by a * negative revision number). */ repository.getFile(filePath, -1, fileProperties, baos); } catch (SVNException svne) { String message = "Error while fetching the file contents and properties: " + "\n" + svne.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } /* * Here the SVNProperty class is used to get the value of the * svn:mime-type property (if any). SVNProperty is used to facilitate * the work with versioned properties. */ String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE); /* * SVNProperty.isTextMimeType(..) method checks up the value of the mime-type * file property and says if the file is a text (true) or not (false). */ boolean isTextType = SVNProperty.isTextMimeType(mimeType); Iterator iterator = fileProperties.nameSet().iterator(); /* * Displays file properties. */ while (iterator.hasNext()) { String propertyName = (String) iterator.next(); String propertyValue = fileProperties.getStringValue(propertyName); //esto muestra las propiedades del file svn OutputMonitor.printLine("File property: " + propertyName + "=" + propertyValue, OutputMonitor.INFORMATION_MESSAGE); } /* * Displays the file contents in the console if the file is a text. */ if (isTextType) { try { try (FileOutputStream output = new FileOutputStream(outPath)) { baos.writeTo(output); } } catch (IOException ex) { OutputMonitor.printStream("IO", ex); } } else { OutputMonitor.printLine("The mime-type property says that the file not a kind of a text file.", OutputMonitor.ERROR_MESSAGE); } /* * Gets the latest revision number of the repository */ long latestRevision = -1; try { latestRevision = repository.getLatestRevision(); } catch (SVNException svne) { String message = "Error while fetching the file contents and properties: " + "\n" + svne.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); notifyTaskProgress(ERROR_MESSAGE, message); } } /** * @return the svnRepositoriesDB */ public Map<String, SVNData> getSvnRepositoriesDB() { return svnRepositoriesDB; } /** * @param svnRepositoriesDB the svnRepositoriesDB to set */ public void setSvnRepositoriesDB(Map<String, SVNData> svnRepositoriesDB) { this.svnRepositoriesDB = svnRepositoriesDB; } /** * Obtiene la cantidad de repositorios que hay en la BD * * @return */ public int getRepositoryNumber() { return this.svnRepositoriesDB.size(); } /** * Este método notifica al servidor el progreso de las actividades invocadas * para actualizar el tablón de Log y Monitor. * * @param messageType tipo de mensage:<tt>INFORMATION_MESSAGE,ERROR_MESSAGE</tt> * @param message contenido del mensaje */ private void notifyTaskProgress(int messageType, String message) { if (listener != null) { Response rs = new Response(); rs.put(OPERATION, NotifyAction.NOTIFY_TEXT_MESSAGE); rs.put(MESSAGE_TYPE, messageType); rs.put(MESSAGE, message); FacadeDesktopEvent evt = new FacadeDesktopEvent(this, rs); listener.notify(evt); } } /** * Initializes the library to work with a repository via * different protocols. */ private static void setupLibrary() { /* * For using over http:// and https:// */ DAVRepositoryFactory.setup(); /* * For using over svn:// and svn+xxx:// */ SVNRepositoryFactoryImpl.setup(); /* * For using over file:/// */ FSRepositoryFactory.setup(); } /** * Lists the content of an SVN repository * * @param repository * @param path * @param c * @return * @throws SVNException */ private static int listEntries(SVNRepository repository, String path, int c) throws SVNException { Collection collection = null; SVNProperties prop = null; /* * Gets the contents of the directory specified by path at the latest * revision (for this purpose -1 is used here as the revision number to * mean HEAD-revision) getDir returns a Collection of SVNDirEntry * elements. SVNDirEntry represents information about the directory * entry. Here this information is used to get the entry name, the name * of the person who last changed this entry, the number of the revision * when it was last changed and the entry type to determine whether it's * a directory or a file. If it's a directory listEntries steps into a * next recursion to display the contents of this directory. The third * parameter of getDir is null and means that a user is not interested * in directory properties. The fourth one is null, too - the user * doesn't provide its own Collection instance and uses the one returned * by getDir. */ Collection entries = repository.getDir(path, (long) SVNRevision.HEAD.getNumber(), prop, collection); Iterator iterator = entries.iterator(); while (iterator.hasNext()) { SVNDirEntry entry = (SVNDirEntry) iterator.next(); if (entry.getKind() == SVNNodeKind.FILE) { c++; } /* Checking up if the entry is a directory. */ if (entry.getKind() == SVNNodeKind.DIR) { c = +listEntries(repository, (path.equals("")) ? entry.getName() : path + "/" + entry.getName(), c); } } return c; } }