1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.pdf;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.ArrayDeque;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Deque;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31
32 import org.apache.maven.doxia.document.DocumentModel;
33 import org.apache.maven.doxia.document.DocumentTOC;
34 import org.apache.maven.doxia.document.DocumentTOCItem;
35 import org.apache.maven.model.Reporting;
36 import org.apache.maven.plugins.annotations.Execute;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.project.MavenProject;
41 import org.codehaus.plexus.util.FileUtils;
42
43
44
45
46
47
48
49 @Mojo(name = "aggregate", aggregator = true, requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
50 @Execute(goal = "pdf")
51
52 public class PdfAggregateMojo extends PdfMojo {
53
54
55
56 @Parameter(defaultValue = "${reactorProjects}", required = true, readonly = true)
57 private List<MavenProject> reactorProjects;
58
59
60
61
62 @Parameter(defaultValue = "${project.build.directory}/pdf-aggregate", required = true)
63 private File aggregatedOutputDirectory;
64
65
66
67
68 @Parameter(defaultValue = "${project.build.directory}/pdf-aggregate", required = true)
69 private File aggregatedWorkingDirectory;
70
71 protected File getOutputDirectory() {
72 return aggregatedOutputDirectory;
73 }
74
75 protected File getWorkingDirectory() {
76 return aggregatedWorkingDirectory;
77 }
78
79 protected boolean isIncludeReports() {
80 return false;
81 }
82
83 protected void prepareTempSiteDirectory(final File tmpSiteDir) {
84 tmpSiteDir.mkdirs();
85 }
86
87 @Override
88 protected void appendGeneratedReports(DocumentModel model, Locale locale) {
89 super.appendGeneratedReports(model, locale);
90
91 getLog().info("Appending staged reports.");
92
93 DocumentTOC toc = model.getToc();
94
95 File dstSiteTmp = null;
96 try {
97 dstSiteTmp = getSiteDirectoryTmp();
98 } catch (IOException ioe) {
99 getLog().error("unexpected IOException while getting aggregator root tmp site dir", ioe);
100 }
101 if (!dstSiteTmp.exists()) {
102 getLog().error("Top-level project does not have src.tmp directory");
103 return;
104 }
105
106 for (MavenProject reactorProject : reactorProjects) {
107 getLog().info("Appending " + reactorProject.getArtifactId() + " reports.");
108
109 copySiteDirectoryTmp(reactorProject, dstSiteTmp);
110
111 addTOCItems(toc, reactorProject);
112 }
113 }
114
115 private void copySiteDirectoryTmp(MavenProject project, File dstSiteTmp) {
116 Reporting reporting = project.getReporting();
117 if (reporting == null) {
118 getLog().info("Skipping reactor project " + project + ": no reporting");
119 return;
120 }
121
122 File srcSiteTmp = getModuleSiteDirectoryTmp(project);
123 if (!srcSiteTmp.exists()) {
124 getLog().info("Skipping reactor project " + project + ": no site.tmp directory");
125 return;
126 }
127
128 String stagedId = getStagedId(project);
129
130 try {
131 String defaultExcludes = FileUtils.getDefaultExcludesAsString();
132 List<String> srcDirNames = FileUtils.getDirectoryNames(srcSiteTmp, "*", defaultExcludes, false);
133 for (String srcDirName : srcDirNames) {
134 File srcDir = new File(srcSiteTmp, srcDirName);
135 File dstDir = new File(new File(dstSiteTmp, srcDirName), stagedId);
136 if (!dstDir.exists() && !dstDir.mkdirs()) {
137 getLog().error("Could not create directory: " + dstDir);
138 return;
139 }
140
141 FileUtils.copyDirectoryStructure(srcDir, dstDir);
142 }
143 } catch (IOException e) {
144 getLog().error(
145 "Error while copying sub-project " + project.getArtifactId() + " site.tmp: "
146 + e.getMessage(),
147 e);
148 }
149 }
150
151 private void addTOCItems(DocumentTOC topLevelToc, MavenProject project) {
152 String stagedId = getStagedId(project);
153
154 Map<String, Object> toc = loadToc(project);
155
156 List<Map<String, Object>> items = (ArrayList) toc.get("items");
157
158 DocumentTOCItem tocItem = new DocumentTOCItem();
159 tocItem.setName(project.getName());
160 tocItem.setRef(stagedId);
161
162 if (items.size() == 1 && "project-info".equals(items.get(0).get("ref"))) {
163
164 items = (List) items.get(0).get("items");
165 }
166
167 for (Map<String, Object> item : items) {
168 addTOCItems(tocItem, item, stagedId);
169 }
170
171 topLevelToc.addItem(tocItem);
172 }
173
174 private Map<String, Object> loadToc(MavenProject project) {
175 try {
176 return TocFileHelper.loadToc(getModuleWorkingDirectory(project));
177 } catch (IOException e) {
178 getLog().error("Error while reading table of contents of module " + project.getArtifactId(), e);
179 return Collections.emptyMap();
180 }
181 }
182
183 private void addTOCItems(DocumentTOCItem parent, Map<String, Object> item, String stagedId) {
184 DocumentTOCItem tocItem = new DocumentTOCItem();
185 tocItem.setName((String) item.get("name"));
186 tocItem.setRef(stagedId + "/" + item.get("ref"));
187
188 List<Map<String, Object>> items = (List) item.get("items");
189
190 for (Map<String, Object> it : items) {
191 addTOCItems(tocItem, it, stagedId);
192 }
193
194 parent.addItem(tocItem);
195 }
196
197 private String getStagedId(MavenProject p) {
198 Deque<String> projectPath = new ArrayDeque<>();
199 projectPath.addFirst(p.getArtifactId());
200 while (p.getParent() != null) {
201 p = p.getParent();
202 projectPath.addFirst(p.getArtifactId());
203 }
204
205 StringBuilder stagedId = new StringBuilder();
206 Iterator<String> artifactIds = projectPath.iterator();
207 while (artifactIds.hasNext()) {
208 stagedId.append(artifactIds.next());
209 if (artifactIds.hasNext()) {
210 stagedId.append('/');
211 }
212 }
213 return stagedId.toString();
214 }
215
216 private File getModuleWorkingDirectory(MavenProject project) {
217 return new File(project.getBuild().getDirectory(), "pdf");
218 }
219
220 private File getModuleSiteDirectoryTmp(MavenProject project) {
221 return new File(getModuleWorkingDirectory(project), "site.tmp");
222 }
223 }