View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2017 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.devops.conga.plugins.aem.maven;
21  
22  import static io.wcm.devops.conga.generator.util.FileUtil.getCanonicalPath;
23  
24  import java.io.File;
25  import java.util.List;
26  
27  import javax.inject.Inject;
28  
29  import org.apache.maven.execution.MavenSession;
30  import org.apache.maven.model.Plugin;
31  import org.apache.maven.plugin.BuildPluginManager;
32  import org.apache.maven.plugin.MavenPluginManager;
33  import org.apache.maven.plugin.MojoExecution;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.MojoFailureException;
36  import org.apache.maven.plugin.descriptor.MojoDescriptor;
37  import org.apache.maven.plugin.descriptor.PluginDescriptor;
38  import org.apache.maven.plugins.annotations.Mojo;
39  import org.apache.maven.plugins.annotations.Parameter;
40  import org.apache.maven.project.MavenProject;
41  import org.codehaus.plexus.configuration.PlexusConfiguration;
42  import org.codehaus.plexus.configuration.PlexusConfigurationException;
43  import org.codehaus.plexus.util.xml.Xpp3Dom;
44  
45  import io.wcm.devops.conga.plugins.aem.maven.model.BundleFile;
46  import io.wcm.devops.conga.plugins.aem.maven.model.InstallableFile;
47  import io.wcm.devops.conga.plugins.aem.maven.model.ModelContentPackageFile;
48  import io.wcm.devops.conga.plugins.aem.maven.model.ModelParser;
49  import io.wcm.tooling.commons.packmgr.install.PackageFile;
50  import io.wcm.tooling.commons.packmgr.install.PackageInstaller;
51  
52  /**
53   * Installs all AEM content packages and OSGi bundles to AEM which are referenced in a model.yaml
54   * generated by CONGA for a node.
55   */
56  @Mojo(name = "package-install", threadSafe = true, requiresProject = false)
57  public final class InstallPackagesMojo extends AbstractContentPackageMojo {
58  
59    /**
60     * Directory with the generated CONGA configuration containing the model.yaml.
61     */
62    @Parameter(required = true, property = "conga.nodeDirectory")
63    private File nodeDirectory;
64  
65    /**
66     * Whether to install (unpack) the uploaded package automatically or not.
67     */
68    @Parameter(property = "vault.install", defaultValue = "true")
69    private boolean install;
70  
71    /**
72     * Force upload and install of content package. If set to:
73     * <ul>
74     * <li><code>true</code>: Package is always installed, even if it was already uploaded before.</li>
75     * <li><code>false</code>: Package is only installed if it was not already uploade before.</li>
76     * <li>nothing (default): Force is applied to packages with the string "-SNAPSHOT" in it's filename.</li>
77     * </ul>
78     */
79    @Parameter(property = "vault.force")
80    private Boolean force;
81  
82    /**
83     * If set to true nested packages get installed as well.
84     */
85    @Parameter(property = "vault.recursive", defaultValue = "true")
86    private boolean recursive;
87  
88    /**
89     * Delay further steps after package installation by this amount of seconds
90     */
91    @Parameter(property = "vault.delayAfterInstallSec")
92    private Integer delayAfterInstallSec;
93  
94    /**
95     * Replicate package(s) to publish instance after upload.
96     */
97    @Parameter(property = "vault.replicatePackage")
98    private boolean replicate;
99  
100   /**
101    * Version of Sling plugin
102    */
103   @Parameter(property = "sling.plugin.version", required = true, defaultValue = "2.4.2")
104   private String slingPluginVersion;
105 
106   @Parameter(defaultValue = "${project}", readonly = true)
107   private MavenProject project;
108   @Parameter(defaultValue = "${session}", readonly = true)
109   private MavenSession session;
110   @Inject
111   private MavenPluginManager pluginManager;
112   @Inject
113   private BuildPluginManager buildPluginManager;
114 
115   @Override
116   public void execute() throws MojoExecutionException, MojoFailureException {
117     if (isSkip()) {
118       return;
119     }
120 
121     if (!nodeDirectory.exists() || !nodeDirectory.isDirectory()) {
122       throw new MojoFailureException("Node directory not found: " + getCanonicalPath(nodeDirectory));
123     }
124 
125     getLog().info("Get AEM content packages from " + getCanonicalPath(nodeDirectory));
126 
127     // collect files to install
128     ModelParser modelParser = new ModelParser(nodeDirectory);
129     List<InstallableFile> items = modelParser.getInstallableFilesForNode();
130 
131     // ensure any file exist
132     if (items.isEmpty()) {
133       getLog().warn("No file found for installing.");
134       return;
135     }
136 
137     // install files
138     PackageInstaller installer = new PackageInstaller(getPackageManagerProperties());
139     installer.setReplicate(this.replicate);
140 
141     for (InstallableFile item : items) {
142       if (item instanceof ModelContentPackageFile modelContentPackageFile) {
143         PackageFile packageFile = toPackageFile(modelContentPackageFile);
144         installer.installFile(packageFile);
145       }
146       else if (item instanceof BundleFile bundleFile) {
147         if (bundleFile.getInstall() == null || bundleFile.getInstall()) {
148           installBundleViaSlingPlugin(bundleFile.getFile());
149         }
150       }
151       else {
152         getLog().warn("Unsupported file: " + getCanonicalPath(item.getFile()));
153       }
154     }
155   }
156 
157   private PackageFile toPackageFile(ModelContentPackageFile item) {
158     PackageFile output = new PackageFile();
159 
160     output.setFile(item.getFile());
161     Boolean installParam = item.getInstall();
162     if (installParam != null) {
163       output.setInstall(installParam);
164     }
165     else {
166       output.setInstall(this.install);
167     }
168     Boolean forcePAram = item.getForce();
169     if (forcePAram != null) {
170       output.setForce(forcePAram);
171     }
172     else {
173       output.setForce(this.force);
174     }
175     Boolean recursiveParam = item.getRecursive();
176     if (recursiveParam != null) {
177       output.setRecursive(recursiveParam);
178     }
179     else {
180       output.setRecursive(this.recursive);
181     }
182     Integer delayAfterInstallSecParam = item.getDelayAfterInstallSec();
183     if (delayAfterInstallSecParam != null) {
184       output.setDelayAfterInstallSec(delayAfterInstallSecParam);
185     }
186     else if (this.delayAfterInstallSec != null) {
187       output.setDelayAfterInstallSec(this.delayAfterInstallSec);
188     }
189     else {
190       output.setDelayAfterInstallSecAutoDetect();
191     }
192     output.setHttpSocketTimeoutSec(item.getHttpSocketTimeoutSec());
193 
194     return output;
195   }
196 
197   /**
198    * Executes the sling-maven-plugin directly from the current project to install OSGi bundles.
199    */
200   private void installBundleViaSlingPlugin(File file) throws MojoExecutionException {
201     Plugin plugin = new Plugin();
202     plugin.setGroupId("org.apache.sling");
203     plugin.setArtifactId("sling-maven-plugin");
204     plugin.setVersion(this.slingPluginVersion);
205 
206     try {
207       PluginDescriptor pluginDescriptor = pluginManager.getPluginDescriptor(plugin,
208           project.getRemotePluginRepositories(), session.getRepositorySession());
209       MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo("install-file");
210       MojoExecution mojoExecution = new MojoExecution(pluginDescriptor.getMojo("install-file"));
211 
212       Xpp3Dom config = convertConfiguration(mojoDescriptor.getMojoConfiguration());
213       config.getChild("slingUrl").setValue(buildConsoleUrl());
214       config.getChild("user").setValue(this.getConsoleUser());
215       config.getChild("password").setValue(this.getConsolePassword());
216       config.getChild("mountByFS").setValue("false");
217       config.getChild("bundleFileName").setValue(file.getAbsolutePath());
218       mojoExecution.setConfiguration(config);
219 
220       buildPluginManager.executeMojo(session, mojoExecution);
221     }
222     catch (Exception ex) {
223       throw new MojoExecutionException("Faild to execute plugin: " + plugin, ex);
224     }
225   }
226 
227   private Xpp3Dom convertConfiguration(PlexusConfiguration plexusConfig) throws PlexusConfigurationException {
228     Xpp3Dom config = new Xpp3Dom(plexusConfig.getName());
229     config.setValue(plexusConfig.getValue());
230     for (String attribute : plexusConfig.getAttributeNames()) {
231       config.setAttribute(attribute, plexusConfig.getAttribute(attribute));
232     }
233     for (PlexusConfiguration child : plexusConfig.getChildren()) {
234       config.addChild(convertConfiguration(child));
235     }
236     return config;
237   }
238 
239 }