| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivy.plugins.parser.m2; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.LineNumberReader; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.ivy.Ivy; |
| import org.apache.ivy.core.IvyContext; |
| import org.apache.ivy.core.IvyPatternHelper; |
| import org.apache.ivy.core.module.descriptor.Artifact; |
| import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor; |
| import org.apache.ivy.core.module.descriptor.DependencyDescriptor; |
| import org.apache.ivy.core.module.descriptor.ExcludeRule; |
| import org.apache.ivy.core.module.descriptor.ModuleDescriptor; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.core.settings.IvySettings; |
| import org.apache.ivy.core.settings.IvyVariableContainer; |
| import org.apache.ivy.plugins.parser.m2.PomWriterOptions.ConfigurationScopeMapping; |
| import org.apache.ivy.plugins.parser.m2.PomWriterOptions.ExtraDependency; |
| import org.apache.ivy.util.ConfigurationUtils; |
| |
| import static org.apache.ivy.util.StringUtils.isNullOrEmpty; |
| |
| public final class PomModuleDescriptorWriter { |
| |
| private static final String SKIP_LINE = "SKIP_LINE"; |
| |
| @SuppressWarnings("serial") |
| private static final ConfigurationScopeMapping DEFAULT_MAPPING = new ConfigurationScopeMapping( |
| new LinkedHashMap<String, String>() { |
| { |
| put("compile", "compile"); |
| put("runtime", "runtime"); |
| put("provided", "provided"); |
| put("test", "test"); |
| put("system", "system"); |
| } |
| }); |
| |
| private PomModuleDescriptorWriter() { |
| } |
| |
| public static void write(ModuleDescriptor md, File output, PomWriterOptions options) |
| throws IOException { |
| LineNumberReader in; |
| if (options.getTemplate() == null) { |
| in = new LineNumberReader(new InputStreamReader( |
| PomModuleDescriptorWriter.class.getResourceAsStream("pom.template"))); |
| } else { |
| in = new LineNumberReader(new InputStreamReader(new FileInputStream( |
| options.getTemplate()))); |
| } |
| |
| if (output.getParentFile() != null) { |
| output.getParentFile().mkdirs(); |
| } |
| PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), |
| StandardCharsets.UTF_8)); |
| try { |
| IvySettings settings = IvyContext.getContext().getSettings(); |
| IvyVariableContainer variables = new IvyVariableContainerWrapper( |
| settings.getVariableContainer()); |
| |
| variables.setVariable("ivy.pom.license", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.header", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.groupId", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.artifactId", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.version", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.packaging", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.name", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.description", SKIP_LINE, true); |
| variables.setVariable("ivy.pom.url", SKIP_LINE, true); |
| |
| if (options.getLicenseHeader() != null) { |
| variables.setVariable("ivy.pom.license", options.getLicenseHeader(), true); |
| } |
| if (options.isPrintIvyInfo()) { |
| String header = "<!--\n" + " Apache Maven 2 POM generated by Apache Ivy\n" |
| + " " + Ivy.getIvyHomeURL() + "\n" + " Apache Ivy version: " |
| + Ivy.getIvyVersion() + " " + Ivy.getIvyDate() + "\n" + "-->"; |
| variables.setVariable("ivy.pom.header", header, true); |
| } |
| |
| setModuleVariables(md, variables, options); |
| |
| boolean dependenciesPrinted = false; |
| |
| int lastIndent = 0; |
| int indent = 0; |
| String line = in.readLine(); |
| while (line != null) { |
| line = IvyPatternHelper.substituteVariables(line, variables); |
| if (line.contains(SKIP_LINE)) { |
| // skip this line |
| line = in.readLine(); |
| continue; |
| } |
| |
| if (line.trim().isEmpty()) { |
| // empty line |
| out.println(line); |
| line = in.readLine(); |
| continue; |
| } |
| |
| lastIndent = indent; |
| indent = line.indexOf('<'); |
| |
| if (!dependenciesPrinted && line.contains("</dependencies>")) { |
| printDependencies(md, out, options, indent, false); |
| dependenciesPrinted = true; |
| } |
| |
| if (!dependenciesPrinted && line.contains("</project>")) { |
| printDependencies(md, out, options, lastIndent, true); |
| dependenciesPrinted = true; |
| } |
| |
| out.println(line); |
| line = in.readLine(); |
| } |
| } finally { |
| in.close(); |
| out.close(); |
| } |
| } |
| |
| private static void setModuleVariables(ModuleDescriptor md, IvyVariableContainer variables, |
| PomWriterOptions options) { |
| ModuleRevisionId mrid = md.getModuleRevisionId(); |
| variables.setVariable("ivy.pom.groupId", mrid.getOrganisation(), true); |
| |
| String artifactId = options.getArtifactName(); |
| if (artifactId == null) { |
| artifactId = mrid.getName(); |
| } |
| |
| String packaging = options.getArtifactPackaging(); |
| if (packaging == null) { |
| // find artifact to determine the packaging |
| Artifact artifact = findArtifact(md, artifactId); |
| if (artifact == null) { |
| // no suitable artifact found, default to 'pom' |
| packaging = "pom"; |
| } else { |
| packaging = artifact.getType(); |
| } |
| } |
| |
| variables.setVariable("ivy.pom.artifactId", artifactId, true); |
| variables.setVariable("ivy.pom.packaging", packaging, true); |
| if (mrid.getRevision() != null) { |
| variables.setVariable("ivy.pom.version", mrid.getRevision(), true); |
| } |
| if (options.getDescription() != null) { |
| variables.setVariable("ivy.pom.description", options.getDescription(), true); |
| } else if (!isNullOrEmpty(md.getDescription())) { |
| variables.setVariable("ivy.pom.description", md.getDescription(), true); |
| } |
| if (md.getHomePage() != null) { |
| variables.setVariable("ivy.pom.url", md.getHomePage(), true); |
| } |
| } |
| |
| /** |
| * Returns the first artifact with the correct name and without a classifier. |
| */ |
| private static Artifact findArtifact(ModuleDescriptor md, String artifactName) { |
| for (Artifact artifact : md.getAllArtifacts()) { |
| if (artifact.getName().equals(artifactName) |
| && artifact.getAttribute("classifier") == null) { |
| return artifact; |
| } |
| } |
| |
| return null; |
| } |
| |
| private static void indent(PrintWriter out, int indent) { |
| for (int i = 0; i < indent; i++) { |
| out.print(' '); |
| } |
| } |
| |
| private static void printDependencies(ModuleDescriptor md, PrintWriter out, |
| PomWriterOptions options, int indent, boolean printDependencies) { |
| List<ExtraDependency> extraDeps = options.getExtraDependencies(); |
| DependencyDescriptor[] dds = getDependencies(md, options); |
| |
| if (!extraDeps.isEmpty() || (dds.length > 0)) { |
| if (printDependencies) { |
| indent(out, indent); |
| out.println("<dependencies>"); |
| } |
| |
| // print the extra dependencies first |
| for (ExtraDependency dep : extraDeps) { |
| String groupId = dep.getGroup(); |
| if (groupId == null) { |
| groupId = md.getModuleRevisionId().getOrganisation(); |
| } |
| String version = dep.getVersion(); |
| if (version == null) { |
| version = md.getModuleRevisionId().getRevision(); |
| } |
| printDependency(out, indent, groupId, dep.getArtifact(), version, dep.getType(), |
| dep.getClassifier(), dep.getScope(), dep.isOptional(), true, null); |
| } |
| |
| // now print the dependencies listed in the ModuleDescriptor |
| ConfigurationScopeMapping mapping = options.getMapping(); |
| if (mapping == null) { |
| mapping = DEFAULT_MAPPING; |
| } |
| |
| for (DependencyDescriptor dd : dds) { |
| ModuleRevisionId mrid = dd.getDependencyRevisionId(); |
| ExcludeRule[] excludes = null; |
| if (dd.canExclude()) { |
| excludes = dd.getAllExcludeRules(); |
| } |
| DependencyArtifactDescriptor[] dads = dd.getAllDependencyArtifacts(); |
| if (dads.length > 0) { |
| for (DependencyArtifactDescriptor dad : dads) { |
| String type = dad.getType(); |
| String classifier = dad.getExtraAttribute("classifier"); |
| String scope = mapping.getScope(dd.getModuleConfigurations()); |
| boolean optional = mapping.isOptional(dd.getModuleConfigurations()); |
| printDependency(out, indent, mrid.getOrganisation(), mrid.getName(), |
| mrid.getRevision(), type, classifier, scope, optional, |
| dd.isTransitive(), excludes); |
| } |
| } else { |
| String scope = mapping.getScope(dd.getModuleConfigurations()); |
| boolean optional = mapping.isOptional(dd.getModuleConfigurations()); |
| final String classifier = dd.getExtraAttribute("classifier"); |
| printDependency(out, indent, mrid.getOrganisation(), mrid.getName(), |
| mrid.getRevision(), null, classifier, scope, optional, dd.isTransitive(), |
| excludes); |
| } |
| } |
| |
| if (printDependencies) { |
| indent(out, indent); |
| out.println("</dependencies>"); |
| } |
| } |
| } |
| |
| private static void printDependency(PrintWriter out, int indent, String groupId, |
| String artifactId, String version, String type, String classifier, String scope, |
| boolean isOptional, boolean isTransitive, ExcludeRule[] excludes) { |
| indent(out, indent * 2); |
| out.println("<dependency>"); |
| indent(out, indent * 3); |
| out.println("<groupId>" + groupId + "</groupId>"); |
| indent(out, indent * 3); |
| out.println("<artifactId>" + artifactId + "</artifactId>"); |
| indent(out, indent * 3); |
| out.println("<version>" + version + "</version>"); |
| if (type != null && !"jar".equals(type)) { |
| indent(out, indent * 3); |
| out.println("<type>" + type + "</type>"); |
| } |
| if (classifier != null) { |
| indent(out, indent * 3); |
| out.println("<classifier>" + classifier + "</classifier>"); |
| } |
| if (scope != null) { |
| indent(out, indent * 3); |
| out.println("<scope>" + scope + "</scope>"); |
| } |
| if (isOptional) { |
| indent(out, indent * 3); |
| out.println("<optional>true</optional>"); |
| } |
| if (!isTransitive) { |
| indent(out, indent * 3); |
| out.println("<exclusions>"); |
| indent(out, indent * 4); |
| out.println("<exclusion>"); |
| indent(out, indent * 5); |
| out.println("<groupId>*</groupId>"); |
| indent(out, indent * 5); |
| out.println("<artifactId>*</artifactId>"); |
| indent(out, indent * 4); |
| out.println("</exclusion>"); |
| indent(out, indent * 3); |
| out.println("</exclusions>"); |
| } else if (excludes != null) { |
| printExclusions(excludes, out, indent); |
| } |
| indent(out, indent * 2); |
| out.println("</dependency>"); |
| } |
| |
| private static void printExclusions(ExcludeRule[] exclusions, PrintWriter out, int indent) { |
| indent(out, indent * 3); |
| out.println("<exclusions>"); |
| |
| for (ExcludeRule exclusion : exclusions) { |
| indent(out, indent * 4); |
| out.println("<exclusion>"); |
| indent(out, indent * 5); |
| out.println( |
| "<groupId>" + exclusion.getId().getModuleId().getOrganisation() + "</groupId>"); |
| indent(out, indent * 5); |
| out.println( |
| "<artifactId>" + exclusion.getId().getModuleId().getName() + "</artifactId>"); |
| indent(out, indent * 4); |
| out.println("</exclusion>"); |
| } |
| |
| indent(out, indent * 3); |
| out.println("</exclusions>"); |
| } |
| |
| private static DependencyDescriptor[] getDependencies(ModuleDescriptor md, |
| PomWriterOptions options) { |
| String[] confs = ConfigurationUtils.replaceWildcards(options.getConfs(), md); |
| |
| List<DependencyDescriptor> result = new ArrayList<>(); |
| for (DependencyDescriptor dd : md.getDependencies()) { |
| String[] depConfs = dd.getDependencyConfigurations(confs); |
| if (depConfs != null && depConfs.length > 0) { |
| result.add(dd); |
| } |
| } |
| |
| return result.toArray(new DependencyDescriptor[result.size()]); |
| } |
| |
| /** |
| * Wraps an {@link IvyVariableContainer} delegating most method calls to the wrapped instance, |
| * except for a set of variables which are only stored locally in the wrapper, and not |
| * propagated to the wrapped instance. |
| */ |
| private static final class IvyVariableContainerWrapper implements IvyVariableContainer { |
| |
| private final IvyVariableContainer variables; |
| |
| private Map<String, String> localVariables = new HashMap<>(); |
| |
| private IvyVariableContainerWrapper(IvyVariableContainer variables) { |
| this.variables = variables; |
| } |
| |
| public void setVariable(String varName, String value, boolean overwrite) { |
| localVariables.put(varName, value); |
| } |
| |
| public void setEnvironmentPrefix(String prefix) { |
| variables.setEnvironmentPrefix(prefix); |
| } |
| |
| public String getVariable(String name) { |
| String result = variables.getVariable(name); |
| if (result == null) { |
| result = localVariables.get(name); |
| } |
| return result; |
| } |
| |
| public Object clone() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| } |