1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.web

File ExportAction.java

 

Coverage histogram

../../../../img/srcFileCovDistChart5.png
74% of files have more coverage

Code metrics

60
171
5
1
397
282
40
0.23
34.2
5
8

Classes

Class Line # Actions
ExportAction 65 171 0% 40 130
0.4491525344.9%
 

Contributing tests

This file is covered by 1 test. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.web;
21   
22    import java.io.IOException;
23    import java.lang.reflect.Type;
24    import java.util.ArrayList;
25    import java.util.Collection;
26    import java.util.HashMap;
27    import java.util.List;
28    import java.util.Map;
29   
30    import org.apache.commons.lang3.ArrayUtils;
31    import org.apache.commons.lang3.StringUtils;
32    import org.xwiki.filter.FilterException;
33    import org.xwiki.filter.input.InputFilterStream;
34    import org.xwiki.filter.input.InputFilterStreamFactory;
35    import org.xwiki.filter.instance.input.DocumentInstanceInputProperties;
36    import org.xwiki.filter.output.BeanOutputFilterStreamFactory;
37    import org.xwiki.filter.output.DefaultOutputStreamOutputTarget;
38    import org.xwiki.filter.output.OutputFilterStream;
39    import org.xwiki.filter.output.OutputFilterStreamFactory;
40    import org.xwiki.filter.type.FilterStreamType;
41    import org.xwiki.filter.xar.output.XAROutputProperties;
42    import org.xwiki.model.reference.DocumentReferenceResolver;
43    import org.xwiki.model.reference.EntityReferenceSerializer;
44    import org.xwiki.model.reference.EntityReferenceSet;
45    import org.xwiki.model.reference.WikiReference;
46   
47    import com.xpn.xwiki.XWikiContext;
48    import com.xpn.xwiki.XWikiException;
49    import com.xpn.xwiki.doc.XWikiDocument;
50    import com.xpn.xwiki.export.html.HtmlPackager;
51    import com.xpn.xwiki.internal.export.OfficeExporter;
52    import com.xpn.xwiki.internal.export.OfficeExporterURLFactory;
53    import com.xpn.xwiki.pdf.api.PdfExport;
54    import com.xpn.xwiki.pdf.api.PdfExport.ExportType;
55    import com.xpn.xwiki.pdf.impl.PdfExportImpl;
56    import com.xpn.xwiki.pdf.impl.PdfURLFactory;
57    import com.xpn.xwiki.plugin.packaging.PackageAPI;
58    import com.xpn.xwiki.util.Util;
59   
60    /**
61    * Exports in XAR, PDF, HTML and all output formats supported by *Office (when an *Office Server is running).
62    *
63    * @version $Id: ad48e414d3b79220c3cfb31c756f9ef718548976 $
64    */
 
65    public class ExportAction extends XWikiAction
66    {
 
67  1 toggle @Override
68    public String render(XWikiContext context) throws XWikiException
69    {
70  1 String defaultPage;
71   
72  1 try {
73  1 XWikiRequest request = context.getRequest();
74  1 String format = request.get("format");
75   
76  1 if ((format == null) || (format.equals("xar"))) {
77  1 defaultPage = exportXAR(context);
78  0 } else if (format.equals("html")) {
79  0 defaultPage = exportHTML(context);
80    } else {
81  0 defaultPage = export(format, context);
82    }
83    } catch (Exception e) {
84  0 throw new XWikiException(XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_EXPORT,
85    "Exception while exporting", e);
86    }
87   
88  1 return defaultPage;
89    }
90   
91    /**
92    * Create ZIP archive containing wiki pages rendered in HTML, attached files and used skins.
93    *
94    * @param context the XWiki context.
95    * @return always return null.
96    * @throws XWikiException error when exporting HTML ZIP package.
97    * @throws IOException error when exporting HTML ZIP package.
98    * @since XWiki Platform 1.3M1
99    */
 
100  0 toggle private String exportHTML(XWikiContext context) throws XWikiException, IOException
101    {
102  0 XWikiRequest request = context.getRequest();
103   
104  0 String description = request.get("description");
105   
106  0 String name = request.get("name");
107  0 if (StringUtils.isBlank(name)) {
108  0 name = context.getDoc().getFullName();
109    }
110   
111  0 Collection<String> pageList = resolvePagesToExport(request.getParameterValues("pages"), context);
112  0 if (pageList.isEmpty()) {
113  0 return null;
114    }
115   
116  0 HtmlPackager packager = new HtmlPackager();
117   
118  0 if (name != null && name.trim().length() > 0) {
119  0 packager.setName(name);
120    }
121   
122  0 if (description != null) {
123  0 packager.setDescription(description);
124    }
125   
126  0 packager.addPages(pageList);
127   
128  0 packager.export(context);
129   
130  0 return null;
131    }
132   
 
133  1 toggle private Collection<String> resolvePagesToExport(String[] pages, XWikiContext context) throws XWikiException
134    {
135  1 List<String> pageList = new ArrayList<>();
136  1 if (pages == null || pages.length == 0) {
137  0 pageList.add(context.getDoc().getFullName());
138    } else {
139  1 Map<String, Object[]> wikiQueries = new HashMap<String, Object[]>();
140  2 for (int i = 0; i < pages.length; ++i) {
141  1 String pattern = pages[i];
142   
143  1 String wikiName;
144  1 if (pattern.contains(":")) {
145  0 int index = pattern.indexOf(':');
146  0 wikiName = pattern.substring(0, index);
147  0 pattern = pattern.substring(index + 1);
148    } else {
149  1 wikiName = context.getWikiId();
150    }
151   
152  1 StringBuffer where;
153  1 List<String> params;
154   
155  1 if (!wikiQueries.containsKey(wikiName)) {
156  1 Object[] query = new Object[2];
157  1 query[0] = where = new StringBuffer("where ");
158  1 query[1] = params = new ArrayList<String>();
159  1 wikiQueries.put(wikiName, query);
160    } else {
161  0 Object[] query = wikiQueries.get(wikiName);
162  0 where = (StringBuffer) query[0];
163  0 params = (List<String>) query[1];
164    }
165   
166  1 if (i > 0) {
167  0 where.append(" or ");
168    }
169   
170  1 where.append("doc.fullName like ?");
171  1 params.add(pattern);
172    }
173   
174  1 String database = context.getWikiId();
175  1 try {
176  1 for (Map.Entry<String, Object[]> entry : wikiQueries.entrySet()) {
177  1 String wikiName = entry.getKey();
178  1 Object[] query = entry.getValue();
179  1 String where = ((StringBuffer) query[0]).toString();
180  1 @SuppressWarnings("unchecked")
181    List<String> params = (List<String>) query[1];
182   
183  1 context.setWikiId(wikiName);
184  1 List<String> docsNames = context.getWiki().getStore().searchDocumentsNames(where, params, context);
185  1 for (String docName : docsNames) {
186  2 String pageReference = wikiName + XWikiDocument.DB_SPACE_SEP + docName;
187  2 if (context.getWiki().getRightService()
188    .hasAccessLevel("view", context.getUser(), pageReference, context)) {
189  2 pageList.add(pageReference);
190    }
191    }
192    }
193    } finally {
194  1 context.setWikiId(database);
195    }
196    }
197   
198  1 return pageList;
199    }
200   
 
201  0 toggle private String export(String format, XWikiContext context) throws XWikiException, IOException
202    {
203    // We currently use the PDF export infrastructure but we have to redesign the export code.
204  0 XWikiURLFactory urlFactory = new OfficeExporterURLFactory();
205  0 PdfExport exporter = new OfficeExporter();
206    // Check if the office exporter supports the specified format.
207  0 ExportType exportType = ((OfficeExporter) exporter).getExportType(format);
208    // Note 1: exportType will be null if no office server is started or it doesn't support the passed format
209    // Note 2: we don't use the office server for PDF exports since it doesn't work OOB. Instead we use FOP.
210  0 if ("pdf".equalsIgnoreCase(format)) {
211    // The export format is PDF or the office converter can't be used (either it doesn't support the specified
212    // format or the office server is not started).
213  0 urlFactory = new PdfURLFactory();
214  0 exporter = new PdfExportImpl();
215  0 exportType = ExportType.PDF;
216  0 } else if (exportType == null) {
217  0 context.put("message", "core.export.formatUnknown");
218  0 return "exception";
219    }
220   
221  0 urlFactory.init(context);
222  0 context.setURLFactory(urlFactory);
223  0 handleRevision(context);
224   
225  0 XWikiDocument doc = context.getDoc();
226  0 context.getResponse().setContentType(exportType.getMimeType());
227   
228    // Compute the name of the export. Since it's gong to be saved on the user's file system it needs to be a valid
229    // File name. Thus we use the "path" serializer but replace the "/" separator by "_" since we're not computing
230    // a directory hierarchy but a file name
231  0 EntityReferenceSerializer<String> serializer =
232    Utils.getComponent(EntityReferenceSerializer.TYPE_STRING, "path");
233  0 String filename = serializer.serialize(doc.getDocumentReference()).replaceAll("/", "_");
234    // Make sure we don't go over 255 chars since several filesystems don't support filename longer than that!
235  0 filename = StringUtils.abbreviateMiddle(filename, "__", 255);
236  0 context.getResponse().addHeader(
237    "Content-disposition",
238    String.format("inline; filename=%s.%s", filename, exportType.getExtension()));
239  0 exporter.export(doc, context.getResponse().getOutputStream(), exportType, context);
240   
241  0 return null;
242    }
243   
 
244  1 toggle private String exportXAR(XWikiContext context) throws XWikiException, IOException, FilterException
245    {
246  1 XWikiRequest request = context.getRequest();
247   
248  1 boolean history = Boolean.valueOf(request.get("history"));
249  1 boolean backup = Boolean.valueOf(request.get("backup"));
250  1 String author = request.get("author");
251  1 String description = request.get("description");
252  1 String licence = request.get("licence");
253  1 String version = request.get("version");
254  1 String name = request.get("name");
255  1 String[] pages = request.getParameterValues("pages");
256  1 boolean all = ArrayUtils.isEmpty(pages);
257   
258  1 if (!context.getWiki().getRightService().hasWikiAdminRights(context)) {
259  0 context.put("message", "needadminrights");
260  0 return "exception";
261    }
262   
263  1 if (StringUtils.isEmpty(name)) {
264  0 if (all) {
265  0 name = "backup";
266    } else {
267  0 name = "export";
268    }
269    }
270   
271  1 if (context.getWiki().ParamAsLong("xwiki.action.export.xar.usefilter", 1) == 1) {
272    // Create input wiki stream
273  1 DocumentInstanceInputProperties inputProperties = new DocumentInstanceInputProperties();
274   
275    // We don't want to log the details
276  1 inputProperties.setVerbose(false);
277   
278  1 inputProperties.setWithJRCSRevisions(history);
279  1 inputProperties.setWithRevisions(false);
280   
281  1 EntityReferenceSet entities = new EntityReferenceSet();
282   
283  1 if (all) {
284  0 entities.includes(new WikiReference(context.getWikiId()));
285    } else {
286    // Find all page references and add them for processing
287  1 Collection<String> pageList = resolvePagesToExport(pages, context);
288  1 DocumentReferenceResolver<String> resolver =
289    Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "current");
290  1 for (String pageName : pageList) {
291  2 entities.includes(resolver.resolve(pageName));
292    }
293    }
294   
295  1 inputProperties.setEntities(entities);
296   
297  1 InputFilterStreamFactory inputFilterStreamFactory =
298    Utils.getComponent(InputFilterStreamFactory.class, FilterStreamType.XWIKI_INSTANCE.serialize());
299   
300  1 InputFilterStream inputFilterStream = inputFilterStreamFactory.createInputFilterStream(inputProperties);
301   
302    // Create output wiki stream
303  1 XAROutputProperties xarProperties = new XAROutputProperties();
304   
305    // We don't want to log the details
306  1 xarProperties.setVerbose(false);
307   
308  1 XWikiResponse response = context.getResponse();
309   
310  1 xarProperties.setTarget(new DefaultOutputStreamOutputTarget(response.getOutputStream()));
311  1 xarProperties.setPackageName(name);
312  1 if (description != null) {
313  0 xarProperties.setPackageDescription(description);
314    }
315  1 if (licence != null) {
316  0 xarProperties.setPackageLicense(licence);
317    }
318  1 if (author != null) {
319  0 xarProperties.setPackageAuthor(author);
320    }
321  1 if (version != null) {
322  0 xarProperties.setPackageVersion(version);
323    }
324  1 xarProperties.setPackageBackupPack(backup);
325  1 xarProperties.setPreserveVersion(backup || history);
326   
327  1 BeanOutputFilterStreamFactory<XAROutputProperties> xarFilterStreamFactory =
328    Utils.getComponent((Type) OutputFilterStreamFactory.class,
329    FilterStreamType.XWIKI_XAR_CURRENT.serialize());
330   
331  1 OutputFilterStream outputFilterStream = xarFilterStreamFactory.createOutputFilterStream(xarProperties);
332   
333    // Export
334  1 response.setContentType("application/zip");
335  1 response.addHeader("Content-disposition", "attachment; filename=" + Util.encodeURI(name, context) + ".xar");
336   
337  1 inputFilterStream.read(outputFilterStream.getFilter());
338   
339  1 inputFilterStream.close();
340  1 outputFilterStream.close();
341   
342    // Flush
343  1 response.getOutputStream().flush();
344   
345    // Indicate that we are done with the response so no need to add anything
346  1 context.setFinished(true);
347    } else {
348  0 PackageAPI export = ((PackageAPI) context.getWiki().getPluginApi("package", context));
349  0 if (export == null) {
350    // No Packaging plugin configured
351  0 return "exception";
352    }
353   
354  0 export.setWithVersions(history);
355   
356  0 if (author != null) {
357  0 export.setAuthorName(author);
358    }
359   
360  0 if (description != null) {
361  0 export.setDescription(description);
362    }
363   
364  0 if (licence != null) {
365  0 export.setLicence(licence);
366    }
367   
368  0 if (version != null) {
369  0 export.setVersion(version);
370    }
371   
372  0 export.setBackupPack(backup);
373   
374  0 export.setName(name);
375   
376  0 if (all) {
377  0 export.backupWiki();
378    } else {
379  0 if (pages != null) {
380  0 for (String pageName : pages) {
381  0 String defaultAction = request.get("action_" + pageName);
382  0 int iAction;
383  0 try {
384  0 iAction = Integer.parseInt(defaultAction);
385    } catch (Exception e) {
386  0 iAction = 0;
387    }
388  0 export.add(pageName, iAction);
389    }
390    }
391  0 export.export();
392    }
393    }
394   
395  1 return null;
396    }
397    }