1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.export.html; |
21 |
|
|
22 |
|
import java.io.File; |
23 |
|
import java.io.FileFilter; |
24 |
|
import java.io.FileInputStream; |
25 |
|
import java.io.IOException; |
26 |
|
import java.lang.reflect.Type; |
27 |
|
import java.util.Collection; |
28 |
|
import java.util.HashSet; |
29 |
|
import java.util.Set; |
30 |
|
import java.util.zip.ZipEntry; |
31 |
|
import java.util.zip.ZipOutputStream; |
32 |
|
|
33 |
|
import org.apache.commons.io.IOUtils; |
34 |
|
import org.apache.commons.io.filefilter.NotFileFilter; |
35 |
|
import org.apache.commons.io.filefilter.SuffixFileFilter; |
36 |
|
import org.apache.commons.io.filefilter.TrueFileFilter; |
37 |
|
import org.apache.commons.lang3.RandomStringUtils; |
38 |
|
import org.slf4j.Logger; |
39 |
|
import org.slf4j.LoggerFactory; |
40 |
|
import org.xwiki.context.Execution; |
41 |
|
import org.xwiki.context.ExecutionContext; |
42 |
|
import org.xwiki.context.ExecutionContextException; |
43 |
|
import org.xwiki.context.ExecutionContextManager; |
44 |
|
import org.xwiki.environment.Environment; |
45 |
|
import org.xwiki.model.reference.DocumentReference; |
46 |
|
import org.xwiki.model.reference.DocumentReferenceResolver; |
47 |
|
import org.xwiki.model.reference.EntityReference; |
48 |
|
import org.xwiki.url.URLContextManager; |
49 |
|
|
50 |
|
import com.xpn.xwiki.XWikiContext; |
51 |
|
import com.xpn.xwiki.XWikiException; |
52 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
53 |
|
import com.xpn.xwiki.util.Util; |
54 |
|
import com.xpn.xwiki.web.ExportURLFactory; |
55 |
|
import com.xpn.xwiki.web.Utils; |
56 |
|
|
57 |
|
|
58 |
|
|
59 |
|
|
60 |
|
@version |
61 |
|
@since |
62 |
|
|
|
|
| 0% |
Uncovered Elements: 141 (141) |
Complexity: 26 |
Complexity Density: 0.24 |
|
63 |
|
public class HtmlPackager |
64 |
|
{ |
65 |
|
private static final Logger LOGGER = LoggerFactory.getLogger(HtmlPackager.class); |
66 |
|
|
67 |
|
|
68 |
|
|
69 |
|
|
70 |
|
private static final String POINT = "."; |
71 |
|
|
72 |
|
|
73 |
|
|
74 |
|
|
75 |
|
private static final String CONTEXT_TDOC = "tdoc"; |
76 |
|
|
77 |
|
|
78 |
|
|
79 |
|
|
80 |
|
private static final String VCONTEXT_DOC = "doc"; |
81 |
|
|
82 |
|
|
83 |
|
|
84 |
|
|
85 |
|
private static final String VCONTEXT_CDOC = "cdoc"; |
86 |
|
|
87 |
|
|
88 |
|
|
89 |
|
|
90 |
|
private static final String VCONTEXT_TDOC = CONTEXT_TDOC; |
91 |
|
|
92 |
|
|
93 |
|
|
94 |
|
|
95 |
|
private static final String ZIPPATH_SEPARATOR = "/"; |
96 |
|
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
|
private String name = "html.export"; |
101 |
|
|
102 |
|
|
103 |
|
|
104 |
|
|
105 |
|
private String description = ""; |
106 |
|
|
107 |
|
|
108 |
|
@link |
109 |
|
|
110 |
|
private Set<String> pages = new HashSet<String>(); |
111 |
|
|
112 |
|
|
113 |
|
|
114 |
|
|
115 |
|
private Environment environment = Utils.getComponent((Type) Environment.class); |
116 |
|
|
117 |
|
|
118 |
|
|
119 |
|
|
120 |
|
@param |
121 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
122 |
0 |
public void setName(String name)... |
123 |
|
{ |
124 |
0 |
this.name = name; |
125 |
|
} |
126 |
|
|
127 |
|
|
128 |
|
@return |
129 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
130 |
0 |
public String getName()... |
131 |
|
{ |
132 |
0 |
return this.name; |
133 |
|
} |
134 |
|
|
135 |
|
|
136 |
|
|
137 |
|
|
138 |
|
@param |
139 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
140 |
0 |
public void setDescription(String description)... |
141 |
|
{ |
142 |
0 |
this.description = description; |
143 |
|
} |
144 |
|
|
145 |
|
|
146 |
|
@return |
147 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
148 |
0 |
public String getDescription()... |
149 |
|
{ |
150 |
0 |
return this.description; |
151 |
|
} |
152 |
|
|
153 |
|
|
154 |
|
|
155 |
|
|
156 |
|
@param |
157 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
158 |
0 |
public void addPage(String page)... |
159 |
|
{ |
160 |
0 |
this.pages.add(page); |
161 |
|
} |
162 |
|
|
163 |
|
|
164 |
|
|
165 |
|
|
166 |
|
@param |
167 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
168 |
0 |
public void addPages(Collection<String> pages)... |
169 |
|
{ |
170 |
0 |
this.pages.addAll(pages); |
171 |
|
} |
172 |
|
|
173 |
|
|
174 |
|
|
175 |
|
|
176 |
|
@param@link |
177 |
|
|
178 |
|
@param |
179 |
|
@param |
180 |
|
@throws |
181 |
|
@throws |
182 |
|
|
|
|
| 0% |
Uncovered Elements: 29 (29) |
Complexity: 4 |
Complexity Density: 0.16 |
|
183 |
0 |
private void renderDocument(String pageName, ZipOutputStream zos, XWikiContext context)... |
184 |
|
throws XWikiException, IOException |
185 |
|
{ |
186 |
0 |
DocumentReferenceResolver<String> resolver = |
187 |
|
Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "current"); |
188 |
0 |
DocumentReference docReference = resolver.resolve(pageName); |
189 |
0 |
XWikiDocument doc = context.getWiki().getDocument(docReference, context); |
190 |
|
|
191 |
0 |
if (doc.isNew()) { |
192 |
|
|
193 |
0 |
return; |
194 |
|
} |
195 |
|
|
196 |
0 |
String zipname = doc.getDocumentReference().getWikiReference().getName(); |
197 |
0 |
for (EntityReference space : doc.getDocumentReference().getSpaceReferences()) { |
198 |
0 |
zipname += POINT + space.getName(); |
199 |
|
} |
200 |
0 |
zipname += POINT + doc.getDocumentReference().getName(); |
201 |
0 |
String language = doc.getLanguage(); |
202 |
0 |
if (language != null && language.length() != 0) { |
203 |
0 |
zipname += POINT + language; |
204 |
|
} |
205 |
|
|
206 |
0 |
zipname += ".html"; |
207 |
|
|
208 |
0 |
ZipEntry zipentry = new ZipEntry(zipname); |
209 |
0 |
zos.putNextEntry(zipentry); |
210 |
|
|
211 |
0 |
String originalDatabase = context.getWikiId(); |
212 |
0 |
try { |
213 |
0 |
context.setWikiId(doc.getDocumentReference().getWikiReference().getName()); |
214 |
0 |
context.setDoc(doc); |
215 |
|
|
216 |
0 |
XWikiDocument tdoc = doc.getTranslatedDocument(context); |
217 |
0 |
context.put(CONTEXT_TDOC, tdoc); |
218 |
|
|
219 |
0 |
String content = evaluateDocumentContent(context); |
220 |
|
|
221 |
0 |
zos.write(content.getBytes(context.getWiki().getEncoding())); |
222 |
0 |
zos.closeEntry(); |
223 |
|
} finally { |
224 |
0 |
context.setWikiId(originalDatabase); |
225 |
|
} |
226 |
|
} |
227 |
|
|
|
|
| 0% |
Uncovered Elements: 9 (9) |
Complexity: 1 |
Complexity Density: 0.11 |
|
228 |
0 |
private String evaluateDocumentContent(XWikiContext context) throws IOException... |
229 |
|
{ |
230 |
0 |
context.getWiki().getPluginManager().beginParsing(context); |
231 |
0 |
Utils.enablePlaceholders(context); |
232 |
0 |
String content; |
233 |
0 |
try { |
234 |
0 |
content = context.getWiki().evaluateTemplate("view.vm", context); |
235 |
0 |
content = Utils.replacePlaceholders(content, context); |
236 |
|
} finally { |
237 |
0 |
Utils.disablePlaceholders(context); |
238 |
|
} |
239 |
0 |
content = context.getWiki().getPluginManager().endParsing(content.trim(), context); |
240 |
0 |
return content; |
241 |
|
} |
242 |
|
|
243 |
|
|
244 |
|
@link |
245 |
|
|
246 |
|
@param |
247 |
|
@param |
248 |
|
@param@link |
249 |
|
@param |
250 |
|
@throws |
251 |
|
@throws |
252 |
|
|
|
|
| 0% |
Uncovered Elements: 16 (16) |
Complexity: 2 |
Complexity Density: 0.12 |
|
253 |
0 |
private void renderDocuments(ZipOutputStream zos, File tempdir, ExportURLFactory urlf, XWikiContext context)... |
254 |
|
throws XWikiException, IOException |
255 |
|
{ |
256 |
0 |
ExecutionContextManager ecim = Utils.getComponent(ExecutionContextManager.class); |
257 |
0 |
Execution execution = Utils.getComponent(Execution.class); |
258 |
|
|
259 |
0 |
try { |
260 |
0 |
XWikiContext renderContext = context.clone(); |
261 |
0 |
renderContext.put("action", "view"); |
262 |
|
|
263 |
0 |
ExecutionContext executionContext = ecim.clone(execution.getContext()); |
264 |
|
|
265 |
|
|
266 |
0 |
executionContext.setProperty("xwikicontext", renderContext); |
267 |
|
|
268 |
|
|
269 |
|
|
270 |
|
|
271 |
|
|
272 |
0 |
execution.pushContext(executionContext); |
273 |
|
|
274 |
0 |
try { |
275 |
|
|
276 |
0 |
urlf.init(this.pages, tempdir, renderContext); |
277 |
0 |
renderContext.setURLFactory(urlf); |
278 |
0 |
Utils.getComponent(URLContextManager.class).setURLFormatId("filesystem"); |
279 |
|
|
280 |
0 |
for (String pageName : this.pages) { |
281 |
0 |
renderDocument(pageName, zos, renderContext); |
282 |
|
} |
283 |
|
} finally { |
284 |
0 |
execution.popContext(); |
285 |
|
} |
286 |
|
} catch (ExecutionContextException e) { |
287 |
0 |
throw new XWikiException(XWikiException.MODULE_XWIKI_EXPORT, XWikiException.ERROR_XWIKI_INIT_FAILED, |
288 |
|
"Failed to initialize Execution Context", e); |
289 |
|
} |
290 |
|
} |
291 |
|
|
292 |
|
|
293 |
|
|
294 |
|
|
295 |
|
@param |
296 |
|
@throws |
297 |
|
@throws |
298 |
|
|
|
|
| 0% |
Uncovered Elements: 18 (18) |
Complexity: 1 |
Complexity Density: 0.06 |
|
299 |
0 |
public void export(XWikiContext context) throws IOException, XWikiException... |
300 |
|
{ |
301 |
0 |
context.getResponse().setContentType("application/zip"); |
302 |
0 |
context.getResponse().addHeader("Content-disposition", |
303 |
|
"attachment; filename=" + Util.encodeURI(this.name, context) + ".zip"); |
304 |
0 |
context.setFinished(true); |
305 |
|
|
306 |
0 |
ZipOutputStream zos = new ZipOutputStream(context.getResponse().getOutputStream()); |
307 |
|
|
308 |
0 |
File dir = this.environment.getTemporaryDirectory(); |
309 |
0 |
File tempdir = new File(dir, RandomStringUtils.randomAlphanumeric(8)); |
310 |
0 |
tempdir.mkdirs(); |
311 |
0 |
File attachmentDir = new File(tempdir, "attachment"); |
312 |
0 |
attachmentDir.mkdirs(); |
313 |
|
|
314 |
|
|
315 |
0 |
ExportURLFactory urlf = new ExportURLFactory(); |
316 |
|
|
317 |
|
|
318 |
0 |
renderDocuments(zos, tempdir, urlf, context); |
319 |
|
|
320 |
|
|
321 |
0 |
for (String skinName : urlf.getFilesystemExportContext().getNeededSkins()) { |
322 |
0 |
addSkinToZip(skinName, zos, urlf.getFilesystemExportContext().getExportedSkinFiles(), context); |
323 |
|
} |
324 |
|
|
325 |
|
|
326 |
0 |
addDirToZip(tempdir, TrueFileFilter.TRUE, zos, "", null); |
327 |
|
|
328 |
0 |
zos.setComment(this.description); |
329 |
|
|
330 |
|
|
331 |
0 |
zos.finish(); |
332 |
0 |
zos.flush(); |
333 |
|
|
334 |
|
|
335 |
0 |
deleteDirectory(tempdir); |
336 |
|
} |
337 |
|
|
338 |
|
|
339 |
|
|
340 |
|
|
341 |
|
@param |
342 |
|
|
|
|
| 0% |
Uncovered Elements: 17 (17) |
Complexity: 4 |
Complexity Density: 0.36 |
|
343 |
0 |
private static void deleteDirectory(File directory)... |
344 |
|
{ |
345 |
0 |
if (!directory.isDirectory()) { |
346 |
0 |
return; |
347 |
|
} |
348 |
|
|
349 |
0 |
File[] files = directory.listFiles(); |
350 |
|
|
351 |
0 |
if (files == null) { |
352 |
0 |
return; |
353 |
|
} |
354 |
|
|
355 |
0 |
for (File file : files) { |
356 |
0 |
if (file.isDirectory()) { |
357 |
0 |
deleteDirectory(file); |
358 |
0 |
continue; |
359 |
|
} |
360 |
|
|
361 |
0 |
file.delete(); |
362 |
|
} |
363 |
|
|
364 |
0 |
directory.delete(); |
365 |
|
} |
366 |
|
|
367 |
|
|
368 |
|
|
369 |
|
|
370 |
|
@param |
371 |
|
@param |
372 |
|
@param |
373 |
|
@throws |
374 |
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
375 |
0 |
private static void addSkinToZip(String skinName, ZipOutputStream out, Collection<String> exportedSkinFiles,... |
376 |
|
XWikiContext context) throws IOException |
377 |
|
{ |
378 |
0 |
File file = new File(context.getWiki().getEngineContext().getRealPath("/skins/" + skinName)); |
379 |
|
|
380 |
|
|
381 |
0 |
FileFilter filter = new NotFileFilter(new SuffixFileFilter(new String[] { ".vm", ".less", "skin.properties" })); |
382 |
|
|
383 |
0 |
addDirToZip(file, filter, out, "skins" + ZIPPATH_SEPARATOR + skinName + ZIPPATH_SEPARATOR, exportedSkinFiles); |
384 |
|
} |
385 |
|
|
386 |
|
|
387 |
|
|
388 |
|
|
389 |
|
@param |
390 |
|
@param |
391 |
|
@param |
392 |
|
@param |
393 |
|
@throws |
394 |
|
|
|
|
| 0% |
Uncovered Elements: 30 (30) |
Complexity: 7 |
Complexity Density: 0.35 |
|
395 |
0 |
private static void addDirToZip(File directory, FileFilter filter, ZipOutputStream out, String basePath,... |
396 |
|
Collection<String> exportedSkinFiles) throws IOException |
397 |
|
{ |
398 |
0 |
if (LOGGER.isDebugEnabled()) { |
399 |
0 |
LOGGER.debug("Adding dir [" + directory.getPath() + "] to the Zip file being generated."); |
400 |
|
} |
401 |
|
|
402 |
0 |
if (!directory.isDirectory()) { |
403 |
0 |
return; |
404 |
|
} |
405 |
|
|
406 |
0 |
File[] files = directory.listFiles(filter); |
407 |
|
|
408 |
0 |
if (files == null) { |
409 |
0 |
return; |
410 |
|
} |
411 |
|
|
412 |
0 |
for (File file : files) { |
413 |
0 |
if (file.isDirectory()) { |
414 |
0 |
addDirToZip(file, filter, out, basePath + file.getName() + ZIPPATH_SEPARATOR, exportedSkinFiles); |
415 |
|
} else { |
416 |
0 |
String path = basePath + file.getName(); |
417 |
|
|
418 |
0 |
if (exportedSkinFiles != null && exportedSkinFiles.contains(path)) { |
419 |
0 |
continue; |
420 |
|
} |
421 |
|
|
422 |
0 |
FileInputStream in = new FileInputStream(file); |
423 |
|
|
424 |
0 |
try { |
425 |
|
|
426 |
0 |
out.putNextEntry(new ZipEntry(path)); |
427 |
|
|
428 |
0 |
try { |
429 |
0 |
IOUtils.copy(in, out); |
430 |
|
} finally { |
431 |
0 |
out.closeEntry(); |
432 |
|
} |
433 |
|
} finally { |
434 |
0 |
in.close(); |
435 |
|
} |
436 |
|
} |
437 |
|
} |
438 |
|
} |
439 |
|
} |