博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jar包的License信息都存在于哪块
阅读量:5812 次
发布时间:2019-06-18

本文共 4456 字,大约阅读时间需要 14 分钟。

最近两天在搞产品发布前的jar包License扫描工作,因为这个数据交换项目是基于Kettle做的二次开发,而Kettle本身是一款强大的开源数据交换产品,其中包含了近两千个jar包,所以为了产品发布后不被惹上官司,需要扫描介质里所有jar包的License。

那么问题来了,如何扫描介质里所有jar包的License呢

大概了解pom.xml文件的小伙伴可能有想法了,直接去<licenses>标签获取即可。

另外,熟悉Maven公共库网站的小伙伴可能也有想法了,可以写段Java程序,拼接url(https:/mvnrepository.com/artifact/groupId/artifactId/version)在线获取jar包信息Html页面,再去解析即可。

那么url标红的变量从哪获取呢?对于绝大部分小伙伴来说,项目开发就在外网,所以直接去遍历扫描Maven仓库目录即可轻松获取到(当然,这种也有局限性,就是这个jar包必须是Maven编译出来的,而非Ant);但是对于像我们这种在公司内网开发的来说,领导最多能帮你把介质放到外网就不错了,所以你拥有的只有jar包本身,要想获取以上三个变量,需要解析pom.xml文件(这种也有同样的局限性),这里建议最好使用Maven官方的API工具类MavenXpp3Reader来准确解析(maven-model-3.6.0.jar),以免自己手动解析xml出现各种问题,特别是需要扫描很多jar包的时候。一个好的Java程序员应该尝试熟悉使用各种外部工具,毕竟Java流行的原因很大程度上得益于Java开源社区的强大支持。实现代码如下:

public static boolean searchInPom(MyFileEntity fe) {	JarFile jf = null;	try {		jf = new JarFile(fe.getFile());		Enumeration
entries = jf.entries(); while (entries.hasMoreElements()) { JarEntry entry = (JarEntry) entries.nextElement(); if (entry.getName().toLowerCase().endsWith("pom.xml")) { StringWriter writer = new StringWriter(); try { org.springframework.util.FileCopyUtils.copy(new InputStreamReader(jf.getInputStream(entry)), writer); } catch (IOException e1) { e1.printStackTrace(); } StringReader sr = new StringReader(writer.toString()); MavenXpp3Reader reader = new MavenXpp3Reader(); Model model = null; try { model = reader.read(sr); List
licenses = model.getLicenses(); if (licenses != null && licenses.size() > 0) { // System.out.println(licenses.get(0).getName()); fe.setLicense(licenses.get(0).getName()); return true; } else { // pom中没有license标签,则尝试联网获取 String groupId = model.getGroupId(); String artifactId = model.getArtifactId(); String version = model.getVersion(); Parent parent = model.getParent(); String groupId2 = null; String artifactId2 = null; String version2 = null; if (parent != null) { groupId2 = parent.getGroupId(); artifactId2 = parent.getArtifactId(); version2 = parent.getVersion(); } // 自定义的fe对象简单封装了这三个变量groupId,artifactId和version fe.setGroupId(groupId == null ? groupId2 : groupId); fe.setArtifactId(artifactId == null ? artifactId2 : artifactId); fe.setVersion(version == null ? version2 : version); // System.out.println(fe); return searchOnInet(fe); // searchOnInet方法自己实现 } } catch (IOException | XmlPullParserException e) { e.printStackTrace(); } finally { if (sr != null) { sr.close(); } } } } } catch (IOException e2) { e2.printStackTrace(); } finally { try { if (jf != null) { jf.close(); } } catch (IOException e) { e.printStackTrace(); } } return false;}

其实,jar包的License信息的存放是有千奇百怪的规范或方式,那接下来总结一下哪些相对具体的地方都有可能放置License吧。

一.META-INF/maven/**/pom.xml

具体位置1:Licenses元素

条件:Maven编译出来的jar,且要含有此标签,有的pom中无此标签(如slf4j-api-1.6.1.jar)

示例:mssql-jdbc.jar

具体位置2:一般在pom开头的注释

条件:Maven编译出来的jar,且要含有相关注释,有的pom中无此注释(如slf4j-api-1.6.1.jar)

示例:commons-io.jar

二.META-INF/MANIFEST.MF

具体位置:Bundle-License:***

条件:含有MANIFEST.MF文件,有的无此文件(如jmi.jar),且含有此key,有的无此key(如asm.jar)

示例:mssql-jdbc.jar

补充获取License实现代码(需要准确获取MANIFEST中的License信息,可以使用jdk的类java.util.jar.Manifest):

public static final String MANIFEST_ENTRY = "META-INF/MANIFEST.MF";static String LICENSE_TAG = "Bundle-License";public static boolean searchInMf(MyFileEntity fe) {	JarFile jf = null;	FileInputStream fis = null;	try {		jf = new JarFile(fe.getFile());		JarEntry entry = jf.getJarEntry(MANIFEST_ENTRY);		if (entry != null) {			Manifest m = jf.getManifest();			Attributes ma = m.getMainAttributes();			String url = ma.getValue(LICENSE_TAG);			if (url != null) {				// System.out.println(url);				fe.setUrl(url);				return true;			}		}	} catch (IOException e) {		e.printStackTrace();	} finally {		try {			if (fis != null) {				jf.close();			}		} catch (IOException e) {			e.printStackTrace();		}	}	return false;}

三.META-INF/LICENSE或META-INF/LICENSE.txt(有的在META-INF下,有的不在)

具体位置:一般存在于第一二行文本

条件:META-INF下含有此文件,有的无此文件(如mssql-jdbc.jar),有的有此文件,但打开无License信息(如dom4j.jar)

示例:apache-log4j-extras.jar

四.META-INF/NOTICE或META-INF/NOTICE.txt

具体位置:License文本信息位置不固定

条件:META-INF下含有此文件,有的无此文件(如guava.jar)

示例:fastjson.jar

五.其他

具体位置:about.html或其他各种文件

条件:任何文件都有可能,因为任何文件可以被人为写入任何信息包括license

示例1:jface.jar(about.html)

示例2:ftp4che.jar(COPYING文件)

示例3:ftp4che.jar(类注释)

示例4:bcprov-jdk14.jar(LICENSE.java)

转载于:https://www.cnblogs.com/songzehao/p/10854262.html

你可能感兴趣的文章
OCP读书笔记(24) - 题库(ExamD)
查看>>
Http、TCP/IP协议与Socket之间的区别(转载)
查看>>
解决Unable to load R3 module ...VBoxDD.dll (VBoxDD):GetLastError=1790
查看>>
.net excel利用NPOI导入oracle
查看>>
vrpie在Visio Studio 中无法调试的问题
查看>>
第六课:数据库的基本工具
查看>>
关于二叉树重构的思索
查看>>
$_SERVER['SCRIPT_FLENAME']与__FILE__
查看>>
skynet实践(8)-接入websocket
查看>>
系统版本判断
查看>>
My97DatePicker 日历插件
查看>>
0603 学术诚信与职业道德
查看>>
小点心家族第3位成员——楼层定位效果
查看>>
Knockout.Js官网学习(enable绑定、disable绑定)
查看>>
hive基本操作与应用
查看>>
excel快捷键设置
查看>>
poj3692
查看>>
python之信号量【Semaphore】
查看>>
html5纲要,细谈HTML 5新增的元素
查看>>
Android应用集成支付宝接口的简化
查看>>