viernes, 25 de octubre de 2013

Programa para crear repositorios SVN usando Java. SVNkit

"SVNkit ofrece un conjunto de librerias y clases Java, para la automatización en la creación de repositorios SVN. "

SVNKitAsí pues he escrito un conjunto de clases en Java con la intención de crear una aplicación que permita instalar, configurar y administrar (dar de alta usuarios) un repositorio o varios sobre un servidor Debian. Esta es una muestra de como automatizar el proceso de creación y gestión de repositorios SVN en la empresa. 
SVNkit

Para la realización de este ejemplo he utilizado SVNKit una API para Java que permite la gestión de SVN. La libreria puede descargarse desde: 


Descripción de la aplicación svnRobot

La aplicación consiste de tres clases: 

Repositorio.java

Que se encargará de realizar las operaciones de crear el repositorio en la ruta especificada, configurar la seguridad con Apache, agregar usuarios, modificar contraseñas y realizar el respaldo de la instancia. 

CrearSVN.java

Clase utilitaria facade que crea el repositorio y lo configura con Apache.

AgregarUsuariosSVN.java

Clase utilitaria que agrega un  usuario al repositorio ya existente, utiliza el método agregarUsuario de la clase Repositorio.java

Entorno de la aplicación

Para el desarrollo de esta aplicación se utilizó un IDE Eclipse y ha sido probado en ambiente local con una máquina con Sistema Operativo Ubuntu, Apache y SVN instalados. Se deben tener las librerias de SVNKit agregadas en el proyecto. Un proyecto Java Standar es más que suficiente. 

Código fuente

Clase Repositorio.java
package svn;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ResourceBundle;

import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
/**Clase Repositorio basada en el API SVNKit. Se ocupa de crear un 
 *repositorio y de realizar las operaciones de configurar con Apache, 
 *agregar usuarios, modificar contraseñas y realizar el respaldo de la
 *instancia
 * @author Luis Ubaldo Godínez Flores
 * @version 1.0
 * @since 15/08/2013
 */
public class Repositorio {
//Las siguientes dos lineas se suprimen para evitar hardcore en la aplicación
//public static final String apachepath="/etc/apache2/";
//public static final String dav_svn_path=apachepath+"mods-available/dav_svn.conf";

//private SVNURL urlRepositorio;
private File SVNDirectory;
private boolean enableRevision;
private boolean force;
/**Constructor de la clase

* @param ruta es la ruta del repositorio
* @param enableRevision (true or false) indica si esta habilitado para revisiones
* @param force ejecuta la operación a la fuerza
*/
public Repositorio(String ruta,boolean enableRevision, boolean force)
{
try{
ResourceBundle rb=ResourceBundle.getBundle("svnRobot");
String svnPath=rb.getString("svnCreationPath");
ruta=svnPath+ruta;
this.SVNDirectory= new File(ruta);
this.enableRevision=true;
this.force=false;
}
catch(Exception ex)
{
System.out.println("No se puede crear el objeto");
ex.getCause();
}
}



public boolean isEnableRevision() {
return enableRevision;
}



public void setEnableRevision(boolean enableRevision) {
this.enableRevision = enableRevision;
}



public boolean isForce() {
return force;
}



public void setForce(boolean force) {
this.force = force;
}


    /*
public static String getPath() {
return path;
}*/



public File getSVNDirectory() {
return SVNDirectory;
}



public void setSVNDirectory(File sVNDirectory) {
SVNDirectory = sVNDirectory;
}


/** Crea un nuevo repositorio si y solo si no existe
 * 
 * @param repositorio
 * @return un objeto tipo SVNURL, que es la url en formato de SVNkit, del repositorio creado.
 * 
 * Recibe un objeto de tipo Repositorio. Si el directorio no existe lo crea y lo convierte en 
 * una instancia DAVsvn. Habilitado para enlazarlo al módulo de seguridad de Apache.
 */
public static SVNURL crearNuevoRepositorio(Repositorio repositorio)
{
SVNURL url=null;
File directorio=repositorio.getSVNDirectory();
boolean enableRevision=repositorio.isEnableRevision();
boolean force=repositorio.isForce();
try
{

DAVRepositoryFactory.setup();
if (!directorio.exists())
{
directorio.mkdir();
url=SVNRepositoryFactory.createLocalRepository(directorio, enableRevision, force);
}
}catch(Exception ex)
{
ex.printStackTrace();
System.out.println("No puedo crear el repositorio, porque ya existe");
}

return url;
}

/**
* El método configSVNyApache permite asociar un repositorio svn para acceder a través
* de la seguridad del servidor de aplicaciones Apache. Debe usarse junto con el método
* crearNuevoRepositorio, como una secuencia. 
* @param url Representa la URL del repositorio que se va a configurar con Apache
* @return 1 si se logró configurar el repositorio y 0 de modo contrario
*/
public static boolean configSVNyApache(SVNURL url)
{
boolean creado=false;
try
{
ResourceBundle rb=ResourceBundle.getBundle("svnRobot");
String dav_svn_path=rb.getString("davSVNConfigurationPath");
File davfile=new File(dav_svn_path);
BufferedWriter salida= new BufferedWriter(new FileWriter(davfile,true));
//obtengo el nombre del repositorio de la SVNURL
int pos=url.getPath().lastIndexOf("/");
String SVNNombre=url.getPath().substring(pos+1);
//hasta aquí
salida.newLine();
salida.write("<Location /svn/"+SVNNombre+"> \n");
salida.write("DAV svn \n");
salida.write("SVNPath "+url.getPath()+"\n");
salida.write("#Authentication Basic \n");
salida.write("AuthName \"Subversion Repository\" \n");
salida.write("AuthType Basic \n");
salida.write("AuthUserFile "+rb.getString("htpasswdPath")+SVNNombre+".htpasswd \n");
salida.write("#Necesario para seguridad \n");
salida.write("Require valid-user \n");
salida.write("</Location> \n");
salida.close();
creado=true;
}
catch(Exception ex)
{
System.out.println("Ocurrió un error al configurar el repositorio");
ex.printStackTrace();
}
return creado;
}
/**
* Este método permite agregar un usuario de manera automática desde Java, utilizando el comando
* htpasswd -b -c -m /path/repository/myRepo user password
* @author Luis Ubaldo Godínez Flores
* @since 01-10-2013
* @param repositorio - Representa el nombre del repositorio donde se desea agregar usuarios
* @param usuario - Nombre de usuario
* @return regresa un 1 en caso de exito y 0 si no se puede crear el usuario
**/

public static boolean agregarUsuario(String repositorio, String usuario, String password)
{
boolean creado=false;
ResourceBundle rb=ResourceBundle.getBundle("svnRobot");
String archivoPasswords=rb.getString("htpasswdPath")+repositorio+".htpasswd";
String parametros="";
Process p=null;
BufferedReader inStream = null;
try
{
File htpasswdFile=new File(archivoPasswords);
if (htpasswdFile.exists())
{
parametros="-b -m";
}
else{
parametros="-b -c -m";
}

String comando="htpasswd "+parametros+" "+archivoPasswords+" "+usuario+ " "+ password;
   try{
p=Runtime.getRuntime().exec(comando);
inStream=new BufferedReader(new InputStreamReader(p.getInputStream()));
System.out.println(inStream.readLine());
inStream.close();
p.destroy();
creado=true;
   }
   catch(IOException ex){
    System.err.println("No se pudo ejecutar el comando htpasswd");
   }
}
catch(Exception ex)
{
System.out.println("No se ha podido crear el usuario");
ex.getCause();
}

return creado;
}


}

Clase crearSVN.java
package svn;

import java.util.Scanner;
. import org.tmatesoft.svn.core.SVNURL;
/**Clase utilitaria de la clase objeto, crea un repositorio en la ruta especificada
 * @author Luis Ubaldo Godínez Flores
 * @version 1.0
 * @since 15/08/2013
 * */
public class crearSVN {

public static void main(String[] args)
{
Repositorio repositorio;
Scanner scanner=new Scanner(System.in);
SVNURL url=null;
System.out.println("Escriba el nombre repositorio que será creado");
System.out.println("Asegurese que tiene los permisos correctos");
String nombreRepositorio=scanner.next();
try
{
repositorio= new Repositorio(nombreRepositorio,true,false);
url=Repositorio.crearNuevoRepositorio(repositorio);
System.out.println("El repositorio se creo con exito en la ruta: "+nombreRepositorio);
System.out.println("Configurando seguridad y acceso con Apache Web Server");

if (Repositorio.configSVNyApache(url))
{
System.out.println("El repositorio ha sido configurado con Apache");
System.out.println("Reinicie el servidor apache y agregué usuarios");
System.out.println("A través de la utilería htpasswd");
}
else
{
System.out.println("Verifique que tiene derechos para crear y configurar el repositorio");
System.out.println("y que el archivo dav_svn.conf exista");
}
}catch(Exception ex)
{
System.out.println("No se pudo crear el repositorio");
}
scanner.close();

}

}



Clase AgregarUsuarios.java
package svn;

import java.util.Scanner;

/**
 * Clase utilitaria que muestra el uso del método agrearUsuario a un repositorio 
 * ya existente. La clase solicita el nombre del repositorio, el usuario y el password
 * y hace uso del comando htpasswd para crear el usuario. 
 */
public class AgregarUsuariosSVN {

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner=new Scanner(System.in);
System.out.println("Escriba el nombre del repositorio:");
String repositorio=scanner.next();
        System.out.println("Escriba el nombre del usuario");
        String usuario=scanner.next();
        System.out.println("Escriba el password:");
        String password=scanner.next();
        
        if (Repositorio.agregarUsuario(repositorio, usuario, password))
        {
        System.out.println("El usuario se creó correctamente");
        }
        else
        {
        System.out.println("Ocurrió un error");
        }
        scanner.close();
}



}

Consideraciones finales

Después de compilar y crear los archivos jar correspondientes para las clases crearSVN.java y AgregarUsuarios.java, se deberá ejecutar los programas con derechos de super usuario en Linux ya que por lo general los repositorios SVN se crean en el directorio var. 

Espero que este artículo les haya sido de interés sientanse libres de copiar y pegar el código en sus respectivos IDE, comenten y enriquezcan esta práctica. 

Recuerden que si esta información ha sido de utilidad dar click en el boton g+. Muchas gracias. 

No hay comentarios:

Publicar un comentario

Si tienes alguna duda, comentario o sugerencia sobre este artículo, por favor siéntete libre de compartirlo. Si tienes algún comentario o asunto más personal, por favor utiliza nuestro formulario de contacto. Gracias.