diff --git a/pom.xml b/pom.xml index 505bd596..5055a809 100644 --- a/pom.xml +++ b/pom.xml @@ -547,6 +547,12 @@ under the License. + + + org.eclipse.sisu + sisu-maven-plugin + + diff --git a/src/it/projects/inheritedResources/child/pom.xml b/src/it/projects/inheritedResources/child/pom.xml new file mode 100644 index 00000000..d2ce774b --- /dev/null +++ b/src/it/projects/inheritedResources/child/pom.xml @@ -0,0 +1,55 @@ + + + + + + 4.0.0 + + + inheritResources + parent + 1.0 + ../pom.xml + + + child + pom + + Child inheriting site resources + + + + + maven-project-info-reports-plugin + @projectInfoReportsPluginVersion@ + + + + summary + + + + + + + + diff --git a/src/it/projects/inheritedResources/child/src/site/markdown/test-child.md b/src/it/projects/inheritedResources/child/src/site/markdown/test-child.md new file mode 100644 index 00000000..35ef3d61 --- /dev/null +++ b/src/it/projects/inheritedResources/child/src/site/markdown/test-child.md @@ -0,0 +1,19 @@ + +Overwritten \ No newline at end of file diff --git a/src/it/projects/inheritedResources/child/src/site/markdown/test2.md b/src/it/projects/inheritedResources/child/src/site/markdown/test2.md new file mode 100644 index 00000000..35ef3d61 --- /dev/null +++ b/src/it/projects/inheritedResources/child/src/site/markdown/test2.md @@ -0,0 +1,19 @@ + +Overwritten \ No newline at end of file diff --git a/src/it/projects/inheritedResources/child/src/site/site.xml b/src/it/projects/inheritedResources/child/src/site/site.xml new file mode 100644 index 00000000..9c74fa07 --- /dev/null +++ b/src/it/projects/inheritedResources/child/src/site/site.xml @@ -0,0 +1,39 @@ + + + + + + org.apache.maven.skins + maven-fluido-skin + ${fluidoSkinVersion} + + + + + + + + + + + + diff --git a/src/it/projects/inheritedResources/invoker.properties b/src/it/projects/inheritedResources/invoker.properties new file mode 100644 index 00000000..978b68af --- /dev/null +++ b/src/it/projects/inheritedResources/invoker.properties @@ -0,0 +1,16 @@ +# 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 +# +# http://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. diff --git a/src/it/projects/inheritedResources/pom.xml b/src/it/projects/inheritedResources/pom.xml new file mode 100644 index 00000000..f5a94d24 --- /dev/null +++ b/src/it/projects/inheritedResources/pom.xml @@ -0,0 +1,87 @@ + + + + + + 4.0.0 + + inheritResources + parent + 1.0 + pom + + Parent containing site resources + + + @mavenVersion@ + UTF-8 + @fluidoSkinVersion@ + + + + + + + org.apache.maven.plugins + maven-site-plugin + @project.version@ + + + attach-resources + false + + attach-resources + + + + **/something + + true + + + + + + + + + + + + maven-project-info-reports-plugin + @projectInfoReportsPluginVersion@ + + + + index + + + + + + + + + child + + + diff --git a/src/it/projects/inheritedResources/src/site/markdown/test.md b/src/it/projects/inheritedResources/src/site/markdown/test.md new file mode 100644 index 00000000..121cbb9f --- /dev/null +++ b/src/it/projects/inheritedResources/src/site/markdown/test.md @@ -0,0 +1,19 @@ + +Inherited \ No newline at end of file diff --git a/src/it/projects/inheritedResources/src/site/markdown/test2.md b/src/it/projects/inheritedResources/src/site/markdown/test2.md new file mode 100644 index 00000000..121cbb9f --- /dev/null +++ b/src/it/projects/inheritedResources/src/site/markdown/test2.md @@ -0,0 +1,19 @@ + +Inherited \ No newline at end of file diff --git a/src/it/projects/inheritedResources/src/site/site.xml b/src/it/projects/inheritedResources/src/site/site.xml new file mode 100644 index 00000000..8816f7cf --- /dev/null +++ b/src/it/projects/inheritedResources/src/site/site.xml @@ -0,0 +1,38 @@ + + + + + + org.apache.maven.skins + maven-fluido-skin + ${fluidoSkinVersion} + + + + + + + + + + + diff --git a/src/it/projects/inheritedResources/verify.bsh b/src/it/projects/inheritedResources/verify.bsh new file mode 100644 index 00000000..7cc6d948 --- /dev/null +++ b/src/it/projects/inheritedResources/verify.bsh @@ -0,0 +1,61 @@ + +/* + * 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 + * + * http://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. + */ + +import java.io.*; +import org.codehaus.plexus.util.*; + +boolean result = true; + +try +{ + File parentSiteDirectory = new File( basedir, "target/site" ); + File parentIndex = new File( parentSiteDirectory, "index.html" ); + if ( !parentIndex.exists() || parentIndex.isDirectory() ) + { + System.err.println( "no index file in parent or is a directory." ); + result = false; + } + + // CHILD + + File childSiteDirectory = new File( basedir, "child/target/site" ); + + File childIndex = new File( childSiteDirectory, "index.html" ); + if ( !childIndex.exists() ) + { + System.err.println( "no index file in child." ); + result = false; + } + + File childSummary = new File( childSiteDirectory, "summary.html" ); + if ( !childSummary.exists() ) + { + System.err.println( "no summary file in child." ); + result = false; + } + +} +catch ( IOException e ) +{ + e.printStackTrace(); + result = false; +} + +return result; diff --git a/src/it/projects/site-attach-resources/child/pom.xml b/src/it/projects/site-attach-resources/child/pom.xml new file mode 100644 index 00000000..33098d2d --- /dev/null +++ b/src/it/projects/site-attach-resources/child/pom.xml @@ -0,0 +1,38 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugins.site.its + site-attach-resources + 1.0-SNAPSHOT + + + jar-site-attach-resources + jar + + site-attach-resources IT for jar + the site resources should not be attached: only when packaging = pom, see https://issues.apache.org/jira/browse/MSITE-597 + diff --git a/src/it/projects/site-attach-resources/child/src/site/site.xml b/src/it/projects/site-attach-resources/child/src/site/site.xml new file mode 100644 index 00000000..ec9b2dfe --- /dev/null +++ b/src/it/projects/site-attach-resources/child/src/site/site.xml @@ -0,0 +1,30 @@ + + + + + + + org.apache.maven.skins + maven-fluido-skin + ${fluidoSkinVersion} + + diff --git a/src/it/projects/site-attach-resources/child/src/site/xdoc/index.xml b/src/it/projects/site-attach-resources/child/src/site/xdoc/index.xml new file mode 100644 index 00000000..104a9e21 --- /dev/null +++ b/src/it/projects/site-attach-resources/child/src/site/xdoc/index.xml @@ -0,0 +1,28 @@ + + + + + + +
+

MSITE-265.

+
+ +
\ No newline at end of file diff --git a/src/it/projects/site-attach-resources/invoker.properties b/src/it/projects/site-attach-resources/invoker.properties new file mode 100644 index 00000000..75550e85 --- /dev/null +++ b/src/it/projects/site-attach-resources/invoker.properties @@ -0,0 +1,18 @@ +# 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 +# +# http://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. + +invoker.goals=clean deploy diff --git a/src/it/projects/site-attach-resources/no-site-resources/pom.xml b/src/it/projects/site-attach-resources/no-site-resources/pom.xml new file mode 100644 index 00000000..8d8ad860 --- /dev/null +++ b/src/it/projects/site-attach-resources/no-site-resources/pom.xml @@ -0,0 +1,38 @@ + + + + + + 4.0.0 + + + org.apache.maven.plugins.site.its + site-attach-resources + 1.0-SNAPSHOT + + + no-site-resources-attach-descriptor + pom + + site-attach-resources IT for no source/site directory + No site descriptor to attach: must not fail, just explain. + diff --git a/src/it/projects/site-attach-resources/pom.xml b/src/it/projects/site-attach-resources/pom.xml new file mode 100644 index 00000000..c4d58253 --- /dev/null +++ b/src/it/projects/site-attach-resources/pom.xml @@ -0,0 +1,110 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.site.its + site-attach-resources + 1.0-SNAPSHOT + pom + + site-attach-resources IT + + + child + no-site-resources + + + + @mavenVersion@ + UTF-8 + @fluidoSkinVersion@ + + + + + false + site-deploy + Example company web server + file://@project.build.directory@/it/site-attach-resources/target/snapshot-repo/ + + + + + + + + maven-site-plugin + @project.version@ + + + maven-deploy-plugin + 3.1.3 + + + + + + maven-site-plugin + @project.version@ + + default,en,sv + + + + attach-resources + + attach-resources + + + + + default-site + + true + + false + + + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + @projectInfoReportsPluginVersion@ + + + + index + + + + + + + diff --git a/src/it/projects/site-attach-resources/src/site/site.xml b/src/it/projects/site-attach-resources/src/site/site.xml new file mode 100644 index 00000000..9885790c --- /dev/null +++ b/src/it/projects/site-attach-resources/src/site/site.xml @@ -0,0 +1,44 @@ + + + + + + + + + org.apache.maven.skins + maven-fluido-skin + ${fluidoSkinVersion} + + + + + + + + + + + + + + diff --git a/src/it/projects/site-attach-resources/src/site/site_sv.xml b/src/it/projects/site-attach-resources/src/site/site_sv.xml new file mode 100644 index 00000000..a76f6846 --- /dev/null +++ b/src/it/projects/site-attach-resources/src/site/site_sv.xml @@ -0,0 +1,44 @@ + + + + + + + + + org.apache.maven.skins + maven-fluido-skin + ${fluidoSkinVersion} + + + + + + + + + + + + + + diff --git a/src/it/projects/site-attach-resources/src/site/xdoc/parent.xml b/src/it/projects/site-attach-resources/src/site/xdoc/parent.xml new file mode 100644 index 00000000..21144119 --- /dev/null +++ b/src/it/projects/site-attach-resources/src/site/xdoc/parent.xml @@ -0,0 +1,28 @@ + + + + + + +
+

Must be contained in all child sites as well.

+
+ +
\ No newline at end of file diff --git a/src/it/projects/site-attach-resources/verify.bsh b/src/it/projects/site-attach-resources/verify.bsh new file mode 100644 index 00000000..55706865 --- /dev/null +++ b/src/it/projects/site-attach-resources/verify.bsh @@ -0,0 +1,84 @@ + +/* + * 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 + * + * http://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. + */ + +import java.io.*; +import org.codehaus.plexus.util.*; + +boolean result = true; + +try +{ + File target = new File( basedir, "target" ); + if ( !target.exists() || !target.isDirectory() ) + { + System.err.println( "target file is missing or not a directory." ); + return false; + } + + File siteDescriptor = new File( target, "site-attach-resources-1.0-SNAPSHOT-site-resources.zip" ); + if ( !siteDescriptor.exists() || siteDescriptor.isDirectory() ) + { + System.err.println( "site-resources archive file is missing from target or is a directory." ); + return false; + } + + File artifactsDirectory = new File( target, "snapshot-repo/org/apache/maven/plugins/site/its/site-attach-resources/1.0-SNAPSHOT" ); + boolean hasSiteResourcesArtifact = false; + File[] files = artifactsDirectory.listFiles(); + for ( int i = 0; i < files.length; i++ ) + { + String name = files[i].getName(); + // site-attach-resources-1.0-20241209.200100-1-site-resources.zip + if ( name.endsWith( "site-resources.zip" ) ) + { + hasSiteResourcesArtifact = hasSiteResourcesArtifact || name.startsWith( "site-attach-resources-1.0" ); + } + } + if ( !hasSiteResourcesArtifact ) + { + System.err.println( "site-resources archive not deployed for pom packaging." ); + return false; + } + + artifactsDirectory = new File( target, "snapshot-repo/org/apache/maven/plugins/site/its/jar-site-attach-resources/1.0-SNAPSHOT" ); + hasSiteResourcesArtifact = false; + files = artifactsDirectory.listFiles(); + for ( int i = 0; i < files.length; i++ ) + { + String name = files[i].getName(); + // site-attach-resources-1.0-20241209.200100-1-site-resources.zip + if ( name.endsWith( "site-resources.zip" ) ) + { + hasSiteResourcesArtifact = true; + } + } + if ( hasSiteResourcesArtifact ) + { + System.err.println( "site-resources archive deployed for jar packaging." ); + return false; + } +} +catch ( IOException e ) +{ + e.printStackTrace(); + result = false; +} + +return result; \ No newline at end of file diff --git a/src/main/java/org/apache/maven/plugins/site/SiteResourcesAttachMojo.java b/src/main/java/org/apache/maven/plugins/site/SiteResourcesAttachMojo.java new file mode 100644 index 00000000..223c1148 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/site/SiteResourcesAttachMojo.java @@ -0,0 +1,160 @@ +/* + * 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 + * + * http://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.maven.plugins.site; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProjectHelper; +import org.codehaus.plexus.archiver.Archiver; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.FileSet; +import org.codehaus.plexus.archiver.util.DefaultFileSet; + +/** + * Adds the site resources (compressed in a ZIP archive) as dedicated artifact with classifier {@value #CLASSIFIER} to be installed/deployed. + * Usually used in combination with {@link org.apache.maven.plugins.site.descriptor.SiteDescriptorAttachMojo} to also deploy the actual site descriptor. + * This is implicitly used for sites inheriting from this project. + * + * @since next + */ +@Mojo(name = SiteResourcesAttachMojo.GOAL_NAME, defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true) +public class SiteResourcesAttachMojo extends AbstractSiteMojo { + + public static final String GOAL_NAME = "attach-resources"; + + /** + * Directory containing the site.xml file and the source for hand written docs (one directory + * per Doxia-source-supported markup types) + * @see Doxia Markup Languages References. + */ + @Parameter(defaultValue = "${basedir}/src/site") + protected File siteDirectory; + + /** + * Maven ProjectHelper. + */ + @Component + private MavenProjectHelper projectHelper; + + @Component(hint = ARCHIVE_EXTENSION) + private Archiver zipArchiver; + + /** + * The file name patterns to exclude (potentially in addition to the default ones mentioned at {@link #addDefaultExcludes}). + * The format of each pattern is described in {@link org.codehaus.plexus.util.DirectoryScanner}. + * The comparison is performed against the file path relative to the {@link #siteDirectory}. + *

+ * Each value is either a regex pattern if enclosed within {@code %regex[} and {@code ]}, otherwise an + * Ant pattern. + * Exclusions take precedence over inclusions via {@link #includes}. + * In any case all site descriptors are always excluded ({@code site.xml} and {@code site_*.xml}). + */ + @Parameter(defaultValue = "**/.gitattributes", required = true) + protected Set excludes; + + /** + * The file name patterns to include. The format of each pattern is described in {@link org.codehaus.plexus.util.DirectoryScanner}. + * The comparison is performed against the file path relative to the {@link #siteDirectory}. + * Since this is hardly predictable it is recommended to use only filename/directory name patterns here + * but not take into account file system hierarchies! + *

+ * Each value is either a regex pattern if enclosed within {@code %regex[} and {@code ]}, otherwise an + * Ant pattern. + * If this is not set, everything is included. + */ + @Parameter(required = false) + protected Set includes; + + /** + * By default certain metadata files are excluded which means they will not be copied into the package. + * If you need them for a particular reason you can do that by setting this parameter to {@code false}. + * + * @see org.codehaus.plexus.util.AbstractScanner#DEFAULTEXCLUDES + */ + @Parameter(defaultValue = "true") + protected boolean addDefaultExcludes; + + /** + * Attach site resources in archive only if packaging is pom. + */ + @Parameter(defaultValue = "true") + private boolean pomPackagingOnly; + + public static final String CLASSIFIER = "site-resources"; + public static final String ARCHIVE_EXTENSION = "zip"; + + public void execute() throws MojoExecutionException { + if (pomPackagingOnly && !"pom".equals(project.getPackaging())) { + // https://issues.apache.org/jira/browse/MSITE-597 + getLog().info("Skipping because packaging '" + project.getPackaging() + "' is not pom."); + return; + } + + if (siteDirectory.exists()) { + try { + File destFile = new File( + project.getBuild().getDirectory(), + project.getBuild().getFinalName() + "-" + CLASSIFIER + "." + ARCHIVE_EXTENSION); + + File siteResourcesArchiveFile = createArchive(zipArchiver, destFile); + // Attach the site resources archive + getLog().info("Attaching site resources archive with classifier '" + CLASSIFIER + "'."); + projectHelper.attachArtifact(project, ARCHIVE_EXTENSION, CLASSIFIER, siteResourcesArchiveFile); + } catch (IOException e) { + throw new MojoExecutionException("Unable to archive site resources", e); + } + } else { + getLog().warn("No site resources found: nothing to attach."); + } + } + + private FileSet createFileSet() { + DefaultFileSet fileSet = new DefaultFileSet(); + fileSet.setDirectory(siteDirectory); + Set excludes = new HashSet<>(this.excludes); + // always exclude all site descriptors + excludes.add("site.xml"); + excludes.add("site_*.xml"); + fileSet.setExcludes(excludes.toArray(new String[0])); + if (includes != null && !includes.isEmpty()) { + fileSet.setIncludes(includes.toArray(new String[0])); + } + fileSet.setUsingDefaultExcludes(addDefaultExcludes); + return fileSet; + } + + public File createArchive(Archiver archiver, File destFile) throws ArchiverException, IOException { + archiver.setDestFile(destFile); + archiver.addFileSet(createFileSet()); + archiver.createArchive(); + return archiver.getDestFile(); + } + + public File getSiteDirectory() { + return siteDirectory; + } +} diff --git a/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java b/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java index 1030d63c..6fe49d10 100644 --- a/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java +++ b/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java @@ -179,6 +179,12 @@ public abstract class AbstractSiteRenderingMojo extends AbstractSiteDescriptorMo @Component protected MavenReportExecutor mavenReportExecutor; + @Component + private MavenSession session; + + @Component + protected SiteResourcesResolver siteResourcesResolver; + /** * Gets the input files encoding. * @@ -543,4 +549,12 @@ private void populateItemRefs(List items, Locale locale, Map localesList = getLocales(); for (Locale locale : localesList) { diff --git a/src/main/java/org/apache/maven/plugins/site/render/SiteResourcesResolver.java b/src/main/java/org/apache/maven/plugins/site/render/SiteResourcesResolver.java new file mode 100644 index 00000000..eb5bf45a --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/site/render/SiteResourcesResolver.java @@ -0,0 +1,289 @@ +/* + * 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 + * + * http://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.maven.plugins.site.render; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.site.SiteResourcesAttachMojo; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.dir.DirectoryArchiver; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ComponentConfigurator; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.transfer.ArtifactNotFoundException; + +/** + * Resolves and extracts/copies inherited site resources from parent projects. + * @see SiteResourcesAttachMojo + */ +@Named +@Singleton +public class SiteResourcesResolver { + + private final UnArchiver unArchiver; + private final RepositorySystem repoSystem; + private final ComponentConfigurator componentConfigurator; + + @Inject + public SiteResourcesResolver( + @Named(SiteResourcesAttachMojo.ARCHIVE_EXTENSION) UnArchiver unArchiver, + RepositorySystem repoSystem, + ComponentConfigurator componentConfigurator) { + super(); + this.unArchiver = unArchiver; + this.repoSystem = repoSystem; + this.componentConfigurator = componentConfigurator; + } + + public void resolveParentSiteResources( + MavenSession mavenSession, + MavenProject project, + PluginDescriptor pluginDescriptor, + File destDirectory, + Log log) + throws IOException { + MavenProject parent = project.getParent(); + if (parent != null) { + // start with the topmost one to allow child projects to override parent resources + resolveParentSiteResources(mavenSession, parent, pluginDescriptor, destDirectory, log); + // is it part of a multi-module project? + if (parent.getBasedir() != null) { + resolveLocalSiteResources(mavenSession, parent, pluginDescriptor, destDirectory, log); + } else { + resolveRepositorySiteResources( + RepositoryUtils.toArtifact(parent.getArtifact()), + mavenSession.getRepositorySession(), + parent.getRemoteProjectRepositories(), + destDirectory, + log); + } + } + } + + protected void resolveRepositorySiteResources( + Artifact artifact, + RepositorySystemSession repoSession, + List remoteRepositories, + File destDirectory, + Log log) + throws IOException { + final Artifact siteResourcesArtifact; + try { + siteResourcesArtifact = resolveSiteResources(artifact, repoSession, remoteRepositories); + } catch (ArtifactResolutionException e) { + throw new IOException("Error resolving site resources artifact for " + artifact, e); + } + if (siteResourcesArtifact != null) { + try { + extractArchive(siteResourcesArtifact.getFile(), destDirectory); + } catch (ArchiverException e) { + throw new IOException("Error extracting archive " + siteResourcesArtifact.getFile(), e); + } + log.info("Copied inherited site resources from " + artifact + " to " + destDirectory); + } else { + log.debug("No site resources found for " + artifact); + } + } + + protected Artifact resolveSiteResources( + Artifact parentProjectArtifact, + RepositorySystemSession repoSession, + List remoteRepositories) + throws ArtifactResolutionException { + try { + Artifact siteResourcesArtifact = new DefaultArtifact( + parentProjectArtifact.getGroupId(), + parentProjectArtifact.getArtifactId(), + SiteResourcesAttachMojo.CLASSIFIER, + SiteResourcesAttachMojo.ARCHIVE_EXTENSION, + parentProjectArtifact.getVersion()); + ArtifactRequest request = + new ArtifactRequest(siteResourcesArtifact, remoteRepositories, "remote-site-resources"); + ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); + return result.getArtifact(); + } catch (ArtifactResolutionException e) { + if (e.getCause() instanceof ArtifactNotFoundException) { + // this is no error + return null; + } + throw e; + } + } + + protected void extractArchive(File archiveFile, File destDirectory) throws ArchiverException { + unArchiver.setSourceFile(archiveFile); + unArchiver.setDestDirectory(destDirectory); + unArchiver.setOverwrite(true); + unArchiver.extract(); + } + + private void resolveLocalSiteResources( + MavenSession mavenSession, + MavenProject currentProject, + PluginDescriptor pluginDescriptor, + File destDirectory, + Log log) + throws IOException { + // evaluate the configuration of the according mojo + Plugin sitePlugin = currentProject.getPlugin("org.apache.maven.plugins:maven-site-plugin"); + // also evaluate pluginMgmt + if (sitePlugin != null) { + // just use the first potential execution's configuration + Optional configuration = sitePlugin.getExecutions().stream() + .filter(e -> e.getGoals().contains(SiteResourcesAttachMojo.GOAL_NAME)) + .map(e -> (Xpp3Dom) e.getConfiguration()) + .findFirst(); + if (configuration.isPresent()) { + try { + copySiteResourcesToDirectory( + mavenSession, currentProject, pluginDescriptor, configuration.get(), destDirectory, log); + } catch (ArchiverException e1) { + throw new IOException("Error copying site resources to " + destDirectory, e1); + } catch (ComponentConfigurationException e1) { + throw new IOException( + "Error extracting mojo configuration from " + currentProject.getArtifact(), e1); + } + } else { + log.debug("No automatic execution of goal " + SiteResourcesAttachMojo.GOAL_NAME + " found in " + + currentProject.getArtifact()); + } + } else { + log.debug("No site plugin found in project " + currentProject.getArtifact()); + } + } + + void copySiteResourcesToDirectory( + MavenSession mavenSession, + MavenProject project, + PluginDescriptor pluginDescriptor, + Xpp3Dom pomConfiguration, + File destDirectory, + Log log) + throws ArchiverException, IOException, ComponentConfigurationException { + // get mojo descriptor of sibling mojo! + MojoDescriptor attachMojoDescriptor = pluginDescriptor.getMojo(SiteResourcesAttachMojo.GOAL_NAME); + MojoExecution attachMojoExecution = new MojoExecution(attachMojoDescriptor, "implicit-attach-resources"); + SiteResourcesAttachMojo mojo = new SiteResourcesAttachMojo(); + // modify MavenSession to use the basedir of another project as context + MavenSession mavenSessionForOtherProject = mavenSession.clone(); + mavenSessionForOtherProject.setCurrentProject(project); + ExpressionEvaluator expressionEvaluator = + new PluginParameterExpressionEvaluator(mavenSessionForOtherProject, attachMojoExecution); + + componentConfigurator.configureComponent( + mojo, + getEffectiveMojoConfiguration(pomConfiguration, attachMojoDescriptor), + expressionEvaluator, + pluginDescriptor.getClassRealm()); + // this is a pseudo archiver which just copies from source to destination considering the fileSet configuration + DirectoryArchiver archiver = new DirectoryArchiver(); + mojo.createArchive(archiver, destDirectory); + log.info("Copied inherited site resources from " + mojo.getSiteDirectory() + " to " + destDirectory); + } + + /** Logic similar to {@link DefaultLifecycleExecutionPlanCalculator#finalizeMojoConfiguration}, + * i.e. merges pom configuration with mojo default configuration and removes configuration elements not belonging to mojo parameters. + * + * This will also remove configuration added via the {@link org.apache.maven.model.plugin.DefaultReportingConverter} in Maven 3. + * This is {@code reportPlugins} and {@code outputDirectory} which cannot be injected into mojos. + */ + private PlexusConfiguration getEffectiveMojoConfiguration(Xpp3Dom pomConfiguration, MojoDescriptor mojoDescriptor) { + Xpp3Dom mojoConfiguration = createFromPlexusConfiguration(mojoDescriptor.getMojoConfiguration()); + Xpp3Dom finalConfiguration = new Xpp3Dom("configuration"); + + if (mojoDescriptor.getParameters() != null) { + for (Parameter parameter : mojoDescriptor.getParameters()) { + Xpp3Dom parameterConfiguration = pomConfiguration.getChild(parameter.getName()); + + if (parameterConfiguration == null) { + parameterConfiguration = pomConfiguration.getChild(parameter.getAlias()); + } + + Xpp3Dom parameterDefaults = mojoConfiguration.getChild(parameter.getName()); + + parameterConfiguration = Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE); + + if (parameterConfiguration != null) { + parameterConfiguration = new Xpp3Dom(parameterConfiguration, parameter.getName()); + + if (StringUtils.isEmpty(parameterConfiguration.getAttribute("implementation")) + && StringUtils.isNotEmpty(parameter.getImplementation())) { + parameterConfiguration.setAttribute("implementation", parameter.getImplementation()); + } + + finalConfiguration.addChild(parameterConfiguration); + } + } + } + return new XmlPlexusConfiguration(finalConfiguration); + } + + /** + * Converts a {@link PlexusConfiguration} to a new {@link Xpp3Dom}. + * @param configuration + * @return the converted configuration + */ + private static Xpp3Dom createFromPlexusConfiguration(PlexusConfiguration configuration) { + Xpp3Dom dom = new Xpp3Dom(configuration.getName()); + + dom.setValue(configuration.getValue(null)); + + String[] attributeNames = configuration.getAttributeNames(); + for (String attributeName : attributeNames) { + dom.setAttribute(attributeName, configuration.getAttribute(attributeName)); + } + + PlexusConfiguration[] children = configuration.getChildren(); + for (PlexusConfiguration child : children) { + dom.addChild(createFromPlexusConfiguration(child)); + } + return dom; + } +} diff --git a/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java b/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java index eb2ad981..bc3043ec 100644 --- a/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java +++ b/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java @@ -127,6 +127,7 @@ private WebAppContext createWebApplication() throws MojoExecutionException { webapp.setAttribute(DoxiaFilter.LOCALES_LIST_KEY, localesList); try { + resolveParentSiteResources(tempWebappDirectory); Map i18nDoxiaContexts = new HashMap<>(); for (Locale locale : localesList) {