package com.lcw.util; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; import org.apache.maven.repository.legacy.repository.ArtifactRepositoryFactory; import org.apache.maven.repository.legacy.repository.DefaultArtifactRepositoryFactory; import org.apache.maven.settings.building.DefaultSettingsBuilder; import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuildingResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author lancw */ public class MavenDependencyUtil { private static final Logger LOGGER = LoggerFactory.getLogger(MavenDependencyUtil.class.getName()); private static final ArtifactRepositoryFactory FACTORY = new DefaultArtifactRepositoryFactory(); private static final String MAVEN_HOME = "MAVEN_HOME"; private static final String M2_HOME = "M2_HOME"; private static final String MAVEN_HOME_END = "\\bin\\.."; private static final String SUFFIX_JAR = ".jar"; private static final String SUFFIX_WAR = ".war"; private static final String INFO = "[INFO]"; private static final String BF = "BUILD FAILURE"; private static String mavenHome; private static final HashMap<String, ArrayList<URL>> CACHE = new HashMap<>(); /** * 解析项目pom文件,返回依赖jar的URL数组 * * @param pomPath * @return * @throws Exception */ public static ArrayList<URL> analysisPOM(String pomPath) throws Exception { try { if (CACHE.isEmpty()) { CACHE.putAll((Map<String, ArrayList<URL>>) SerializableUtil.readObject(SerializableUtil.FileNameEnum.DEPENDENCY_CACHE)); } } catch (Exception e) { LOGGER.info("未找到依赖关系缓存,将从maven依赖中分析"); } if (CACHE.get(pomPath) != null) { LOGGER.info("get URLs from cache"); return CACHE.get(pomPath); } File pf = new File(pomPath); ArrayList<URL> urls = new ArrayList<>(); if (pf.isDirectory()) { getSubFile(pf, urls, 1); if (!urls.isEmpty()) { return urls; } else { throw new Exception(pomPath + "文件夹中没有任何jar文件"); } } ArtifactRepository localRepository = localRepository(); File pomDir = new File(pomPath).getParentFile(); String cmd = System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS") ? "cmd /c " : ""; Process p = Runtime.getRuntime().exec(cmd + "mvn dependency:list", null, pomDir); boolean error = false; try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) { String tmp = br.readLine(); while (tmp != null) { LOGGER.info(tmp); if (tmp.startsWith(INFO) && tmp.contains(":jar:")) {//io.netty:netty:jar:3.7.0.Final:compile tmp = tmp.replace(INFO, "").trim(); String[] args = tmp.split(":"); Artifact a = new DefaultArtifact(args[0], args[1], args[3], args[4], args[2], null, new DefaultArtifactHandler()); File file = new File(localRepository.getBasedir(), localRepository.pathOf(a) + SUFFIX_JAR); if (!file.exists()) { LOGGER.error("file not found:" + file.getAbsolutePath()); } else { urls.add(file.toURI().toURL()); } } else if (tmp.contains(BF)) { error = true; } tmp = br.readLine(); } } if (error) { throw new Exception("项目构建失败,请修复项目错误!"); } p.destroy(); File target = new File(pomDir.getAbsolutePath() + "/target"); if (!target.exists()) { p = Runtime.getRuntime().exec(cmd + "mvn install -Dmaven.test.skip=true", null, pomDir); try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) { String tmp = br.readLine(); while (tmp != null) { LOGGER.info(tmp); if (tmp.contains(BF)) { error = true; } tmp = br.readLine(); } } } if (error) { throw new Exception("项目构建失败,请修复项目错误!"); } File[] jar = target.listFiles((File dir, String name) -> name.endsWith(SUFFIX_JAR) || name.endsWith(SUFFIX_WAR)); if (jar != null) { for (File file : jar) { urls.add(file.toURI().toURL()); } } if (urls.size() > 0) { CACHE.put(pomPath, urls); SerializableUtil.saveObject(CACHE, SerializableUtil.FileNameEnum.DEPENDENCY_CACHE); } return urls; } private static void getSubFile(File f, ArrayList<URL> urls, int deep) throws MalformedURLException { for (File file : f.listFiles()) { if (file.isDirectory() && deep < 30) { getSubFile(file, urls, ++deep); } else if (file.getName().endsWith(".jar")) { urls.add(file.toURI().toURL()); } } } /** * 从系统环境变量中查找mavenHome * * @return */ public static String getMavenHome() { if (mavenHome == null) { mavenHome = System.getenv(M2_HOME); if (StringUtils.isBlank(mavenHome)) { LOGGER.error("查询" + M2_HOME + "失败,继续查询" + MAVEN_HOME); mavenHome = System.getenv(MAVEN_HOME); } if (mavenHome == null || mavenHome.trim().isEmpty()) { LOGGER.error("查询" + MAVEN_HOME + "失败"); } else { mavenHome = mavenHome.endsWith(MAVEN_HOME_END) ? mavenHome.replace(MAVEN_HOME_END, "") : mavenHome; LOGGER.info(M2_HOME + ":" + mavenHome); } } mavenHome = mavenHome == null ? mavenHome : mavenHome.replace("\\", "/"); return mavenHome; } /** * maven仓库处理 * * @return * @throws Exception */ private static ArtifactRepository localRepository() throws Exception { if (mavenHome == null) { getMavenHome(); } SettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); request.setGlobalSettingsFile(new File(mavenHome, "/conf/settings.xml")); DefaultSettingsBuilder builder = new DefaultSettingsBuilderFactory().newInstance(); SettingsBuildingResult ret = builder.build(request); String path = ret.getEffectiveSettings().getLocalRepository(); path = path == null ? String.format("%s%s", System.getProperty("user.home"), "\\.m2\\repository") : path; return FACTORY.createArtifactRepository("local", "file://" + path, (ArtifactRepositoryLayout) new DefaultRepositoryLayout(), null, null); } public static void clearCache() { SerializableUtil.clearCache(SerializableUtil.FileNameEnum.DEPENDENCY_CACHE); CACHE.clear(); } }