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