Linux distribution of Apache subversion provides svnadmin to create a svn repository.But this is not capable of creating repository remotely.By issuing svnadmin command we can only create a repository within local file system.
Here i am going to describe couple of ways by which we can create svn repositories remotely.Here all my ways achieve above mentioned objective through java.Here is the list of method that i found.
1.Using ssh to execute svnadmin command remotely.
a)Using apache sshd library
b)Using JSch library
2.Using SCM -Manager
3.Using PHP+java Client
To use apache sshd library you have to add following maven dependency.
Following is the maven dependency which can be used to create maven project.
Next approach is using a source code management system.SCM Manager is an open source source code management system which is implemented in java.This is
a server which provide user interface to create repository and manage them with users.Currently it support svn ,git and mercurial.In addition to user interface, it expose REST API to manage repositories.Here i am going to use the REST API to create a repository.Before staring writing the REST Client Download the SCM Manager from here and start the server by executing the script which can be found in bin folder of the distribution.
To write the REST client there so many ways.
1.Using HTTP client
2.Apache Wink client
3.Jersey Client
I am using http client wich is very simple to use.All the REST calls are protected by BASIC Auth in SCM Manager.We have to set the credential in http client.
Here i used Axiom for generating XML payload.
Here is the java client that is used to call the php page.
This is how we can create svn repositories remotely.This will be helpful when ever there is a requirement of automatic repository provisioning.
Here i am going to describe couple of ways by which we can create svn repositories remotely.Here all my ways achieve above mentioned objective through java.Here is the list of method that i found.
1.Using ssh to execute svnadmin command remotely.
a)Using apache sshd library
b)Using JSch library
2.Using SCM -Manager
3.Using PHP+java Client
Using ssh to execute svnadmin command remotely
In this approach the repository is created by executing svnadmin or relevant command in remote host using ssh.Here there are two ssh opensource libraries available for java.a) Using apache sshd library
apache sshd is a pure java implementation of ssh available under apache 2.0 license.This is a sub-project of apache Mina.Here is a example code for executing svnadmin command on remote host as a superuser.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.wso2.carbon; | |
import org.apache.sshd.ClientChannel; | |
import org.apache.sshd.ClientSession; | |
import org.apache.sshd.SshClient; | |
import java.io.ByteArrayInputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.OutputStreamWriter; | |
import java.io.Writer; | |
/** | |
* | |
*/ | |
public class SSHDClient { | |
public static void main(String[] args) { | |
SshClient client = SshClient.setUpDefaultClient(); | |
try { | |
client.start(); | |
ClientSession clientSession = client.connect("localhost", 22).await().getSession(); | |
clientSession.authPassword("root", "password"); | |
ClientChannel channel = clientSession.createChannel("exec", "sudo -S -p '' -u www-data svnadmin create /home/root/repository/af5 \n"); | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
Writer w = new OutputStreamWriter(baos); | |
w.append("password"); | |
w.append("\n"); | |
w.close(); | |
channel.setIn(new ByteArrayInputStream(baos.toByteArray())); | |
channel.setOut(System.out); | |
channel.setErr(System.err); | |
channel.open(); | |
channel.waitFor(ClientChannel.CLOSED, 0); | |
channel.close(false); | |
client.stop(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>org.apache.sshd</groupId> | |
<artifactId>sshd-core</artifactId> | |
<version>0.7.0</version> | |
</dependency> |
b)Using JSch library
This is another popular java implementation of ssh.There are good examples also available for this libarary.Here is how to execute svnadmin command using JSch library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.wso2.carbon; | |
import com.jcraft.jsch.*; | |
import java.io.DataInputStream; | |
import java.io.DataOutputStream; | |
import java.io.IOException; | |
public class SSHClient { | |
public static void main(String[] args) throws JSchException, IOException { | |
String host = "localhost"; // host IP | |
String user = "root"; // username for SSH connection | |
String password = "password"; // password for SSH connection | |
int port = 22; // default SSH port | |
JSch shell = new JSch(); | |
// get a new session | |
Session session = shell.getSession(user, host, port); | |
// set user password and connect to a channel | |
session.setUserInfo(new SSHUserInfo(password)); | |
session.connect(); | |
Channel channel = session.openChannel("exec"); | |
ChannelExec channelExec= (ChannelExec) channel; | |
channelExec.setCommand("sudo -S -p '' -u www-data "+"svnadmin create /home/root/repository/af191 \r\n"); | |
channelExec.connect(); | |
DataInputStream dataIn = new DataInputStream(channelExec.getInputStream()); | |
DataOutputStream dataOut = new DataOutputStream(channelExec.getOutputStream()); | |
dataOut.write("password\n".getBytes()); | |
dataOut.flush(); | |
System.out.println(channel.getExitStatus()); | |
dataIn.close(); | |
dataOut.close(); | |
channelExec.disconnect(); | |
session.disconnect(); | |
return; | |
} | |
// this class implements jsch UserInfo interface for passing password to the session | |
static class SSHUserInfo implements UserInfo { | |
private String password; | |
SSHUserInfo(String password) { | |
this.password = password; | |
} | |
public String getPassphrase() { | |
return null; | |
} | |
public String getPassword() { | |
return password; | |
} | |
public boolean promptPassword(String arg0) { | |
return true; | |
} | |
public boolean promptPassphrase(String arg0) { | |
return true; | |
} | |
public boolean promptYesNo(String arg0) { | |
return true; | |
} | |
public void showMessage(String arg0) { | |
System.out.println(arg0); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.44-1</version>
</dependency>
Using SCM -Manager
Next approach is using a source code management system.SCM Manager is an open source source code management system which is implemented in java.This is
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>com.jcraft</groupId> | |
<artifactId>jsch</artifactId> | |
<version>0.1.44-1</version> | |
</dependency> |
a server which provide user interface to create repository and manage them with users.Currently it support svn ,git and mercurial.In addition to user interface, it expose REST API to manage repositories.Here i am going to use the REST API to create a repository.Before staring writing the REST Client Download the SCM Manager from here and start the server by executing the script which can be found in bin folder of the distribution.
To write the REST client there so many ways.
1.Using HTTP client
2.Apache Wink client
3.Jersey Client
I am using http client wich is very simple to use.All the REST calls are protected by BASIC Auth in SCM Manager.We have to set the credential in http client.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.wso2.carbon; | |
import org.apache.axiom.om.OMAbstractFactory; | |
import org.apache.axiom.om.OMElement; | |
import org.apache.axiom.om.OMFactory; | |
import org.apache.commons.httpclient.HttpClient; | |
import org.apache.commons.httpclient.HttpConnectionManager; | |
import org.apache.commons.httpclient.SimpleHttpConnectionManager; | |
import org.apache.commons.httpclient.UsernamePasswordCredentials; | |
import org.apache.commons.httpclient.auth.AuthScope; | |
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; | |
import org.apache.commons.httpclient.methods.PostMethod; | |
import javax.xml.stream.XMLStreamException; | |
import java.io.IOException; | |
import java.io.StringWriter; | |
/** | |
* | |
* | |
*/ | |
public class SVNClient { | |
private static final String REST_BASE_URI = "/api/rest"; | |
private static final String REST_CREATE_REPOSITORY_URI = "/repositories"; | |
private static final String REST_GET_REPOSITORY_URI = "/repositories/svn/"; | |
//repositories xml elements | |
private static final String REPOSITORY_XML_ROOT_ELEMENT = "repositories"; | |
private static final String REPOSITORY_NAME_ELEMENT = "name"; | |
private static final String REPOSITORY_TYPE_ELEMENT = "type"; | |
private static final String REPOSITORY_URL_ELEMENT = "url"; | |
//permission xml elements | |
private static final String PERMISSION_XML_ROOT_ELEMENT = "permissions"; | |
private static final String PERMISSION_TYPE_ELEMENT = "type"; | |
private static final String PERMISSION_NAME_ELEMENT = "name"; | |
private static final String PERMISSION_GROUP_PERMISSION_ELEMENT = "groupPermission"; | |
public static void main(String[] args) { | |
HttpClient client = new HttpClient(); | |
String userName = "scmadmin"; | |
String password = "scmadmin"; | |
AuthScope authScope = AuthScope.ANY; | |
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userName, password); | |
client.getState().setCredentials(authScope, credentials); | |
PostMethod post = new PostMethod("http://localhost:8080/" + REST_BASE_URI + | |
REST_CREATE_REPOSITORY_URI); | |
post.setRequestEntity(new ByteArrayRequestEntity(getRepositoryAsString("testRepo"))); | |
post.setDoAuthentication(true); | |
post.addRequestHeader("Content-Type", "application/xml;charset=UTF-8"); | |
try { | |
client.executeMethod(post); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return; | |
} finally { | |
HttpConnectionManager manager = client.getHttpConnectionManager(); | |
if (manager instanceof SimpleHttpConnectionManager) { | |
((SimpleHttpConnectionManager) manager).shutdown(); | |
} | |
} | |
} | |
private static byte[] getRepositoryAsString(String appid) { | |
OMFactory factory = OMAbstractFactory.getOMFactory(); | |
OMElement repository = factory.createOMElement(REPOSITORY_XML_ROOT_ELEMENT, null); | |
OMElement name = factory.createOMElement(REPOSITORY_NAME_ELEMENT, null); | |
name.setText(appid); | |
repository.addChild(name); | |
OMElement type = factory.createOMElement(REPOSITORY_TYPE_ELEMENT, null); | |
type.setText("svn"); | |
repository.addChild(type); | |
OMElement permission = factory.createOMElement(PERMISSION_XML_ROOT_ELEMENT, null); | |
OMElement groupPermission = factory.createOMElement(PERMISSION_GROUP_PERMISSION_ELEMENT, null); | |
groupPermission.setText("false"); | |
permission.addChild(groupPermission); | |
OMElement permName = factory.createOMElement(PERMISSION_NAME_ELEMENT, null); | |
permName.setText("RW"); | |
OMElement permType = factory.createOMElement(PERMISSION_TYPE_ELEMENT, null); | |
permType.setText("OWNER"); | |
permission.addChild(permName); | |
permission.addChild(permType); | |
repository.addChild(permission); | |
StringWriter writer = new StringWriter(); | |
try { | |
repository.serialize(writer); | |
} catch (XMLStreamException e) { | |
e.printStackTrace(); | |
} finally { | |
try { | |
writer.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
return writer.toString().getBytes(); | |
} | |
} |
Using PHP+java Client
In this approach a php page that is hosted in apache 2 server in remote host will create a svn repository using svnadmin command and there will be a java client that is used to call the php.The php page is secured using Basic Auth.Here is the very simple php code to create svn repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//There should be a proper way of handling authentication. | |
//This is just for POC | |
$ADMIN_USER_NAME='admin'; | |
$ADMIN_PASSWORD='admin'; | |
$PARENT_REPO_PATH='/home/root/repository/'; | |
if (!isset($_SERVER['PHP_AUTH_USER'])) { | |
header('WWW-Authenticate: Basic realm="My Realm"'); | |
header('HTTP/1.0 401 Unauthorized'); | |
echo '401 Authorization Required'; | |
exit; | |
} else { | |
if((strcmp($_SERVER['PHP_AUTH_USER'],$ADMIN_USER_NAME)==0) && (strcmp($_SERVER['PHP_AUTH_PW'],$ADMIN_PASSWORD)==0)){ | |
$name = $_REQUEST['name']; | |
$cmd = 'svnadmin create ' . escapeshellarg($PARENT_REPO_PATH . $name) . ' --fs-type fsfs'; | |
$output1=exec($cmd, $output, $exitValue); | |
if ($exitValue != 0) { | |
Print $output1; | |
header('HTTP/1.1 500 Internal Server Error'); | |
return; | |
}else{ | |
header('HTTP/1.1 201 Created'); | |
return; | |
} | |
}else{ | |
header('WWW-Authenticate: Basic realm="My Realm"'); | |
header('HTTP/1.0 401 Unauthorized'); | |
echo '401 Authorization Required'; | |
exit; | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.wso2.carbon; | |
import org.apache.commons.httpclient.HttpClient; | |
import org.apache.commons.httpclient.HttpStatus; | |
import org.apache.commons.httpclient.NameValuePair; | |
import org.apache.commons.httpclient.UsernamePasswordCredentials; | |
import org.apache.commons.httpclient.auth.AuthScope; | |
import org.apache.commons.httpclient.methods.GetMethod; | |
import java.io.IOException; | |
/** | |
* | |
*/ | |
public class PHPBasedSVNRepositoryClient { | |
public static final String CREATE_REPO_EPR = "/createRepo.php"; | |
public static void main(String[] args) { | |
HttpClient client = new HttpClient(); | |
String userName = "admin"; | |
String password = "admin"; | |
AuthScope authScope = AuthScope.ANY; | |
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userName, password); | |
client.getState().setCredentials(authScope, credentials); | |
; | |
GetMethod get = new GetMethod("http://localhost" + CREATE_REPO_EPR); | |
NameValuePair[] repositoryName = new NameValuePair[1]; | |
repositoryName[0] = new NameValuePair(); | |
repositoryName[0].setName("name"); | |
repositoryName[0].setValue("testRepo"); | |
get.setQueryString(repositoryName); | |
get.setDoAuthentication(true); | |
try { | |
client.executeMethod(get); | |
if (get.getStatusCode() == HttpStatus.SC_CREATED) { | |
System.out.println("repository is created successfully"); | |
} else { | |
System.out.println("repository creation is failed"); | |
} | |
} catch (IOException e) { | |
System.out.println("repository creation is failed " + e.getLocalizedMessage()); | |
} finally { | |
get.releaseConnection(); | |
} | |
} | |
} |
This is how we can create svn repositories remotely.This will be helpful when ever there is a requirement of automatic repository provisioning.