這兩天在寫一個java程序,可以檢測其他的java項目的代碼是否符合規範。並且能夠對SVN中的項目進行檢查。
第一步是先實現本地文件的掃描,很簡單,就是一個文件遍歷找出所有文件的代碼:
/*
* 遞歸調用查找指定文件加下所有文件
*/
public static String GetFiles(String path) throws RowsExceededException, WriteException{
File rootDir = new File(path);
if(!rootDir.isDirectory()){
//調用檢測代碼的方法
checkLine(rootDir);
//清楚上下文記錄
context.clear();
}else{
String[] fileList = rootDir.list();
for (int i = 0; i < fileList.length; i++) {
path = rootDir.getAbsolutePath()+"\\"+fileList[i];
GetFiles(path);
}
}
return null;
}
第二步:循環讀取文件中的每一行,並對每行進行分析:
if(rootDir.getName().endsWith(".java")){
String path = rootDir.getAbsolutePath();
System.out.println(path);
FileInputStream scanFile = null;
BufferedInputStream bin = null;
InputStreamReader inread = null;
BufferedReader br = null;
try {
scanFile = new FileInputStream(path);
bin = new BufferedInputStream(scanFile);
inread = new InputStreamReader(bin);
br = new BufferedReader(inread);
String str = "";
int i =1;
while((str = br.readLine())!=null){//讀取每一行代碼,並調用parseLine方法來解析和檢查
parseLine(path, str, i);
i++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
inread.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
第三步,對代碼進行檢測,這裏使用正則表達式來判斷當前行代碼是屬性,還是常量,還是方法定義,還是控制語句(if,for,while,switch)等,
這段檢測的代碼都是本人用正則來判斷,也可以使用ASTView組件的API來獲取java類中的屬性,方法名,等,類似於反射技術。
//如果當前行是定義屬性,常量,或則局部變量
if(temp.matches("(private|public|protecte)?\\s?[\\w<,>]*\\s\\w*;")
|| temp.matches("(final)?\\s?[\\w<,>]*\\s\\w*(;|\\s?=\\s?\\w*;|"
+ "\\s?=\\s?new\\s[\\w<,>]*\\(([\\w<,>\\s]*)?\\);|\\s?=\\s?\\(\\w*\\)\\s?[\\w\\.\\)\\(\"\\s]*;)")){
//獲取上下文中,當前行的前面一行代碼
String pre = context.get(i-2);
//判斷該屬性,常量,或則局部變量的前面一行如果不是註釋,則不符合規範。下面的正則可以匹配雙斜槓和斜槓星
if(!pre.trim().matches("/([\\w*]|[^\\x00-\\xff]|\\s)*/")){
printXLS("錯誤規範66","定義的局部變量,常量,字段/屬性必須有註釋", path, "第"+i+"行");
isStatus = true;
}
}
代碼規範多達七八十條,在這裏就不一一列舉。
printXLS("錯誤規範66","定義的局部變量,常量,字段/屬性必須有註釋", path, "第"+i+"行");
printXLS是把錯誤報告寫到Excel文件中。
第四部:編寫代碼從SVN中檢出項目,這裏需要用到SVNKit庫,SVNKit是一個純java的subversion客戶端庫。
代碼如下:
/*第一步:
*導入可能用到的類
*/
import java.io.*;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
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.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
public class SVNUtil {
/*
* 第二步: 聲明客戶端管理類SVNClientManager。
*/
private static SVNClientManager ourClientManager;
public static void checkOut() throws SVNException {
/*
* 第三步: 對版本庫進行初始化操作 (在用版本庫進行其他操作前必須進行初始化) 對於通過使用 http:// 和 https://
* 訪問,執行DAVRepositoryFactory.setup(); 對於通過使用svn:// 和
* svn+xxx://訪問,執行SVNRepositoryFactoryImpl.setup();
* 對於通過使用file:///訪問,執行FSRepositoryFactory.setup(); 本程序框架用svn://來訪問
*/
SVNRepositoryFactoryImpl.setup();
/*
* 第四步: 要訪問版本庫的相關變量設置
*/
// 版本庫的URL地址
SVNURL repositoryURL = null;
try {
repositoryURL = SVNURL.parseURIEncoded("svn://192.168.9.60/temp");
} catch (SVNException e) {
//
}
// 版本庫的用戶名
String name = "test";
// 版本庫的用戶名密碼
String password = "111111";
// 工作副本目錄
String myWorkingCopyPath = "F:/SVN_JAVAScan";
// 驅動選項
ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
/*
* 第五步: 創建SVNClientManager的實例。提供認證信息(用戶名,密碼) 和驅動選項。
*/
ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, name, password);
/*
* 第六步: 通過SVNClientManager的實例獲取要進行操作的client實例(如 * SVNUpdateClient)
* 通過client實例來執行相關的操作。 此框架以check out操作來進行說明,其他操作類似。
*/
/* 工作副本目錄創建 */
File wcDir = new File(myWorkingCopyPath);
if (wcDir.exists()) {
System.out.println("the destination directory '" + wcDir.getAbsolutePath() + "' already exists!");
} else {
wcDir.mkdirs();
}
try {
/*
* 遞歸的把工作副本從repositoryURL check out 到 wcDir目錄。 SVNRevision.HEAD
* 意味着把最新的版本checked out出來。
*/
SVNUpdateClient updateClient = ourClientManager.getUpdateClient();
updateClient.setIgnoreExternals(false);
//需要遍歷多個文件夾時,要傳入遞歸深度參數爲無限SVNDepth.INFINITY
long workingVersion = updateClient.doCheckout(repositoryURL, wcDir, SVNRevision.HEAD, SVNRevision.HEAD,SVNDepth.INFINITY, true);
System.out.println("把版本:"+workingVersion+" check out 到目錄:"+wcDir+"中。");
} catch (SVNException svne) {
svne.printStackTrace();
}
}
}
上面就是檢出SVN項目到本地中的方法,既然項目以及可以檢出到本地指定的文件夾中。那麼執行完上面的代碼,下面的代碼就是掃描文件,只需要將前面掃描文件的代碼執行即可。