/* * Capsule * Copyright (c) 2014-2016, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are licensed under the terms * of the Eclipse Public License v1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package capsule; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import org.apache.maven.model.Dependency; import org.apache.maven.model.Exclusion; import org.apache.maven.model.Model; import org.apache.maven.model.Repository; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.eclipse.aether.util.artifact.JavaScopes; public final class Pom { private final Model pom; private final Pom root; private final MavenCapsule capsule; private Pom parent; private Map<String, Dependency> managedDependencies; private Map<String, String> props; public Pom(InputStream is, Pom root, MavenCapsule capsule) { try { this.pom = new MavenXpp3Reader().read(is); this.root = root; this.capsule = capsule; } catch (Exception e) { throw new RuntimeException("Error trying to read pom.", e); } } // public PomReader(InputStream is) { // this(is, null, null); // } private Pom getParent() { if (parent == null) parent = resolveParent(); return parent; } private Pom resolveParent() { if (pom.getParent() == null) return null; final String group = pom.getParent().getGroupId(); final String artifactId = pom.getParent().getArtifactId(); final String version = pom.getParent().getVersion(); if (root != null && Objects.equals(group, root.getGroupId()) && Objects.equals(artifactId, root.getArtifactId()) && Objects.equals(version, root.getVersion())) return root; if (capsule != null) { try { capsule.log1(MavenCapsule.LOG_VERBOSE1, "Resolving parent " + pom.getParent() + " of pom " + pom); final String coords = group + ":" + artifactId + ":" + version; final List<Path> ps = capsule.lookupAndResolve(coords, "pom"); if (!ps.isEmpty()) return new Pom(Files.newInputStream(ps.get(0)), root, capsule); } catch (Exception e) { capsule.log1(MavenCapsule.LOG_QUIET1, "Exception while resolving parent " + pom.getParent() + " of pom " + pom + " : " + e.getMessage()); capsule.log1(MavenCapsule.LOG_VERBOSE1, e); } } return null; } public String getArtifactId() { return pom.getArtifactId(); } public String getGroupId() { return pom.getGroupId() != null ? pom.getGroupId() : (pom.getParent() != null ? pom.getParent().getGroupId() : null); } public String getVersion() { return pom.getVersion() != null ? pom.getVersion() : (pom.getParent() != null ? pom.getParent().getVersion() : null); } public String getId() { return pom.getId(); } public Map<String, String> getProperties() { if (props == null) { props = new HashMap<>(); if (getParent() != null) props.putAll(getParent().getProperties()); for (Map.Entry<Object, Object> e : pom.getProperties().entrySet()) props.put((String) e.getKey(), (String) e.getValue()); } return props; } public List<String> getRepositories() { final List<Repository> repos = pom.getRepositories(); if (repos == null) return Collections.emptyList(); final List<String> repositories = new ArrayList<>(repos.size()); for (Repository repo : repos) repositories.add(repoToString(repo)); return repositories; } public List<String> getDependencies(String type) { final List<Dependency> deps = pom.getDependencies(); if (deps == null) return Collections.emptyList(); final List<String> dependencies = new ArrayList<>(deps.size()); for (Dependency dep : deps) { if (includeDependency(dep) && type.equals(dep.getType())) dependencies.add(resolve(depToString(manageVersion(dep)))); } return dependencies; } public List<String> getManagedDependencies() { final Map<String, Dependency> deps = getManagedDependencies0(); if (deps == null) return Collections.emptyList(); final List<String> dependencies = new ArrayList<>(deps.size()); for (Dependency dep : deps.values()) dependencies.add(resolve(depManagement2coords(dep))); return dependencies; } private Map<String, Dependency> getManagedDependencies0() { if (managedDependencies == null) { managedDependencies = new HashMap<>(); if (getParent() != null) managedDependencies.putAll(getParent().getManagedDependencies0()); if (pom.getDependencyManagement() != null) { for (Dependency d : pom.getDependencyManagement().getDependencies()) managedDependencies.put(d.getManagementKey(), d); } } return managedDependencies; } /** * Applies dependency management to dependency versions */ private Dependency manageVersion(Dependency dep) { if (dep.getVersion() != null) return dep; final Dependency md = getManagedDependencies0().get(dep.getManagementKey()); if (md != null) dep.setVersion(md.getVersion()); return dep; } private static boolean includeDependency(Dependency dep) { if (dep.isOptional()) return false; if (dep.getScope() == null || dep.getScope().isEmpty()) return true; switch (dep.getScope().toLowerCase()) { case JavaScopes.COMPILE: case JavaScopes.RUNTIME: return true; default: return false; } } private static String depToString(Dependency dep) { return dep2coords(dep) + exclusions2desc(dep); } private static String dep2coords(Dependency dep) { return dep.getGroupId() + ":" + dep.getArtifactId() + ":" + (dep.getVersion() != null ? dep.getVersion() : "") + (dep.getClassifier() != null && !dep.getClassifier().isEmpty() ? ":" + dep.getClassifier() : ""); } private static String exclusions2desc(Dependency dep) { List<Exclusion> exclusions = dep.getExclusions(); if (exclusions == null || exclusions.isEmpty()) return ""; StringBuilder sb = new StringBuilder(); sb.append('('); for (Exclusion ex : exclusions) sb.append(exclusion2coord(ex)).append(','); sb.delete(sb.length() - 1, sb.length()); sb.append(')'); return sb.toString(); } private static String exclusion2coord(Exclusion ex) { return ex.getGroupId() + ":" + ex.getArtifactId(); } private static String depManagement2coords(Dependency dep) { return dep.getGroupId() + ":" + dep.getArtifactId() + ":" + (dep.getType() != null ? dep.getType() : "") + ":" + (dep.getClassifier() != null ? dep.getClassifier() : "") + ":" + (dep.isOptional() ? "-" : dep.getVersion() != null ? dep.getVersion() : ""); } private static String repoToString(Repository repo) { if (repo.getId() != null && !repo.getId().isEmpty()) return repo.getId() + "(" + repo.getUrl() + ")"; return repo.getUrl(); } private String resolve(String s) { if (s == null) return null; final Map<String, String> ps = getProperties(); String ret = s; if (getGroupId() != null) ret = ret.replace("${project.groupId}", getGroupId()).replace("${pom.groupId}", getGroupId()); if (getVersion() != null) ret = ret .replace("${project.version}", getVersion()) .replace("${pom.version}", getVersion()) .replace("${version}", getVersion()); for (String pName : ps.keySet()) ret = ret.replace("${" + pName + "}", ps.get(pName)); return ret; } }