/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.module.artifact.builder; import static com.google.common.base.Preconditions.checkArgument; import static java.util.Collections.singletonList; import static org.apache.commons.lang.StringUtils.isEmpty; import static org.mule.runtime.module.artifact.classloader.MuleMavenPlugin.MULE_MAVEN_PLUGIN_ARTIFACT_ID; import static org.mule.runtime.module.artifact.classloader.MuleMavenPlugin.MULE_MAVEN_PLUGIN_GROUP_ID; import org.mule.runtime.api.exception.MuleRuntimeException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.io.xpp3.MavenXpp3Writer; import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Base class for all kind of artifact that may exists in mule. * <p> * Provides all the support needed for maven. * * @param <T> the actual type of the builder. */ public abstract class AbstractDependencyFileBuilder<T extends AbstractDependencyFileBuilder<T>> { public static final String COMPILE_SCOPE = "compile"; private static final String MULE_MAVEN_PLUGIN_VERSION = "1.0.0"; private final String artifactId; private final List<AbstractDependencyFileBuilder> dependencies = new ArrayList<>(); private final List<AbstractDependencyFileBuilder> sharedLibraries = new ArrayList<>(); private String groupId = "org.mule.test"; private String version = "1.0.0"; private String type = "jar"; private String classifier; private File artifactPomFile; private File tempFolder; /** * @param artifactId the maven artifact id */ public AbstractDependencyFileBuilder(String artifactId) { checkArgument(artifactId != null, "artifact id cannot be null"); this.artifactId = artifactId; } protected String getTempFolder() { if (tempFolder != null) { return tempFolder.getAbsolutePath(); } return System.getProperty("java.io.tmpdir"); } /** * Sets the temporary folder to be used to create the artifact file. * * @param tempFolder temporary folder to use to create the artifact file. * @return the same builder instance */ public T tempFolder(File tempFolder) { checkArgument(tempFolder != null, "tempFolder cannot be null"); checkArgument(tempFolder.isDirectory(), "tempFolder must be a directory"); this.tempFolder = tempFolder; return getThis(); } public abstract File getArtifactFile(); public File getArtifactPomFile() { if (artifactPomFile == null) { checkArgument(!isEmpty(artifactId), "Filename cannot be empty"); final File tempFile = new File(getTempFolder(), artifactId + ".pom"); tempFile.deleteOnExit(); Model model = new Model(); model.setGroupId(getGroupId()); model.setArtifactId(getArtifactId()); model.setVersion(getVersion()); model.setModelVersion("4.0.0"); if (!sharedLibraries.isEmpty()) { model.setBuild(new Build()); model.getBuild().setPlugins(singletonList(createMuleMavenPlugin())); } for (AbstractDependencyFileBuilder fileBuilderDependency : dependencies) { model.addDependency(fileBuilderDependency.getAsMavenDependency()); } artifactPomFile = new File(tempFile.getAbsolutePath()); try (FileOutputStream fileOutputStream = new FileOutputStream(artifactPomFile)) { new MavenXpp3Writer().write(fileOutputStream, model); } catch (IOException e) { throw new MuleRuntimeException(e); } } return artifactPomFile; } private Plugin createMuleMavenPlugin() { Plugin plugin = new Plugin(); plugin.setGroupId(MULE_MAVEN_PLUGIN_GROUP_ID); plugin.setArtifactId(MULE_MAVEN_PLUGIN_ARTIFACT_ID); plugin.setVersion(MULE_MAVEN_PLUGIN_VERSION); Xpp3Dom configuration = new Xpp3Dom("configuration"); plugin.setConfiguration(configuration); Xpp3Dom sharedLibrariesDom = new Xpp3Dom("sharedLibraries"); configuration.addChild(sharedLibrariesDom); dependencies.stream().filter(sharedLibraries::contains) .forEach(sharedLibrary -> { Xpp3Dom sharedLibraryDom = new Xpp3Dom("sharedLibrary"); sharedLibrariesDom.addChild(sharedLibraryDom); Xpp3Dom groupIdDom = new Xpp3Dom("groupId"); groupIdDom.setValue(sharedLibrary.getGroupId()); sharedLibraryDom.addChild(groupIdDom); Xpp3Dom artifactIdDom = new Xpp3Dom("artifactId"); artifactIdDom.setValue(sharedLibrary.getArtifactId()); sharedLibraryDom.addChild(artifactIdDom); }); return plugin; } public T dependingOn(AbstractDependencyFileBuilder dependencyFileBuilder) { dependencies.add(dependencyFileBuilder); return getThis(); } /** * Adds a new dependency that will be visible to other plugins within the artifact. * * @param dependencyFileBuilder shared dependency. * @return the same builder instance */ public T dependingOnSharedLibrary(AbstractDependencyFileBuilder dependencyFileBuilder) { dependencies.add(dependencyFileBuilder); sharedLibraries.add(dependencyFileBuilder); return getThis(); } /** * @param groupId the maven group id * @return the same builder instance */ public T withGroupId(String groupId) { this.groupId = groupId; return getThis(); } /** * @param version the maven version * @return the same builder instnace */ public T withVersion(String version) { this.version = version; return getThis(); } /** * @param classifier the maven classifier * @return the same builder instance */ public T withClassifier(String classifier) { this.classifier = classifier; return getThis(); } /** * @return maven group id */ public String getGroupId() { return groupId; } /** * @return maven artifact id */ public String getArtifactId() { return artifactId; } /** * @return maven version */ public String getVersion() { return version; } /** * @return maven type */ public String getType() { return type; } /** * @return maven classifier */ public String getClassifier() { return classifier; } /** * @return the path within the maven repository this artifact is located in. */ public String getArtifactFileRepositoryPath() { return getGroupId().replace(".", File.separator) + File.separator + Paths .get(getArtifactId(), getVersion(), getArtifactId() + "-" + getVersion() + (getClassifier() != null ? "-" + getClassifier() : "") + "." + type) .toString(); } /** * @return the path within the maven repository this artifact pom is located in. */ public String getArtifactFilePomRepositoryPath() { return getGroupId().replace(".", File.separator) + File.separator + Paths.get(getArtifactId(), getVersion(), getArtifactId() + "-" + getVersion() + ".pom").toString(); } /** * @return the path within the artifact file where the pom file is bundled */ public String getArtifactFileBundledPomPath() { return Paths.get("META-INF", "maven", getGroupId(), getArtifactId(), "pom.xml").toString(); } /** * Creates a {@link Dependency} object from this artifact with scope compile. * * @return a maven */ public Dependency getAsMavenDependency() { Dependency dependency = new Dependency(); dependency.setVersion(getVersion()); dependency.setGroupId(getGroupId()); dependency.setArtifactId(getArtifactId()); dependency.setClassifier(getClassifier()); dependency.setType(getType()); dependency.setScope(COMPILE_SCOPE); return dependency; } /** * @return current instance. Used just to avoid compilation warnings. */ protected abstract T getThis(); /** * @return the collection of dependencies of this artifact. */ public List<AbstractDependencyFileBuilder> getDependencies() { return dependencies; } /** * @return a collection of all the compile dependencies of this artifact including the transitive ones */ public List<AbstractDependencyFileBuilder> getAllCompileDependencies() { List<AbstractDependencyFileBuilder> allCompileDependencies = new ArrayList<>(); for (AbstractDependencyFileBuilder dependency : dependencies) { if (dependency.getAsMavenDependency().getScope().equals(COMPILE_SCOPE)) { allCompileDependencies.addAll(dependency.getAllCompileDependencies()); allCompileDependencies.add(dependency); } } return allCompileDependencies; } }