/**
*
*/
package com.rekoe.service;
import java.io.File;
import java.util.Collection;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.tmatesoft.svn.core.SVNAuthenticationException;
import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties;
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;
import com.rekoe.domain.Pj;
import com.rekoe.domain.PjUsr;
import com.rekoe.domain.Usr;
import com.rekoe.utils.EncryptUtil;
import com.rekoe.utils.UsrProvider;
/**
* 仓库服务层
*/
@IocBean(create = "init")
public class RepositoryService {
/**
* 日志
*/
private final Log LOG = Logs.get();
@Inject
private ProjectService projectService;
@Inject
private ProjectUserService projectUserService;
/**
* 获取svn仓库
*
* @param pjId
* 项目ID
* @return svn仓库
* @throws SVNException
* svn异常,例如没有权限等
*/
public SVNRepository getRepository(String pjId) throws SVNException {
Pj pj = projectService.fetch(Cnd.where("pj", "=", pjId));
if (pj == null) {
LOG.warn("Not found project: " + pjId);
return null;
}
return this.getRepository(pj);
}
/**
* 从项目的url中获取svn的url
*
* @param url
* 项目url
* @return svn url
*/
public static String parseURL(String url) {
if (StringUtils.isBlank(url)) {
return null;
}
String result = url.trim();// 去空格
result = StringUtils.replace(result, "\t", " ");
result = StringUtils.replace(result, "\r", " ");
result = StringUtils.replace(result, "\n", " ");
result = StringUtils.replace(result, "\b", " ");
result = StringUtils.replace(result, "<", " ");// eg.
result = StringUtils.replace(result, "(", " ");// eg. ()
result = result.trim();
int blank = result.indexOf(" ");
if (blank != -1) {
result = result.substring(0, blank);
}
return result;
}
/**
* 获取svn仓库
*
* @param pj
* 项目
* @return svn仓库
* @throws SVNException
* svn异常,例如没有权限等
*/
@SuppressWarnings("deprecation")
public SVNRepository getRepository(Pj pj) throws SVNException {
Usr usr = UsrProvider.getCurrentUsr();
String svnUrl = parseURL(pj.getUrl());
if (StringUtils.isBlank(svnUrl)) {
throw new RuntimeException("URL不可以为空");
}
String svnUserName = usr.getUsr();
String svnPassword = usr.getPsw();
if (!com.rekoe.utils.Constants.HTTP_MUTIL.equals(pj.getType())) {
// pj_usr覆盖用户的密码
PjUsr pjUsr = projectUserService.get(pj.getPj(), svnUserName);
if (pjUsr != null) {
svnPassword = pjUsr.getPsw();
}
}
svnPassword = EncryptUtil.decrypt(svnPassword);// 解密
SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(svnUrl));
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(svnUserName, svnPassword);
repository.setAuthenticationManager(authManager);
return repository;
}
/**
* 返回项目仓库的根
*
* @param pj
* 项目
* @return 仓库根
*/
public String getRepositoryRoot(Pj pj) {
SVNRepository repository = null;
try {
repository = this.getRepository(pj);
return repository.getRepositoryRoot(true).toString();
} catch (SVNAuthenticationException e) {
LOG.error(e.getMessage());
return null;
} catch (SVNException e) {
LOG.error(e.getMessage());
return null;
} finally {
if (repository != null) {
repository.closeSession();
}
}
}
/**
* 获取项目指定路径的svn仓库文件系统
*
* @param pj
* 项目
* @param path
* 相对仓库根目录的路径
* @return 目录或文件系统
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public Collection getDir(String pj, String path) {
if (StringUtils.isBlank(path)) {
path = "/";// root
}
if (!path.startsWith("/")) {
path = "/" + path;
}
SVNRepository repository = null;
try {
repository = this.getRepository(pj);
SVNProperties properties = new SVNProperties();
return repository.getDir(path, SVNRevision.HEAD.getNumber(), properties, (Collection) null);
} catch (SVNAuthenticationException e) {
LOG.error(e);
throw new RuntimeException("认证失败");
} catch (SVNException e) {
LOG.error(e);
throw new RuntimeException(e.getMessage());
} finally {
if (repository != null) {
repository.closeSession();
}
}
}
/**
* Creates a local blank FSFS-type repository. A call to this routine is
* equivalent to
* createLocalRepository(path, null, enableRevisionProperties, force)
* .
*
* @param respository
* a repository root location
* @return a local URL (file:///) of a newly created repository
*/
public static SVNURL createLocalRepository(File respository) {
try {
return SVNRepositoryFactory.createLocalRepository(respository, true, false);
} catch (SVNException e) {
throw new RuntimeException(String.format("pj.save.error.createRepository", "创建仓库失败.{0}", new Object[] { respository.getAbsolutePath() }) + " : " + e.getMessage());
}
}
public void init() {
/*
* For using over http:// and https://
*/
DAVRepositoryFactory.setup();
/*
* For using over svn:// and svn+xxx://
*/
SVNRepositoryFactoryImpl.setup();
/*
* For using over file:///
*/
FSRepositoryFactory.setup();
}
}