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

File Package.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart6.png
69% of files have more coverage

Code metrics

154
514
80
1
1,499
1,004
191
0.37
6.43
80
2.39

Classes

Class Line # Actions
Package 82 514 0% 191 345
0.538770153.9%
 

Contributing tests

This file is covered by 9 tests. .

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   
21    package com.xpn.xwiki.plugin.packaging;
22   
23    import java.io.ByteArrayInputStream;
24    import java.io.ByteArrayOutputStream;
25    import java.io.File;
26    import java.io.FileInputStream;
27    import java.io.FileOutputStream;
28    import java.io.IOException;
29    import java.io.InputStream;
30    import java.io.OutputStream;
31    import java.util.ArrayList;
32    import java.util.Date;
33    import java.util.HashMap;
34    import java.util.LinkedList;
35    import java.util.List;
36    import java.util.Map;
37    import java.util.zip.ZipEntry;
38    import java.util.zip.ZipOutputStream;
39   
40    import org.apache.commons.compress.archivers.ArchiveEntry;
41    import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
42    import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
43    import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
44    import org.apache.commons.io.input.CloseShieldInputStream;
45    import org.apache.commons.lang3.StringUtils;
46    import org.apache.commons.lang3.exception.ExceptionUtils;
47    import org.dom4j.Document;
48    import org.dom4j.DocumentException;
49    import org.dom4j.Element;
50    import org.dom4j.dom.DOMDocument;
51    import org.dom4j.dom.DOMElement;
52    import org.dom4j.io.OutputFormat;
53    import org.dom4j.io.SAXReader;
54    import org.slf4j.Logger;
55    import org.slf4j.LoggerFactory;
56    import org.xwiki.extension.Extension;
57    import org.xwiki.extension.ExtensionId;
58    import org.xwiki.extension.InstalledExtension;
59    import org.xwiki.extension.LocalExtension;
60    import org.xwiki.extension.ResolveException;
61    import org.xwiki.extension.event.ExtensionInstalledEvent;
62    import org.xwiki.extension.repository.ExtensionRepositoryManager;
63    import org.xwiki.extension.repository.InstalledExtensionRepository;
64    import org.xwiki.extension.repository.LocalExtensionRepository;
65    import org.xwiki.model.reference.SpaceReference;
66    import org.xwiki.observation.ObservationManager;
67    import org.xwiki.query.QueryException;
68   
69    import com.xpn.xwiki.XWiki;
70    import com.xpn.xwiki.XWikiContext;
71    import com.xpn.xwiki.XWikiException;
72    import com.xpn.xwiki.doc.XWikiAttachment;
73    import com.xpn.xwiki.doc.XWikiDocument;
74    import com.xpn.xwiki.internal.event.XARImportedEvent;
75    import com.xpn.xwiki.internal.event.XARImportingEvent;
76    import com.xpn.xwiki.internal.xml.XMLWriter;
77    import com.xpn.xwiki.objects.classes.BaseClass;
78    import com.xpn.xwiki.web.Utils;
79   
80    import net.sf.json.JSONObject;
81   
 
82    public class Package
83    {
84    public static final int OK = 0;
85   
86    public static final int Right = 1;
87   
88    public static final String DEFAULT_FILEEXT = "xml";
89   
90    public static final String XAR_FILENAME_ENCODING = "UTF-8";
91   
92    public static final String DefaultPackageFileName = "package.xml";
93   
94    public static final String DefaultPluginName = "package";
95   
96    private static final Logger LOGGER = LoggerFactory.getLogger(Package.class);
97   
98    private String name = "My package";
99   
100    private String description = "";
101   
102    /**
103    * @see #isInstallExension()
104    */
105    private boolean installExtension = true;
106   
107    private String extensionId;
108   
109    private String version = "1.0.0";
110   
111    private String licence = "LGPL";
112   
113    private String authorName = "XWiki";
114   
115    private List<DocumentInfo> files = null;
116   
117    private List<DocumentInfo> customMappingFiles = null;
118   
119    private List<DocumentInfo> classFiles = null;
120   
121    private boolean backupPack = false;
122   
123    private boolean preserveVersion = false;
124   
125    private boolean withVersions = true;
126   
127    private List<DocumentFilter> documentFilters = new ArrayList<DocumentFilter>();
128   
 
129  0 toggle public String getName()
130    {
131  0 return this.name;
132    }
133   
 
134  0 toggle public void setName(String name)
135    {
136  0 this.name = name;
137    }
138   
 
139  0 toggle public String getDescription()
140    {
141  0 return this.description;
142    }
143   
 
144  0 toggle public void setDescription(String description)
145    {
146  0 this.description = description;
147    }
148   
 
149  0 toggle public String getId()
150    {
151  0 return this.extensionId;
152    }
153   
 
154  0 toggle public void setId(String id)
155    {
156  0 this.extensionId = id;
157    }
158   
159    /**
160    * @return <code>true</code> if the extension packaged in the XAR should be registered as such automatically,
161    * <code>false</code> otherwise.
162    * @deprecated since 6.4.5, 7.0.1, 7.1M1, use {@link #isInstallExtension()} instead
163    */
 
164  0 toggle @Deprecated
165    public boolean isInstallExension()
166    {
167  0 return isInstallExtension();
168    }
169   
170    /**
171    * @return <code>true</code> if the extension packaged in the XAR should be registered as such automatically,
172    * <code>false</code> otherwise.
173    * @since 6.4.5
174    * @since 7.0.1
175    * @since 7.1M1
176    */
 
177  170 toggle public boolean isInstallExtension()
178    {
179  170 return this.installExtension;
180    }
181   
182    /**
183    * @param installExension <code>true</code> if the extension packaged in the XAR should be registered as such
184    * automatically, <code>false</code> otherwise.
185    * @deprecated since 6.4.5, 7.0.1, 7.1M1, use {@link #setInstallExension(boolean)} instead
186    */
 
187  0 toggle @Deprecated
188    public void setInstallExension(boolean installExension)
189    {
190  0 this.installExtension = installExension;
191    }
192   
193    /**
194    * @param installExtension <code>true</code> if the extension packaged in the XAR should be registered as such
195    * automatically, <code>false</code> otherwise.
196    * @since 6.4.5
197    * @since 7.0.1
198    * @since 7.1M1
199    */
 
200  0 toggle public void setInstallExtension(boolean installExtension)
201    {
202  0 this.installExtension = installExtension;
203    }
204   
 
205  331 toggle public String getExtensionId()
206    {
207  331 return this.extensionId;
208    }
209   
 
210  0 toggle public void setExtensionId(String extensionId)
211    {
212  0 this.extensionId = extensionId;
213    }
214   
 
215  322 toggle public String getVersion()
216    {
217  322 return this.version;
218    }
219   
 
220  0 toggle public void setVersion(String version)
221    {
222  0 this.version = version;
223    }
224   
 
225  0 toggle public String getLicence()
226    {
227  0 return this.licence;
228    }
229   
 
230  0 toggle public void setLicence(String licence)
231    {
232  0 this.licence = licence;
233    }
234   
 
235  0 toggle public String getAuthorName()
236    {
237  0 return this.authorName;
238    }
239   
 
240  0 toggle public void setAuthorName(String authorName)
241    {
242  0 this.authorName = authorName;
243    }
244   
245    /**
246    * If true, the package will preserve the original author during import, rather than updating the author to the
247    * current (importing) user.
248    *
249    * @see #isWithVersions()
250    * @see #isVersionPreserved()
251    */
 
252  0 toggle public boolean isBackupPack()
253    {
254  0 return this.backupPack;
255    }
256   
 
257  32 toggle public void setBackupPack(boolean backupPack)
258    {
259  32 this.backupPack = backupPack;
260    }
261   
 
262  88 toggle public boolean hasBackupPackImportRights(XWikiContext context)
263    {
264  88 return isFarmAdmin(context);
265    }
266   
267    /**
268    * If true, the package will preserve the current document version during import, regardless of whether or not the
269    * document history is included.
270    *
271    * @see #isWithVersions()
272    * @see #isBackupPack()
273    */
 
274  0 toggle public boolean isVersionPreserved()
275    {
276  0 return this.preserveVersion;
277    }
278   
 
279  1 toggle public void setPreserveVersion(boolean preserveVersion)
280    {
281  1 this.preserveVersion = preserveVersion;
282    }
283   
 
284  330 toggle public List<DocumentInfo> getFiles()
285    {
286  330 return this.files;
287    }
288   
 
289  0 toggle public List<DocumentInfo> getCustomMappingFiles()
290    {
291  0 return this.customMappingFiles;
292    }
293   
 
294  0 toggle public boolean isWithVersions()
295    {
296  0 return this.withVersions;
297    }
298   
299    /**
300    * If set to true, history revisions in the archive will be imported when importing documents.
301    */
 
302  162 toggle public void setWithVersions(boolean withVersions)
303    {
304  162 this.withVersions = withVersions;
305    }
306   
 
307  0 toggle public void addDocumentFilter(Object filter) throws PackageException
308    {
309  0 if (filter instanceof DocumentFilter) {
310  0 this.documentFilters.add((DocumentFilter) filter);
311    } else {
312  0 throw new PackageException(PackageException.ERROR_PACKAGE_INVALID_FILTER, "Invalid Document Filter");
313    }
314    }
315   
 
316  407 toggle public Package()
317    {
318  407 this.files = new ArrayList<DocumentInfo>();
319  407 this.customMappingFiles = new ArrayList<DocumentInfo>();
320  407 this.classFiles = new ArrayList<DocumentInfo>();
321    }
322   
 
323  2007 toggle public boolean add(XWikiDocument doc, int defaultAction, XWikiContext context) throws XWikiException
324    {
325  2007 if (!context.getWiki().checkAccess("edit", doc, context)) {
326  0 return false;
327    }
328   
329  32466 for (int i = 0; i < this.files.size(); i++) {
330  30459 DocumentInfo di = this.files.get(i);
331  30459 if (di.getFullName().equals(doc.getFullName()) && (di.getLanguage().equals(doc.getLanguage()))) {
332  0 if (defaultAction != DocumentInfo.ACTION_NOT_DEFINED) {
333  0 di.setAction(defaultAction);
334    }
335  0 if (!doc.isNew()) {
336  0 di.setDoc(doc);
337    }
338   
339  0 return true;
340    }
341    }
342   
343  2007 doc = doc.clone();
344   
345  2007 try {
346  2007 filter(doc, context);
347   
348  2007 DocumentInfo docinfo = new DocumentInfo(doc);
349  2007 docinfo.setAction(defaultAction);
350  2007 this.files.add(docinfo);
351  2007 BaseClass bclass = doc.getXClass();
352  2007 if (bclass.getFieldList().size() > 0) {
353  188 this.classFiles.add(docinfo);
354    }
355  2007 if (bclass.getCustomMapping() != null) {
356  2007 this.customMappingFiles.add(docinfo);
357    }
358  2007 return true;
359    } catch (ExcludeDocumentException e) {
360  0 LOGGER.info("Skip the document " + doc.getDocumentReference());
361   
362  0 return false;
363    }
364    }
365   
 
366  1982 toggle public boolean add(XWikiDocument doc, XWikiContext context) throws XWikiException
367    {
368  1982 return add(doc, DocumentInfo.ACTION_NOT_DEFINED, context);
369    }
370   
 
371  0 toggle public boolean updateDoc(String docFullName, int action, XWikiContext context) throws XWikiException
372    {
373  0 XWikiDocument doc = new XWikiDocument();
374  0 doc.setFullName(docFullName, context);
375  0 return add(doc, action, context);
376    }
377   
 
378  25 toggle public boolean add(String docFullName, int DefaultAction, XWikiContext context) throws XWikiException
379    {
380  25 XWikiDocument doc = context.getWiki().getDocument(docFullName, context);
381  25 add(doc, DefaultAction, context);
382  25 List<String> languages = doc.getTranslationList(context);
383  25 for (String language : languages) {
384  0 if (!((language == null) || (language.equals("")) || (language.equals(doc.getDefaultLanguage())))) {
385  0 add(doc.getTranslatedDocument(language, context), DefaultAction, context);
386    }
387    }
388   
389  25 return true;
390    }
391   
 
392  0 toggle public boolean add(String docFullName, String language, int DefaultAction, XWikiContext context)
393    throws XWikiException
394    {
395  0 XWikiDocument doc = context.getWiki().getDocument(docFullName, context);
396  0 if ((language == null) || (language.equals(""))) {
397  0 add(doc, DefaultAction, context);
398    } else {
399  0 add(doc.getTranslatedDocument(language, context), DefaultAction, context);
400    }
401   
402  0 return true;
403    }
404   
 
405  0 toggle public boolean add(String docFullName, XWikiContext context) throws XWikiException
406    {
407  0 return add(docFullName, DocumentInfo.ACTION_NOT_DEFINED, context);
408    }
409   
 
410  0 toggle public boolean add(String docFullName, String language, XWikiContext context) throws XWikiException
411    {
412  0 return add(docFullName, language, DocumentInfo.ACTION_NOT_DEFINED, context);
413    }
414   
 
415  4014 toggle public void filter(XWikiDocument doc, XWikiContext context) throws ExcludeDocumentException
416    {
417  4014 for (DocumentFilter docFilter : this.documentFilters) {
418  0 docFilter.filter(doc, context);
419    }
420    }
421   
 
422  0 toggle public String export(OutputStream os, XWikiContext context) throws IOException, XWikiException
423    {
424  0 if (this.files.size() == 0) {
425  0 return "No Selected file";
426    }
427   
428  0 ZipArchiveOutputStream zos = new ZipArchiveOutputStream(os);
429  0 zos.setEncoding(XAR_FILENAME_ENCODING);
430    // By including the unicode extra fields, it is possible to extract XAR-files
431    // containing documents with non-ascii characters in the document name using InfoZIP,
432    // and the filenames will be correctly converted to the character set of the local
433    // file system.
434  0 zos.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.ALWAYS);
435  0 for (int i = 0; i < this.files.size(); i++) {
436  0 DocumentInfo docinfo = this.files.get(i);
437  0 XWikiDocument doc = docinfo.getDoc();
438  0 addToZip(doc, zos, this.withVersions, context);
439    }
440  0 addInfosToZip(zos, context);
441  0 zos.finish();
442  0 zos.flush();
443   
444  0 return "";
445    }
446   
 
447  1 toggle public String exportToDir(File dir, XWikiContext context) throws IOException, XWikiException
448    {
449  1 if (!dir.exists()) {
450  0 if (!dir.mkdirs()) {
451  0 Object[] args = new Object[1];
452  0 args[0] = dir.toString();
453  0 throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_MKDIR,
454    "Error creating directory {0}", null, args);
455    }
456    }
457   
458  26 for (int i = 0; i < this.files.size(); i++) {
459  25 DocumentInfo docinfo = this.files.get(i);
460  25 XWikiDocument doc = docinfo.getDoc();
461  25 addToDir(doc, dir, this.withVersions, context);
462    }
463  1 addInfosToDir(dir, context);
464   
465  1 return "";
466    }
467   
468    /**
469    * Load this package in memory from a byte array. It may be installed later using {@link #install(XWikiContext)}.
470    * Your should prefer {@link #Import(InputStream, XWikiContext)} which may avoid loading the package twice in
471    * memory.
472    *
473    * @param file a byte array containing the content of a zipped package file
474    * @param context current XWikiContext
475    * @return an empty string, useless.
476    * @throws IOException while reading the ZipFile
477    * @throws XWikiException when package content is broken
478    */
 
479  11 toggle public String Import(byte file[], XWikiContext context) throws IOException, XWikiException
480    {
481  11 return Import(new ByteArrayInputStream(file), context);
482    }
483   
484    /**
485    * Load this package in memory from an InputStream. It may be installed later using {@link #install(XWikiContext)}.
486    *
487    * @param file an InputStream of a zipped package file
488    * @param context current XWikiContext
489    * @return an empty string, useless.
490    * @throws IOException while reading the ZipFile
491    * @throws XWikiException when package content is broken
492    * @since 2.3M2
493    */
 
494  172 toggle public String Import(InputStream file, XWikiContext context) throws IOException, XWikiException
495    {
496  172 ZipArchiveInputStream zis;
497  172 ArchiveEntry entry;
498  172 Document description = null;
499   
500  172 try {
501  172 zis = new ZipArchiveInputStream(file, XAR_FILENAME_ENCODING, false);
502   
503  172 List<XWikiDocument> docsToLoad = new LinkedList<XWikiDocument>();
504    /*
505    * Loop 1: Cycle through the zip input stream and load out all of the documents, when we find the
506    * package.xml file we put it aside to so that we only include documents which are in the file.
507    */
508  ? while ((entry = zis.getNextEntry()) != null) {
509  2154 if (entry.isDirectory() || (entry.getName().indexOf("META-INF") != -1)) {
510    // The entry is either a directory or is something inside of the META-INF dir.
511    // (we use that directory to put meta data such as LICENSE/NOTICE files.)
512  0 continue;
513  2154 } else if (entry.getName().compareTo(DefaultPackageFileName) == 0) {
514    // The entry is the manifest (package.xml). Read this differently.
515  172 description = fromXml(new CloseShieldInputStream(zis));
516    } else {
517  1982 XWikiDocument doc = null;
518  1982 try {
519  1982 doc = readFromXML(new CloseShieldInputStream(zis));
520    } catch (Throwable e) {
521  0 LOGGER.warn(
522    "Failed to parse document [{}] from XML during import, thus it will not be installed. "
523    + "The error was: " + ExceptionUtils.getRootCauseMessage(e));
524    // It will be listed in the "failed documents" section after the import.
525  0 addToErrors(entry.getName().replaceAll("/", "."), context);
526   
527  0 continue;
528    }
529   
530    // Run all of the registered DocumentFilters on this document and
531    // if no filters throw exceptions, add it to the list to import.
532  1982 try {
533  1982 this.filter(doc, context);
534  1982 docsToLoad.add(doc);
535    } catch (ExcludeDocumentException e) {
536  0 LOGGER.info("Skip the document '" + doc.getDocumentReference() + "'");
537    }
538    }
539    }
540    // Make sure a manifest was included in the package...
541  172 if (description == null) {
542  0 throw new PackageException(XWikiException.ERROR_XWIKI_UNKNOWN, "Could not find the package definition");
543    }
544    /*
545    * Loop 2: Cycle through the list of documents and if they are in the manifest then add them, otherwise log
546    * a warning and add them to the skipped list.
547    */
548  172 for (XWikiDocument doc : docsToLoad) {
549  1982 if (documentExistInPackageFile(doc.getFullName(), doc.getLanguage(), description)) {
550  1982 this.add(doc, context);
551    } else {
552  0 LOGGER.warn("document " + doc.getDocumentReference() + " does not exist in package definition."
553    + " It will not be installed.");
554    // It will be listed in the "skipped documents" section after the
555    // import.
556  0 addToSkipped(doc.getFullName(), context);
557    }
558    }
559   
560  172 updateFileInfos(description);
561    } catch (DocumentException e) {
562  0 throw new PackageException(XWikiException.ERROR_XWIKI_UNKNOWN, "Error when reading the XML");
563    }
564   
565  172 return "";
566    }
567   
 
568  1982 toggle private boolean documentExistInPackageFile(String docName, String language, Document xml)
569    {
570  1982 Element docFiles = xml.getRootElement();
571  1982 Element infosFiles = docFiles.element("files");
572   
573  1982 @SuppressWarnings("unchecked")
574    List<Element> fileList = infosFiles.elements("file");
575   
576  1982 for (Element el : fileList) {
577  32141 String tmpDocName = el.getStringValue();
578  32141 if (tmpDocName.compareTo(docName) != 0) {
579  28047 continue;
580    }
581  4094 String tmpLanguage = el.attributeValue("language");
582  4094 if (tmpLanguage == null) {
583  0 tmpLanguage = "";
584    }
585  4094 if (tmpLanguage.compareTo(language) == 0) {
586  1982 return true;
587    }
588    }
589   
590  0 return false;
591    }
592   
 
593  172 toggle private void updateFileInfos(Document xml)
594    {
595  172 Element docFiles = xml.getRootElement();
596  172 Element infosFiles = docFiles.element("files");
597   
598  172 @SuppressWarnings("unchecked")
599    List<Element> fileList = infosFiles.elements("file");
600  172 for (Element el : fileList) {
601  1982 String defaultAction = el.attributeValue("defaultAction");
602  1982 String language = el.attributeValue("language");
603  1982 if (language == null) {
604  0 language = "";
605    }
606  1982 String docName = el.getStringValue();
607  1982 setDocumentDefaultAction(docName, language, Integer.parseInt(defaultAction));
608    }
609    }
610   
 
611  1982 toggle private void setDocumentDefaultAction(String docName, String language, int defaultAction)
612    {
613  1982 if (this.files == null) {
614  0 return;
615    }
616   
617  1982 for (DocumentInfo docInfo : this.files) {
618  32141 if (docInfo.getFullName().equals(docName) && docInfo.getLanguage().equals(language)) {
619  1982 docInfo.setAction(defaultAction);
620  1982 return;
621    }
622    }
623    }
624   
 
625  170 toggle public int testInstall(boolean isAdmin, XWikiContext context)
626    {
627  170 if (LOGGER.isDebugEnabled()) {
628  0 LOGGER.debug("Package test install");
629    }
630   
631  170 int result = DocumentInfo.INSTALL_IMPOSSIBLE;
632  170 try {
633  170 if (this.files.size() == 0) {
634  0 return result;
635    }
636   
637  170 result = this.files.get(0).testInstall(isAdmin, context);
638  170 for (DocumentInfo docInfo : this.files) {
639  1978 int res = docInfo.testInstall(isAdmin, context);
640  1978 if (res < result) {
641  0 result = res;
642    }
643    }
644   
645  170 return result;
646    } finally {
647  170 if (LOGGER.isDebugEnabled()) {
648  0 LOGGER.debug("Package test install result " + result);
649    }
650    }
651    }
652   
 
653  170 toggle public int install(XWikiContext context) throws XWikiException
654    {
655  170 boolean isAdmin = context.getWiki().getRightService().hasWikiAdminRights(context);
656   
657  170 if (testInstall(isAdmin, context) == DocumentInfo.INSTALL_IMPOSSIBLE) {
658  0 setStatus(DocumentInfo.INSTALL_IMPOSSIBLE, context);
659  0 return DocumentInfo.INSTALL_IMPOSSIBLE;
660    }
661   
662  170 boolean hasCustomMappings = false;
663  170 for (DocumentInfo docinfo : this.customMappingFiles) {
664  1978 BaseClass bclass = docinfo.getDoc().getXClass();
665  1978 hasCustomMappings |= context.getWiki().getStore().injectCustomMapping(bclass, context);
666    }
667   
668  170 if (hasCustomMappings) {
669  0 context.getWiki().getStore().injectUpdatedCustomMappings(context);
670    }
671   
672  170 int status = DocumentInfo.INSTALL_OK;
673   
674    // Determine if the user performing the installation is a farm admin.
675    // We allow author preservation from the package only to farm admins.
676    // In order to prevent sub-wiki admins to take control of a farm with forged packages.
677    // We test it once for the whole import in case one of the document break user during the import process.
678  170 boolean backup = this.backupPack && isFarmAdmin(context);
679   
680    // Notify all the listeners about import
681  170 ObservationManager om = Utils.getComponent(ObservationManager.class);
682   
683    // FIXME: should be able to pass some sort of source here, the name of the attachment or the list of
684    // imported documents. But for the moment it's fine
685  170 om.notify(new XARImportingEvent(), null, context);
686   
687  170 try {
688    // Start by installing all documents having a class definition so that their
689    // definitions are available when installing documents using them.
690  170 for (DocumentInfo classFile : this.classFiles) {
691  165 if (installDocument(classFile, isAdmin, backup, context) == DocumentInfo.INSTALL_ERROR) {
692  0 status = DocumentInfo.INSTALL_ERROR;
693    }
694    }
695   
696    // Install the remaining documents (without class definitions).
697  170 for (DocumentInfo docInfo : this.files) {
698  1978 if (!this.classFiles.contains(docInfo)) {
699  1813 if (installDocument(docInfo, isAdmin, backup, context) == DocumentInfo.INSTALL_ERROR) {
700  0 status = DocumentInfo.INSTALL_ERROR;
701    }
702    }
703    }
704  170 setStatus(status, context);
705   
706    } finally {
707    // FIXME: should be able to pass some sort of source here, the name of the attachment or the list of
708    // imported documents. But for the moment it's fine
709  170 om.notify(new XARImportedEvent(), null, context);
710   
711  170 registerExtension(context);
712    }
713   
714  170 return status;
715    }
716   
 
717  170 toggle private void registerExtension(XWikiContext context)
718    {
719    // Register the package as extension if it's one
720  170 if (isInstallExtension() && StringUtils.isNotEmpty(getExtensionId()) && StringUtils.isNotEmpty(getVersion())) {
721  161 ExtensionId extensionId = new ExtensionId(getExtensionId(), getVersion());
722   
723  161 try {
724  161 LocalExtensionRepository localRepository = Utils.getComponent(LocalExtensionRepository.class);
725   
726  161 LocalExtension localExtension = localRepository.getLocalExtension(extensionId);
727  161 if (localExtension == null) {
728  160 Extension extension;
729  160 try {
730    // Try to find and download the extension from a repository
731  160 extension = Utils.getComponent(ExtensionRepositoryManager.class).resolve(extensionId);
732    } catch (ResolveException e) {
733  160 LOGGER.debug("Can't find extension [{}]", extensionId, e);
734   
735    // FIXME: Create a dummy extension. Need support for partial/lazy extension.
736  160 return;
737    }
738   
739  0 localExtension = localRepository.storeExtension(extension);
740    }
741   
742  1 InstalledExtensionRepository installedRepository =
743    Utils.getComponent(InstalledExtensionRepository.class);
744   
745  1 String namespace = "wiki:" + context.getWikiId();
746   
747    // Make sure it's not already there
748  1 if (installedRepository.getInstalledExtension(localExtension.getId().getId(), namespace) == null) {
749  1 for (ExtensionId feature : localExtension.getExtensionFeatures()) {
750  0 if (installedRepository.getInstalledExtension(feature.getId(), namespace) != null) {
751    // Already exist so don't register it or it could create a mess
752  0 return;
753    }
754    }
755    } else {
756  0 return;
757    }
758   
759    // Register the extension as installed
760  1 InstalledExtension installedExtension =
761    installedRepository.installExtension(localExtension, namespace, false);
762   
763    // Tell the world about it
764  1 Utils.getComponent(ObservationManager.class)
765    .notify(new ExtensionInstalledEvent(installedExtension.getId(), namespace), installedExtension);
766    } catch (Exception e) {
767  0 LOGGER.error("Failed to register extenion [{}] from the XAR", extensionId, e);
768    }
769    }
770    }
771   
772    /**
773    * Indicate of the user has amin rights on the farm, i.e. that he has admin rights on the main wiki.
774    *
775    * @param context the XWiki context
776    * @return true if the current user is farm admin
777    */
 
778  97 toggle private boolean isFarmAdmin(XWikiContext context)
779    {
780  97 String wiki = context.getWikiId();
781   
782  97 try {
783  97 context.setWikiId(context.getMainXWiki());
784   
785  97 return context.getWiki().getRightService().hasWikiAdminRights(context);
786    } finally {
787  97 context.setWikiId(wiki);
788    }
789    }
790   
 
791  1978 toggle private int installDocument(DocumentInfo doc, boolean isAdmin, boolean backup, XWikiContext context)
792    throws XWikiException
793    {
794  1978 if (this.preserveVersion && this.withVersions) {
795    // Right now importing an archive and the history revisions it contains
796    // without overriding the existing document is not supported.
797    // We fallback on adding a new version to the existing history without importing the
798    // archive's revisions.
799  0 this.withVersions = false;
800    }
801   
802  1978 int result = DocumentInfo.INSTALL_OK;
803   
804  1978 if (LOGGER.isDebugEnabled()) {
805  0 LOGGER.debug("Package installing document " + doc.getFullName() + " " + doc.getLanguage());
806    }
807   
808  1978 if (doc.getAction() == DocumentInfo.ACTION_SKIP) {
809  0 addToSkipped(doc.getFullName() + ":" + doc.getLanguage(), context);
810  0 return DocumentInfo.INSTALL_OK;
811    }
812   
813  1978 int status = doc.testInstall(isAdmin, context);
814  1978 if (status == DocumentInfo.INSTALL_IMPOSSIBLE) {
815  0 addToErrors(doc.getFullName() + ":" + doc.getLanguage(), context);
816  0 return DocumentInfo.INSTALL_IMPOSSIBLE;
817    }
818  1978 if (status == DocumentInfo.INSTALL_OK
819    || status == DocumentInfo.INSTALL_ALREADY_EXIST && doc.getAction() == DocumentInfo.ACTION_OVERWRITE) {
820  1978 XWikiDocument previousdoc = null;
821  1978 if (status == DocumentInfo.INSTALL_ALREADY_EXIST) {
822  3 previousdoc = context.getWiki().getDocument(doc.getFullName(), context);
823    // if this document is a translation: we should only delete the translation
824  3 if (doc.getDoc().getTranslation() != 0) {
825  1 previousdoc = previousdoc.getTranslatedDocument(doc.getLanguage(), context);
826    }
827    // we should only delete the previous document
828    // if we are overridding the versions and/or if this is a backup pack
829  3 if (!this.preserveVersion || this.withVersions) {
830  3 try {
831    // This is not a real document delete, it's a upgrade. To be sure to not
832    // generate DELETE notification we directly use {@link XWikiStoreInterface}
833  3 context.getWiki().getStore().deleteXWikiDoc(previousdoc, context);
834    } catch (Exception e) {
835    // let's log the error but not stop
836  0 result = DocumentInfo.INSTALL_ERROR;
837  0 addToErrors(doc.getFullName() + ":" + doc.getLanguage(), context);
838  0 if (LOGGER.isErrorEnabled()) {
839  0 LOGGER.error("Failed to delete document " + previousdoc.getDocumentReference());
840    }
841  0 if (LOGGER.isDebugEnabled()) {
842  0 LOGGER.debug("Failed to delete document " + previousdoc.getDocumentReference(), e);
843    }
844    }
845  0 } else if (previousdoc.hasElement(XWikiDocument.HAS_ATTACHMENTS)) {
846    // We conserve the old attachments in the new documents
847  0 List<XWikiAttachment> newDocAttachments = doc.getDoc().getAttachmentList();
848  0 for (XWikiAttachment att : previousdoc.getAttachmentList()) {
849  0 if (doc.getDoc().getAttachment(att.getFilename()) == null) {
850    // We add the attachment to new document
851  0 newDocAttachments.add(att);
852    // But then we add it in the "to remove list" of the document
853    // So the attachment will be removed from the database when XWiki#saveDocument
854    // will be called
855  0 doc.getDoc().removeAttachment(att);
856    }
857    }
858    }
859  3 doc.getDoc().addXObjectsToRemoveFromVersion(previousdoc);
860  3 doc.getDoc().setOriginalDocument(previousdoc);
861    }
862  1978 try {
863  1978 if (!backup) {
864  1967 doc.getDoc().setAuthorReference(context.getUserReference());
865  1967 doc.getDoc().setContentAuthorReference(context.getUserReference());
866    // if the import is not a backup pack we set the date to now
867  1967 Date date = new Date();
868  1967 doc.getDoc().setDate(date);
869  1967 doc.getDoc().setContentUpdateDate(date);
870    }
871   
872  1978 if (!this.withVersions) {
873  1967 doc.getDoc().setVersion("1.1");
874    }
875   
876    // Does the document to be imported already exists in the wiki ?
877  1978 boolean isNewDocument = previousdoc == null;
878   
879    // Conserve existing history only if asked for it and if this history exists
880  1978 boolean conserveExistingHistory = this.preserveVersion && !isNewDocument;
881   
882    // Does the document from the package contains history revisions ?
883  1978 boolean packageHasHistory = this.documentContainsHistory(doc);
884   
885    // Reset to initial (1.1) version when we don't want to conserve existing history and either we don't
886    // want the package history or this latter one is empty
887  1978 boolean shouldResetToInitialVersion =
888    !conserveExistingHistory && (!this.withVersions || !packageHasHistory);
889   
890  1978 if (conserveExistingHistory) {
891    // Insert the archive from the existing document
892  0 doc.getDoc().setDocumentArchive(previousdoc.getDocumentArchive(context));
893    }
894   
895    else {
896    // Reset or replace history
897    // if there was not history in the source package then we should reset the version number to 1.1
898  1978 if (shouldResetToInitialVersion) {
899    // Make sure the save will not increment the version to 2.1
900  1978 doc.getDoc().setContentDirty(false);
901  1978 doc.getDoc().setMetaDataDirty(false);
902    }
903    }
904   
905  1978 String saveMessage = context.getMessageTool().get("core.importer.saveDocumentComment");
906  1978 context.getWiki().saveDocument(doc.getDoc(), saveMessage, context);
907  1978 addToInstalled(doc.getFullName() + ":" + doc.getLanguage(), context);
908   
909  1978 if ((this.withVersions && packageHasHistory) || conserveExistingHistory) {
910    // we need to force the saving the document archive.
911  0 if (doc.getDoc().getDocumentArchive() != null) {
912  0 context.getWiki().getVersioningStore()
913    .saveXWikiDocArchive(doc.getDoc().getDocumentArchive(context), true, context);
914    }
915    }
916   
917  1978 if (shouldResetToInitialVersion) {
918    // If we override and do not import version, (meaning reset document to 1.1)
919    // We need manually reset possible existing revision for the document
920    // This means making the history empty (it does not affect the version number)
921  1978 doc.getDoc().resetArchive(context);
922    }
923   
924    } catch (XWikiException e) {
925  0 addToErrors(doc.getFullName() + ":" + doc.getLanguage(), context);
926  0 if (LOGGER.isErrorEnabled()) {
927  0 LOGGER.error("Failed to save document " + doc.getFullName(), e);
928    }
929  0 result = DocumentInfo.INSTALL_ERROR;
930    }
931    }
932  1978 return result;
933    }
934   
935    /**
936    * @return true if the passed document contains a (not-empty) history of previous versions, false otherwise
937    */
 
938  1978 toggle private boolean documentContainsHistory(DocumentInfo doc)
939    {
940  1978 if ((doc.getDoc().getDocumentArchive() == null) || (doc.getDoc().getDocumentArchive().getNodes() == null)
941    || (doc.getDoc().getDocumentArchive().getNodes().size() == 0)) {
942  1978 return false;
943    }
944  0 return true;
945    }
946   
 
947  2010 toggle private List<String> getStringList(String name, XWikiContext context)
948    {
949  2010 @SuppressWarnings("unchecked")
950    List<String> list = (List<String>) context.get(name);
951   
952  2010 if (list == null) {
953  46 list = new ArrayList<String>();
954  46 context.put(name, list);
955    }
956   
957  2010 return list;
958    }
959   
 
960  0 toggle private void addToErrors(String fullName, XWikiContext context)
961    {
962  0 if (fullName.endsWith(":")) {
963  0 fullName = fullName.substring(0, fullName.length() - 1);
964    }
965   
966  0 getErrors(context).add(fullName);
967    }
968   
 
969  0 toggle private void addToSkipped(String fullName, XWikiContext context)
970    {
971  0 if (fullName.endsWith(":")) {
972  0 fullName = fullName.substring(0, fullName.length() - 1);
973    }
974   
975  0 getSkipped(context).add(fullName);
976    }
977   
 
978  1978 toggle private void addToInstalled(String fullName, XWikiContext context)
979    {
980  1978 if (fullName.endsWith(":")) {
981  1546 fullName = fullName.substring(0, fullName.length() - 1);
982    }
983   
984  1978 getInstalled(context).add(fullName);
985    }
986   
 
987  170 toggle private void setStatus(int status, XWikiContext context)
988    {
989  170 context.put("install_status", status);
990    }
991   
 
992  8 toggle public List<String> getErrors(XWikiContext context)
993    {
994  8 return getStringList("install_errors", context);
995    }
996   
 
997  8 toggle public List<String> getSkipped(XWikiContext context)
998    {
999  8 return getStringList("install_skipped", context);
1000    }
1001   
 
1002  1994 toggle public List<String> getInstalled(XWikiContext context)
1003    {
1004  1994 return getStringList("install_installed", context);
1005    }
1006   
 
1007  4 toggle public int getStatus(XWikiContext context)
1008    {
1009  4 Integer status = (Integer) context.get("install_status");
1010  4 if (status == null) {
1011  0 return -1;
1012    } else {
1013  4 return status.intValue();
1014    }
1015    }
1016   
1017    /**
1018    * Create a {@link XWikiDocument} from xml stream.
1019    *
1020    * @param is the xml stream.
1021    * @return the {@link XWikiDocument}.
1022    * @throws XWikiException error when creating the {@link XWikiDocument}.
1023    */
 
1024  1982 toggle private XWikiDocument readFromXML(InputStream is) throws XWikiException
1025    {
1026  1982 XWikiDocument doc = new XWikiDocument();
1027   
1028  1982 doc.fromXML(is, this.withVersions);
1029   
1030  1982 return doc;
1031    }
1032   
1033    /**
1034    * Create a {@link XWikiDocument} from xml {@link Document}.
1035    *
1036    * @param domDoc the xml {@link Document}.
1037    * @return the {@link XWikiDocument}.
1038    * @throws XWikiException error when creating the {@link XWikiDocument}.
1039    */
 
1040  0 toggle private XWikiDocument readFromXML(Document domDoc) throws XWikiException
1041    {
1042  0 XWikiDocument doc = new XWikiDocument();
1043   
1044  0 doc.fromXML(domDoc, this.withVersions);
1045   
1046  0 return doc;
1047    }
1048   
1049    /**
1050    * You should prefer {@link #toXML(com.xpn.xwiki.internal.xml.XMLWriter)}. If an error occurs, a stacktrace is dump
1051    * to logs, and an empty String is returned.
1052    *
1053    * @return a package.xml file for the this package
1054    */
 
1055  0 toggle public String toXml(XWikiContext context)
1056    {
1057  0 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1058  0 try {
1059  0 toXML(baos, context);
1060  0 return baos.toString(context.getWiki().getEncoding());
1061    } catch (IOException e) {
1062  0 e.printStackTrace();
1063  0 return "";
1064    }
1065    }
1066   
1067    /**
1068    * Write the package.xml file to an {@link XMLWriter}.
1069    *
1070    * @param wr the writer to write to
1071    * @throws IOException when an error occurs during streaming operation
1072    * @since 2.3M2
1073    */
 
1074  1 toggle public void toXML(XMLWriter wr) throws IOException
1075    {
1076  1 Element docel = new DOMElement("package");
1077  1 wr.writeOpen(docel);
1078   
1079  1 Element elInfos = new DOMElement("infos");
1080  1 wr.write(elInfos);
1081   
1082  1 Element el = new DOMElement("name");
1083  1 el.addText(this.name);
1084  1 wr.write(el);
1085   
1086  1 el = new DOMElement("description");
1087  1 el.addText(this.description);
1088  1 wr.write(el);
1089   
1090  1 el = new DOMElement("licence");
1091  1 el.addText(this.licence);
1092  1 wr.write(el);
1093   
1094  1 el = new DOMElement("author");
1095  1 el.addText(this.authorName);
1096  1 wr.write(el);
1097   
1098  1 el = new DOMElement("version");
1099  1 el.addText(this.version);
1100  1 wr.write(el);
1101   
1102  1 el = new DOMElement("backupPack");
1103  1 el.addText(new Boolean(this.backupPack).toString());
1104  1 wr.write(el);
1105   
1106  1 el = new DOMElement("preserveVersion");
1107  1 el.addText(new Boolean(this.preserveVersion).toString());
1108  1 wr.write(el);
1109   
1110  1 Element elfiles = new DOMElement("files");
1111  1 wr.writeOpen(elfiles);
1112   
1113  1 for (DocumentInfo docInfo : this.files) {
1114  25 Element elfile = new DOMElement("file");
1115  25 elfile.addAttribute("defaultAction", String.valueOf(docInfo.getAction()));
1116  25 elfile.addAttribute("language", String.valueOf(docInfo.getLanguage()));
1117  25 elfile.addText(docInfo.getFullName());
1118  25 wr.write(elfile);
1119    }
1120    }
1121   
1122    /**
1123    * Write the package.xml file to an OutputStream
1124    *
1125    * @param out the OutputStream to write to
1126    * @param context curent XWikiContext
1127    * @throws IOException when an error occurs during streaming operation
1128    * @since 2.3M2
1129    */
 
1130  1 toggle public void toXML(OutputStream out, XWikiContext context) throws IOException
1131    {
1132  1 XMLWriter wr = new XMLWriter(out, new OutputFormat("", true, context.getWiki().getEncoding()));
1133   
1134  1 Document doc = new DOMDocument();
1135  1 wr.writeDocumentStart(doc);
1136  1 toXML(wr);
1137  1 wr.writeDocumentEnd(doc);
1138    }
1139   
1140    /**
1141    * Write the package.xml file to a ZipOutputStream
1142    *
1143    * @param zos the ZipOutputStream to write to
1144    * @param context current XWikiContext
1145    */
 
1146  0 toggle private void addInfosToZip(ZipArchiveOutputStream zos, XWikiContext context)
1147    {
1148  0 try {
1149  0 String zipname = DefaultPackageFileName;
1150  0 ZipArchiveEntry zipentry = new ZipArchiveEntry(zipname);
1151  0 zos.putArchiveEntry(zipentry);
1152  0 toXML(zos, context);
1153  0 zos.closeArchiveEntry();
1154    } catch (Exception e) {
1155  0 e.printStackTrace();
1156    }
1157    }
1158   
1159    /**
1160    * Generate a relative path based on provided document.
1161    *
1162    * @param doc the document to export.
1163    * @return the corresponding path.
1164    */
 
1165  0 toggle public String getPathFromDocument(XWikiDocument doc, XWikiContext context)
1166    {
1167  0 return getDirectoryForDocument(doc) + getFileNameFromDocument(doc, context);
1168    }
1169   
1170    /**
1171    * Generate a file name based on provided document.
1172    *
1173    * @param doc the document to export.
1174    * @return the corresponding file name.
1175    */
 
1176  25 toggle public String getFileNameFromDocument(XWikiDocument doc, XWikiContext context)
1177    {
1178  25 StringBuilder fileName = new StringBuilder(doc.getDocumentReference().getName());
1179   
1180    // Add language
1181  25 String language = doc.getLanguage();
1182  25 if ((language != null) && (!language.equals(""))) {
1183  0 fileName.append(".");
1184  0 fileName.append(language);
1185    }
1186   
1187    // Add extension
1188  25 fileName.append('.').append(DEFAULT_FILEEXT);
1189   
1190  25 return fileName.toString();
1191    }
1192   
1193    /**
1194    * Generate a relative path based on provided document for the directory where the document should be stored.
1195    *
1196    * @param doc the document to export
1197    * @return the corresponding path
1198    */
 
1199  25 toggle public String getDirectoryForDocument(XWikiDocument doc)
1200    {
1201  25 StringBuilder path = new StringBuilder();
1202  25 for (SpaceReference space : doc.getDocumentReference().getSpaceReferences()) {
1203  25 path.append(space.getName()).append('/');
1204    }
1205  25 return path.toString();
1206    }
1207   
1208    /**
1209    * Write an XML serialized XWikiDocument to a ZipOutputStream
1210    *
1211    * @param doc the document to serialize
1212    * @param zos the ZipOutputStream to write to
1213    * @param withVersions if true, also serialize all document versions
1214    * @param context current XWikiContext
1215    * @throws XWikiException when an error occurs during documents access
1216    * @throws IOException when an error occurs during streaming operation
1217    * @deprecated since 4.1M2
1218    */
 
1219  0 toggle @Deprecated
1220    public void addToZip(XWikiDocument doc, ZipOutputStream zos, boolean withVersions, XWikiContext context)
1221    throws XWikiException, IOException
1222    {
1223  0 String zipname = getPathFromDocument(doc, context);
1224  0 ZipEntry zipentry = new ZipEntry(zipname);
1225  0 zos.putNextEntry(zipentry);
1226  0 doc.toXML(zos, true, false, true, withVersions, context);
1227  0 zos.closeEntry();
1228    }
1229   
1230    /**
1231    * Write an XML serialized XWikiDocument to a ZipOutputStream
1232    *
1233    * @param doc the document to serialize
1234    * @param zos the ZipOutputStream to write to
1235    * @param withVersions if true, also serialize all document versions
1236    * @param context current XWikiContext
1237    * @throws XWikiException when an error occurs during documents access
1238    * @throws IOException when an error occurs during streaming operation
1239    * @since 4.1M2
1240    */
 
1241  0 toggle private void addToZip(XWikiDocument doc, ZipArchiveOutputStream zos, boolean withVersions, XWikiContext context)
1242    throws XWikiException, IOException
1243    {
1244  0 String zipname = getPathFromDocument(doc, context);
1245  0 ZipArchiveEntry zipentry = new ZipArchiveEntry(zipname);
1246  0 zos.putArchiveEntry(zipentry);
1247  0 doc.toXML(zos, true, false, true, withVersions, context);
1248  0 zos.closeArchiveEntry();
1249    }
1250   
 
1251  25 toggle public void addToDir(XWikiDocument doc, File dir, boolean withVersions, XWikiContext context) throws XWikiException
1252    {
1253  25 try {
1254  25 filter(doc, context);
1255  25 File spacedir = new File(dir, getDirectoryForDocument(doc));
1256  25 if (!spacedir.exists()) {
1257  1 if (!spacedir.mkdirs()) {
1258  0 Object[] args = new Object[1];
1259  0 args[0] = dir.toString();
1260  0 throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_MKDIR,
1261    "Error creating directory {0}", null, args);
1262    }
1263    }
1264  25 String filename = getFileNameFromDocument(doc, context);
1265  25 File file = new File(spacedir, filename);
1266  25 FileOutputStream fos = new FileOutputStream(file);
1267  25 doc.toXML(fos, true, false, true, withVersions, context);
1268  25 fos.flush();
1269  25 fos.close();
1270    } catch (ExcludeDocumentException e) {
1271  0 LOGGER.info("Skip the document " + doc.getDocumentReference());
1272    } catch (Exception e) {
1273  0 Object[] args = new Object[1];
1274  0 args[0] = doc.getDocumentReference();
1275   
1276  0 throw new XWikiException(XWikiException.MODULE_XWIKI_DOC, XWikiException.ERROR_XWIKI_DOC_EXPORT,
1277    "Error creating file {0}", e, args);
1278    }
1279    }
1280   
 
1281  1 toggle private void addInfosToDir(File dir, XWikiContext context)
1282    {
1283  1 try {
1284  1 String filename = DefaultPackageFileName;
1285  1 File file = new File(dir, filename);
1286  1 FileOutputStream fos = new FileOutputStream(file);
1287  1 toXML(fos, context);
1288  1 fos.flush();
1289  1 fos.close();
1290    } catch (Exception e) {
1291  0 e.printStackTrace();
1292    }
1293    }
1294   
 
1295  1204 toggle protected String getElementText(Element docel, String name)
1296    {
1297  1204 return getElementText(docel, name, "");
1298    }
1299   
 
1300  1376 toggle protected String getElementText(Element docel, String name, String def)
1301    {
1302  1376 Element el = docel.element(name);
1303  1376 if (el == null) {
1304  189 return def;
1305    } else {
1306  1187 return el.getText();
1307    }
1308    }
1309   
 
1310  172 toggle protected Document fromXml(InputStream xml) throws DocumentException
1311    {
1312  172 SAXReader reader = new SAXReader();
1313  172 Document domdoc = reader.read(xml);
1314   
1315  172 Element docEl = domdoc.getRootElement();
1316   
1317  172 Element infosEl = docEl.element("infos");
1318   
1319  172 this.name = getElementText(infosEl, "name");
1320  172 this.description = getElementText(infosEl, "description");
1321  172 this.licence = getElementText(infosEl, "licence");
1322  172 this.authorName = getElementText(infosEl, "author");
1323  172 this.extensionId = getElementText(infosEl, "extensionId", null);
1324  172 this.version = getElementText(infosEl, "version");
1325  172 this.backupPack = new Boolean(getElementText(infosEl, "backupPack")).booleanValue();
1326  172 this.preserveVersion = new Boolean(getElementText(infosEl, "preserveVersion")).booleanValue();
1327   
1328  172 return domdoc;
1329    }
1330   
 
1331  1 toggle public void addAllWikiDocuments(XWikiContext context) throws XWikiException
1332    {
1333  1 XWiki wiki = context.getWiki();
1334  1 try {
1335  1 List<String> documentNames = wiki.getStore().getQueryManager().getNamedQuery("getAllDocuments").execute();
1336  1 for (String docName : documentNames) {
1337  25 add(docName, DocumentInfo.ACTION_OVERWRITE, context);
1338    }
1339    } catch (QueryException ex) {
1340  0 throw new PackageException(XWikiException.ERROR_XWIKI_STORE_HIBERNATE_SEARCH,
1341    "Cannot retrieve the list of documents to export", ex);
1342    }
1343    }
1344   
 
1345  0 toggle public void deleteAllWikiDocuments(XWikiContext context) throws XWikiException
1346    {
1347  0 XWiki wiki = context.getWiki();
1348  0 List<String> spaces = wiki.getSpaces(context);
1349  0 for (int i = 0; i < spaces.size(); i++) {
1350  0 List<String> docNameList = wiki.getSpaceDocsName(spaces.get(i), context);
1351  0 for (String docName : docNameList) {
1352  0 String docFullName = spaces.get(i) + "." + docName;
1353  0 XWikiDocument doc = wiki.getDocument(docFullName, context);
1354  0 wiki.deleteAllDocuments(doc, context);
1355    }
1356    }
1357    }
1358   
1359    /**
1360    * Load document files from provided directory and sub-directories into packager.
1361    *
1362    * @param dir the directory from where to load documents.
1363    * @param context the XWiki context.
1364    * @param description the package descriptor.
1365    * @return the number of loaded documents.
1366    * @throws IOException error when loading documents.
1367    * @throws XWikiException error when loading documents.
1368    */
 
1369  0 toggle public int readFromDir(File dir, XWikiContext context, Document description) throws IOException, XWikiException
1370    {
1371  0 File[] files = dir.listFiles();
1372   
1373  0 SAXReader reader = new SAXReader();
1374   
1375  0 int count = 0;
1376  0 for (File file : files) {
1377  0 if (file.isDirectory()) {
1378  0 count += readFromDir(file, context, description);
1379    } else {
1380  0 boolean validWikiDoc = false;
1381  0 Document domdoc = null;
1382   
1383  0 try {
1384  0 domdoc = reader.read(new FileInputStream(file));
1385  0 validWikiDoc = XWikiDocument.containsXMLWikiDocument(domdoc);
1386    } catch (DocumentException e1) {
1387    }
1388   
1389  0 if (validWikiDoc) {
1390  0 XWikiDocument doc = readFromXML(domdoc);
1391   
1392  0 try {
1393  0 filter(doc, context);
1394   
1395  0 if (documentExistInPackageFile(doc.getFullName(), doc.getLanguage(), description)) {
1396  0 add(doc, context);
1397   
1398  0 ++count;
1399    } else {
1400  0 throw new PackageException(XWikiException.ERROR_XWIKI_UNKNOWN,
1401    "document " + doc.getDocumentReference() + " does not exist in package definition");
1402    }
1403    } catch (ExcludeDocumentException e) {
1404  0 LOGGER.info("Skip the document '" + doc.getDocumentReference() + "'");
1405    }
1406  0 } else if (!file.getName().equals(DefaultPackageFileName)) {
1407  0 LOGGER.info(file.getAbsolutePath() + " is not a valid wiki document");
1408    }
1409    }
1410    }
1411   
1412  0 return count;
1413    }
1414   
1415    /**
1416    * Load document files from provided directory and sub-directories into packager.
1417    *
1418    * @param dir the directory from where to load documents.
1419    * @param context the XWiki context.
1420    * @return
1421    * @throws IOException error when loading documents.
1422    * @throws XWikiException error when loading documents.
1423    */
 
1424  0 toggle public String readFromDir(File dir, XWikiContext context) throws IOException, XWikiException
1425    {
1426  0 if (!dir.isDirectory()) {
1427  0 throw new PackageException(PackageException.ERROR_PACKAGE_UNKNOWN,
1428    dir.getAbsolutePath() + " is not a directory");
1429    }
1430   
1431  0 int count = 0;
1432  0 try {
1433  0 File infofile = new File(dir, DefaultPackageFileName);
1434  0 Document description = fromXml(new FileInputStream(infofile));
1435   
1436  0 count = readFromDir(dir, context, description);
1437   
1438  0 updateFileInfos(description);
1439    } catch (DocumentException e) {
1440  0 throw new PackageException(PackageException.ERROR_PACKAGE_UNKNOWN, "Error when reading the XML");
1441    }
1442   
1443  0 LOGGER.info("Package read " + count + " documents");
1444   
1445  0 return "";
1446    }
1447   
1448    /**
1449    * Outputs the content of this package in the JSON format
1450    *
1451    * @param wikiContext the XWiki context
1452    * @return a representation of this package under the JSON format
1453    * @since 2.2M1
1454    */
 
1455  0 toggle public JSONObject toJSON(XWikiContext wikiContext)
1456    {
1457  0 Map<String, Object> json = new HashMap<String, Object>();
1458   
1459  0 Map<String, Object> infos = new HashMap<String, Object>();
1460  0 infos.put("name", this.name);
1461  0 infos.put("description", this.description);
1462  0 infos.put("licence", this.licence);
1463  0 infos.put("author", this.authorName);
1464  0 infos.put("version", this.version);
1465  0 infos.put("backup", this.isBackupPack());
1466   
1467  0 Map<String, Map<String, List<Map<String, String>>>> files =
1468    new HashMap<String, Map<String, List<Map<String, String>>>>();
1469   
1470  0 for (DocumentInfo docInfo : this.files) {
1471  0 Map<String, String> fileInfos = new HashMap<String, String>();
1472  0 fileInfos.put("defaultAction", String.valueOf(docInfo.getAction()));
1473  0 fileInfos.put("language", String.valueOf(docInfo.getLanguage()));
1474  0 fileInfos.put("fullName", docInfo.getFullName());
1475   
1476    // If the space does not exist in the map of spaces, we create it.
1477  0 if (files.get(docInfo.getDoc().getSpace()) == null) {
1478  0 files.put(docInfo.getDoc().getSpace(), new HashMap<String, List<Map<String, String>>>());
1479    }
1480   
1481    // If the document name does not exists in the space map of docs, we create it.
1482  0 if (files.get(docInfo.getDoc().getSpace()).get(docInfo.getDoc().getName()) == null) {
1483  0 files.get(docInfo.getDoc().getSpace()).put(docInfo.getDoc().getName(),
1484    new ArrayList<Map<String, String>>());
1485    }
1486   
1487    // Finally we add the file infos (language, fullname and action) to the list of translations
1488    // for that document.
1489  0 files.get(docInfo.getDoc().getSpace()).get(docInfo.getDoc().getName()).add(fileInfos);
1490    }
1491   
1492  0 json.put("infos", infos);
1493  0 json.put("files", files);
1494   
1495  0 JSONObject jsonObject = JSONObject.fromObject(json);
1496   
1497  0 return jsonObject;
1498    }
1499    }