1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.nuiton.jrst;
23
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.StringWriter;
28 import java.io.UnsupportedEncodingException;
29 import java.io.Writer;
30 import java.lang.reflect.Field;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37
38 import org.apache.commons.collections.CollectionUtils;
39 import org.apache.commons.io.FileUtils;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.maven.doxia.parser.Parser;
42 import org.apache.maven.doxia.site.decoration.Menu;
43 import org.apache.maven.doxia.site.decoration.MenuItem;
44 import org.apache.maven.doxia.siterenderer.DefaultSiteRenderer;
45 import org.apache.maven.doxia.siterenderer.DocumentRenderer;
46 import org.apache.maven.doxia.siterenderer.Renderer;
47 import org.apache.maven.doxia.siterenderer.RendererException;
48 import org.apache.maven.doxia.siterenderer.RenderingContext;
49 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
50 import org.apache.maven.project.MavenProject;
51 import org.apache.velocity.VelocityContext;
52 import org.apache.velocity.app.VelocityEngine;
53 import org.apache.velocity.context.Context;
54 import org.codehaus.plexus.component.annotations.Component;
55 import org.codehaus.plexus.component.annotations.Requirement;
56 import org.codehaus.plexus.i18n.I18N;
57 import org.codehaus.plexus.velocity.VelocityComponent;
58 import org.dom4j.Document;
59
60 import com.google.common.collect.Maps;
61
62
63
64
65
66
67
68
69 @Component(role = Renderer.class, hint = "default")
70 public class JrstSiteRenderer extends DefaultSiteRenderer {
71
72 public static final String DEFAULT_PDF_FILENAME = "site";
73
74
75 protected List<Locale> locales;
76
77
78 protected Locale locale;
79
80
81 protected MavenProject mavenProject;
82
83 protected boolean pdfGenerationEnabled;
84
85 protected boolean verbose;
86
87 @Requirement(role = Parser.class, hint = "jrst", optional = true)
88 protected AbstractJrstParser jrstParser;
89
90 @Override
91 public void render(Collection<DocumentRenderer> documents,
92 SiteRenderingContext siteRenderingContext,
93 File outputDirectory)
94 throws RendererException, IOException {
95
96
97
98 locale = siteRenderingContext.getLocale();
99
100 locales = Collections.unmodifiableList(siteRenderingContext.getSiteLocales());
101
102 Map<String, ?> templateProperties = siteRenderingContext.getTemplateProperties();
103
104 mavenProject = (MavenProject) templateProperties.get("project");
105
106 verbose = getBooleanProperty("site.verbose") ||
107 getLogger().isDebugEnabled();
108
109 pdfGenerationEnabled = getBooleanProperty("pdfGenerationEnabled");
110
111 super.render(documents, siteRenderingContext, outputDirectory);
112
113 if (pdfGenerationEnabled) {
114
115
116 List<String> relativPathsFromMenu =
117 getDocumentRelativePathsFromMenu(siteRenderingContext);
118
119
120 Map<String, String> relatifPaths = buildDocMap(documents);
121
122
123 List<String> documentRefs = getDocumentRefs(relatifPaths,
124 relativPathsFromMenu);
125
126 if (CollectionUtils.isEmpty(documentRefs)) {
127
128
129 if (getLogger().isInfoEnabled()) {
130 getLogger().info("No document to put in pdf, skip pdf generation.");
131 }
132 } else {
133 String pdfFilename = getPdfFileName();
134
135 try {
136 Field i18nField = ReflectUtil.getField(DefaultSiteRenderer.class, "i18n");
137 I18N i18n = (I18N) i18nField.get(this);
138
139 renderPdf(i18n, documentRefs,
140 siteRenderingContext,
141 outputDirectory,
142 pdfFilename);
143 } catch (Exception e) {
144 getLogger().error("Can't find rst resource to generate pdf documentation", e);
145 }
146 }
147
148 }
149 }
150
151 @Override
152 public void renderDocument(Writer writer,
153 RenderingContext renderingContext,
154 SiteRenderingContext context)
155 throws RendererException, FileNotFoundException, UnsupportedEncodingException {
156
157 if (AbstractJrstParser.JRST_PARSER_ID.equals(renderingContext.getParserId())) {
158
159
160
161 jrstParser.setRenderingContext(renderingContext);
162 jrstParser.setMavenProject(mavenProject);
163 jrstParser.setVerbose(verbose);
164
165 }
166 super.renderDocument(writer, renderingContext, context);
167 }
168
169 protected String getPdfFileName() {
170
171 String pdfFilename = getStringProperty("pdfFilename");
172 if (StringUtils.isBlank(pdfFilename)) {
173 pdfFilename = DEFAULT_PDF_FILENAME;
174 }
175
176 if (!locales.isEmpty() && !locale.equals(locales.get(0))) {
177
178 pdfFilename += "_" + locale.getCountry();
179 }
180 pdfFilename += ".pdf";
181 return pdfFilename;
182 }
183
184 protected void renderPdf(I18N i18n,
185 List<String> documentRefs,
186 SiteRenderingContext siteRenderingContext,
187 File outputDirectory,
188 String pdfFilename)
189 throws RendererException, FileNotFoundException, UnsupportedEncodingException {
190
191 if (getLogger().isDebugEnabled()) {
192 getLogger().debug("Generate Site Pdf: " + pdfFilename);
193 }
194
195 Context vc = preparePdfVelocityContext(i18n, documentRefs);
196
197
198 File fileOut = new File(outputDirectory, pdfFilename);
199 if (verbose) {
200 getLogger().info("Will generate the site pdf: " + fileOut);
201 }
202
203 try {
204 StringWriter sw = new StringWriter();
205 Field velocityField =
206 ReflectUtil.getField(DefaultSiteRenderer.class, "velocity");
207
208 VelocityComponent velocity = (VelocityComponent) velocityField.get(this);
209 VelocityEngine engine = velocity.getEngine();
210
211 String inputEncoding = siteRenderingContext.getInputEncoding();
212
213
214
215 engine.mergeTemplate("/META-INF/maven/RstAggregation.vm", inputEncoding, vc, sw);
216 String fileContent = sw.toString();
217 File pdfDoc = new File(outputDirectory, "pdfDoc.rst");
218 FileUtils.writeStringToFile(pdfDoc, fileContent, inputEncoding);
219
220
221 Document doc = jrstParser.getStrategy().generateRstToXml(
222 fileOut, inputEncoding);
223
224
225 JRST.generatePdf(pdfDoc, fileOut, JRST.Overwrite.ALLTIME, doc);
226
227 } catch (Exception e) {
228 getLogger().error("Can't generate pdf documentation of the project at " + fileOut, e);
229 }
230 }
231
232 protected Context preparePdfVelocityContext(I18N i18n,
233 List<String> documentRefs) {
234
235 Context vc = new VelocityContext();
236 vc.put("locale", locale);
237 vc.put("supportedLocales", locales);
238 String tableOfContent = i18n.getString("jrst-site-renderer", locale, "content");
239 String docName = mavenProject.getName();
240 String titleDecoration = StringUtils.rightPad("", docName.length(), '=');
241 vc.put("titleDecoration", titleDecoration);
242 vc.put("docName", docName);
243 vc.put("tableContentName", tableOfContent);
244
245
246
247 vc.put("basedir", mavenProject.getBasedir());
248 vc.put("separator", File.separatorChar);
249 vc.put("documentRefs", documentRefs);
250 return vc;
251 }
252
253 protected List<String> getDocumentRelativePathsFromMenu(SiteRenderingContext siteRenderingContext) {
254 List<String> paths = new LinkedList<String>();
255 for (Menu menu : siteRenderingContext.getDecoration().getMenus()) {
256 for (MenuItem item : menu.getItems()) {
257 buildListPathsFromMenuItem(item, paths);
258 }
259 }
260 return paths;
261 }
262
263 protected List<String> getDocumentRefs(Map<String, String> relatifPaths,
264 List<String> relativPathsFromMenu) {
265
266
267 List<String> documentRefs = new LinkedList<String>();
268 for (String path : relativPathsFromMenu) {
269
270 String rstFilename = relatifPaths.get(path);
271 if (rstFilename != null) {
272 if (verbose) {
273 getLogger().info("Add document to render in pdf: " +
274 rstFilename);
275 }
276 documentRefs.add(rstFilename);
277 }
278 }
279 return documentRefs;
280 }
281
282 protected Map<String, String> buildDocMap(Collection<DocumentRenderer> documents) {
283
284 Map<String, String> map = Maps.newTreeMap();
285
286 for (DocumentRenderer doc : documents) {
287 RenderingContext renderingContext = doc.getRenderingContext();
288 String inputName = renderingContext.getInputName();
289
290 if (inputName.endsWith("rst") || inputName.endsWith("rst.vm")) {
291
292 String[] splitName = inputName.split("\\.");
293 String htmlName = splitName[0] + "." + "html";
294 String relativePath = "." + File.separator + htmlName;
295 if (getLogger().isDebugEnabled()) {
296 getLogger().debug("relativePath: " + relativePath);
297 }
298
299 map.put(relativePath, inputName);
300
301
302
303
304
305 }
306 }
307 return map;
308 }
309
310 protected Collection<String> buildListPathsFromMenuItem(MenuItem item,
311 Collection<String> paths) {
312
313 String href = item.getHref();
314 if (!href.startsWith("http") && !href.startsWith("..")) {
315 boolean addHref = true;
316 for (Locale loc : locales) {
317 if (href.startsWith(loc.toString())) {
318 addHref = false;
319 }
320 }
321 if (addHref) {
322 if (!href.startsWith("./")) {
323 href = "./" + href;
324 }
325 if (getLogger().isDebugEnabled()) {
326 getLogger().debug("document to render in pdf: " + href);
327 }
328 paths.add(href);
329 }
330 }
331
332 List<MenuItem> subItems = item.getItems();
333 if (!subItems.isEmpty()) {
334 for (MenuItem subItem : subItems) {
335 paths = buildListPathsFromMenuItem(subItem, paths);
336 }
337 }
338 return paths;
339 }
340
341 protected String getStringProperty(String propertyName) {
342 Object value = mavenProject.getProperties().get(propertyName);
343 String result = value == null ? null : String.valueOf(value);
344 return result;
345 }
346
347 protected boolean getBooleanProperty(String propertyName) {
348 boolean result = "true".equals(getStringProperty(propertyName));
349 return result;
350 }
351
352 }