您的位置:首页 > 其它

从公司gitlab获取所有依赖的jar包坐标

2017-08-09 13:03 741 查看

从公司gitlab获取所有java项目依赖的jar包坐标

背景

公司“安全专员”想方便的拿到公司所有java项目依赖的jar包坐标,方便他从“论坛”上发现什么jar存在安全漏洞时,及时知道我们公司是否也有对该jar包的依赖,以及对应的项目和负责人。

分析

我们内部代码管理工具是gitlab,采用
master
分支发布,只需分析
master
依赖即可。

思路是先拿到所有项目的代码,然后通过maven dependency插件获取到依赖的jar包坐标,然后分析出其中jar包坐标整理到文档中。最好也拿到项目的负责人信息。

初步想到步骤:

从内部gitlab机器用盘上拷贝

执行
mvn dependency:tree --log-file xxx


从产生的日志中分析出依赖的jar坐标

这个想想都觉得慢的受不了,好几个G的小文件,光从用盘上拷贝都要花费不少时间。

另外直接执行
maven dependency:tree
也不能成功,因为依赖的本项目中的其他module不存在,需要先打包。

另外拿不到项目负责人信息。

改进版本一:

通过gitlab api拿到所有项目信息,包括负责人信息,每个执行
git clone xxx
得到所有代码,再次执行时执行
git pull origin master


执行
mvn clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true dependency:tree --log-file xxx


从产生的日志中分析出依赖的jar坐标

能够拿到应用负责人信息,但仍然慢的让人崩溃。

另外有些项目执行
mvn package
因为代码原因会失败,导致
mvn dependency:tree
无法继续执行。

改进版本二:

通过gitlab api拿到所有项目信息,包括负责人信息, 通过gitlab api下载每个项目
master
分支中的所有
pom.xml


对于根目录存在
pom.xml
的项目执行
mvn install -f xxx/xxx/pom.xml
,
web
模块通常会失败,不过没关系, 其他模块成功就行。

执行
mvn dependency:tree -f xxx/xxx/pom.xml


使用apache
commons-exec
执行
dependency:tree
命令,同时分析产生的日志。

第二步对只有
pom.xml
的项目执行
mvn install
web
模块通常会失败,不过没关系,需要的是其他模块,因为执行
mvn dependency:tree
web
模块需要依赖到其他模块。

一两百个java项目,2核的机器20多分钟跑完,产生结果,基本满意。

也可以继续优化下,借助jprofiler等工具找到耗时点、调整执行线程池大小等。

代码

maven依赖

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.gitlab4j</
4000
groupId>
<artifactId>gitlab4j-api</artifactId>
<version>4.4.3</version>
</dependency>


代码片段说明

Pattern pattern = Pattern.compile("(([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+))");

String str = "[INFO] +- javax.servlet:servlet-api:jar:2.5:provided\n";
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
System.out.println(matcher.group());
System.out.println(matcher.group(1));
System.out.println(matcher.group(2));
System.out.println(matcher.group(3));
System.out.println(matcher.group(4));
System.out.println(matcher.group(5));
System.out.println(matcher.group(6));
}


通过上述正则表达式,找出jar包坐标,输出结果为:

javax.servlet:servlet-api:jar:2.5:provided
javax.servlet:servlet-api:jar:2.5:provided
javax.servlet
servlet-api
jar
2.5
provided


完整代码

static String baseDir = "/Users/xxx/tmp/gitlab/";
static String targetFile = "/Users/xxx/tmp/dependency.csv";

static BufferedWriter store;
static {
try {
store = new BufferedWriter(new FileWriter(new File(targetFile)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

static GitLabApi api = new GitLabApi("http://xxxxxx", "xxxxxxx");

static Pattern pattern = Pattern.compile("(([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+):([\\w\\-\\.\\d]+))");

static Executor executor = Executors.newFixedThreadPool(5, new ThreadFactory() {
private final AtomicInteger threadNum = new AtomicInteger(1);

@Override
public Thread newThread(Runnable r) {
String name = "collector-" + threadNum.getAndIncrement();
Thread ret = new Thread(r, name);
ret.setDaemon(true);
return ret;
}
});

public static void main(String[] args) throws GitLabApiException, IOException, InterruptedException {

Map<Group, List<Project>> groupMap = new HashMap<Group, List<Project>>();
int count = 0;
for (Group group : api.getGroupApi().getGroups()) {
List<Project> projects = api.getGroupApi().getProjects(group.getId());
if (projects != null) {
groupMap.put(group, projects);
count += projects.size();
}
}
final CountDownLatch latch = new CountDownLatch(count);
for (final Map.Entry<Group, List<Project>> entry : groupMap.entrySet()) {
final Group group = entry.getKey();
for (final Project project : entry.getValue()) {
executor.execute(new Runnable() {
@Override
public void run() {
try {
if (copyPomFileFromGitlab(project.getId(), project.getName(), group.getName())) {
executeMavenInstall(group.getName(), project.getName());
executeMavenDependencyTree(project.getCreatorId(), group.getName(), project.getName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}
});
}
}
latch.await();
System.out.println("*******************执行结束*********************");
System.out.println("*******************执行结束*********************");
System.out.println("*******************执行结束*********************");

}

private static boolean copyPomFileFromGitlab(Integer projectId, String projectName, String groupName) throws GitLabApiException, IOException {
boolean rootPomExists = false;
Pager<TreeItem> pager = api.getRepositoryApi().getTree(projectId, "/", "master", true, 100);
while (pager.hasNext()) {
for (TreeItem item : pager.next()) {
if (item.getType() == TreeItem.Type.BLOB && item.getName().equals("pom.xml")) {
rootPomExists = item.getPath().equals("pom.xml");
File file = new File(baseDir + groupName + "/" + projectName + "/" + item.getPath());
createFile(file, false);
copy(api.getRepositoryFileApi().getRawFile(projectId, "master", item.getPath()), new FileOutputStream(file));
}
}
}
return rootPomExists;
}

private static void executeMavenInstall(String group, String project) {
try {
DefaultExecutor exec = new DefaultExecutor();
exec.setStreamHandler(new PumpStreamHandler(new LogOutputStream() {
@Override
protected void processLine(String line, int logLevel) {
}
}));
exec.execute(CommandLine.parse(String.format("mvn install -f %s%s/%s/pom.xml", baseDir, group, project)));
} catch (Exception ex) {
ex.printStackTrace();
}
}

private static void executeMavenDependencyTree(Integer creatorId, final String group, final String project) throws GitLabApiException, IOException {
final User user = api.getUserApi().getUser(creatorId);
LogOutputStream outputStream = new LogOutputStream() {
@Override
protected void processLine(String s, int i) {
if (s.startsWith("[ERROR]")) {
System.out.println(s);
return;
}
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
System.out.println(matcher.group());
try {
store.write(
String.format("%s,%s,%s,%s,%s,%s\n", group, project, user.getEmail(), matcher.group(2), matcher.group(3), matcher.group(5)));
store.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};

DefaultExecutor exec = new DefaultExecutor();
exec.setStreamHandler(new PumpStreamHandler(outputStream, outputStream));
exec.execute(CommandLine.parse(String.format("mvn dependency:tree -f %s%s/%s/pom.xml", baseDir, group, project)));
}

private static void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
byte[] bytes = new byte[1024];
int count;
while ((count = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, count);
}
}

private static void createFile(File file, boolean directory) throws IOException {
if (!file.exists()) {
createFile(file.getParentFile(), true);
if (directory) {
file.mkdir();
} else {
file.createNewFile();
}
System.out.println("create:" + file.getPath());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: