1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.filter.confluence.xml.internal

File ConfluenceXMLPackage.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

126
323
69
1
1,073
735
147
0.46
4.68
69
2.13

Classes

Class Line # Actions
ConfluenceXMLPackage 64 323 0% 147 47
0.909266490.9%
 

Contributing tests

This file is covered by 3 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    package org.xwiki.filter.confluence.xml.internal;
21   
22    import java.io.File;
23    import java.io.FileInputStream;
24    import java.io.FileNotFoundException;
25    import java.io.IOException;
26    import java.io.InputStream;
27    import java.text.DateFormat;
28    import java.text.ParseException;
29    import java.text.SimpleDateFormat;
30    import java.util.ArrayList;
31    import java.util.Collection;
32    import java.util.Collections;
33    import java.util.Date;
34    import java.util.LinkedHashMap;
35    import java.util.LinkedHashSet;
36    import java.util.LinkedList;
37    import java.util.List;
38    import java.util.Map;
39    import java.util.Set;
40    import java.util.TreeSet;
41    import java.util.regex.Pattern;
42   
43    import javax.xml.stream.FactoryConfigurationError;
44    import javax.xml.stream.XMLInputFactory;
45    import javax.xml.stream.XMLStreamException;
46    import javax.xml.stream.XMLStreamReader;
47   
48    import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
49    import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
50    import org.apache.commons.configuration.ConfigurationException;
51    import org.apache.commons.configuration.PropertiesConfiguration;
52    import org.apache.commons.io.FileUtils;
53    import org.apache.commons.io.input.CloseShieldInputStream;
54    import org.apache.commons.lang3.math.NumberUtils;
55    import org.xwiki.filter.FilterException;
56    import org.xwiki.filter.input.InputSource;
57    import org.xwiki.filter.input.InputStreamInputSource;
58    import org.xwiki.model.EntityType;
59    import org.xwiki.model.reference.EntityReference;
60    import org.xwiki.xml.stax.StAXUtils;
61   
62    import com.google.common.base.Strings;
63   
 
64    public class ConfluenceXMLPackage
65    {
66    public static final String KEY_SPACE_NAME = "name";
67   
68    public static final String KEY_SPACE_DESCRIPTION = "description";
69   
70    public static final String KEY_PAGE_HOMEPAGE = "homepage";
71   
72    public static final String KEY_PAGE_PARENT = "parent";
73   
74    public static final String KEY_PAGE_SPACE = "space";
75   
76    public static final String KEY_PAGE_TITLE = "title";
77   
78    public static final String KEY_PAGE_CONTENTS = "bodyContents";
79   
80    public static final String KEY_PAGE_CREATION_AUTHOR = "creatorName";
81   
82    public static final String KEY_PAGE_CREATION_DATE = "creationDate";
83   
84    public static final String KEY_PAGE_REVISION = "version";
85   
86    public static final String KEY_PAGE_REVISION_AUTHOR = "lastModifierName";
87   
88    public static final String KEY_PAGE_REVISION_DATE = "lastModificationDate";
89   
90    public static final String KEY_PAGE_REVISION_COMMENT = "versionComment";
91   
92    public static final String KEY_PAGE_REVISIONS = "historicalVersions";
93   
94    public static final String KEY_PAGE_CONTENT_STATUS = "contentStatus";
95   
96    public static final String KEY_PAGE_BODY = "body";
97   
98    public static final String KEY_PAGE_BODY_TYPE = "bodyType";
99   
100    /**
101    * Old property to indicate attachment name.
102    *
103    * @see #KEY_ATTACHMENT_TITLE
104    */
105    public static final String KEY_ATTACHMENT_NAME = "fileName";
106   
107    public static final String KEY_ATTACHMENT_TITLE = "title";
108   
109    /**
110    * Old field containing attachment page id.
111    *
112    * @see #KEY_ATTACHMENT_CONTAINERCONTENT
113    */
114    public static final String KEY_ATTACHMENT_CONTENT = "content";
115   
116    public static final String KEY_ATTACHMENT_CONTAINERCONTENT = "containerContent";
117   
118    /**
119    * Old property to indicate attachment size.
120    *
121    * @see #KEY_ATTACHMENT_CONTENTPROPERTIES
122    * @see #KEY_ATTACHMENT_CONTENT_FILESIZE
123    */
124    public static final String KEY_ATTACHMENT_CONTENT_SIZE = "fileSize";
125   
126    /**
127    * Old property to indicate attachment media type.
128    *
129    * @see #KEY_ATTACHMENT_CONTENTPROPERTIES
130    * @see #KEY_ATTACHMENT_CONTENT_MEDIA_TYPE
131    */
132    public static final String KEY_ATTACHMENT_CONTENTTYPE = "contentType";
133   
134    public static final String KEY_ATTACHMENT_CONTENTPROPERTIES = "contentProperties";
135   
136    public static final String KEY_ATTACHMENT_CONTENTSTATUS = "contentStatus";
137   
138    public static final String KEY_ATTACHMENT_CONTENT_MINOR_EDIT = "MINOR_EDIT";
139   
140    public static final String KEY_ATTACHMENT_CONTENT_FILESIZE = "FILESIZE";
141   
142    public static final String KEY_ATTACHMENT_CONTENT_MEDIA_TYPE = "MEDIA_TYPE";
143   
144    public static final String KEY_ATTACHMENT_CREATION_AUTHOR = "creatorName";
145   
146    public static final String KEY_ATTACHMENT_CREATION_DATE = "creationDate";
147   
148    public static final String KEY_ATTACHMENT_REVISION_AUTHOR = "lastModifierName";
149   
150    public static final String KEY_ATTACHMENT_REVISION_DATE = "lastModificationDate";
151   
152    public static final String KEY_ATTACHMENT_REVISION_COMMENT = "comment";
153   
154    /**
155    * Old property to indicate attachment revision.
156    *
157    * @see #KEY_ATTACHMENT_VERSION
158    */
159    public static final String KEY_ATTACHMENT_ATTACHMENTVERSION = "attachmentVersion";
160   
161    public static final String KEY_ATTACHMENT_VERSION = "version";
162   
163    /**
164    * Old property to indicate attachment original revision.
165    *
166    * @see #KEY_ATTACHMENT_ORIGINALVERSIONID
167    */
168    public static final String KEY_ATTACHMENT_ORIGINALVERSION = "originalVersion";
169   
170    public static final String KEY_ATTACHMENT_ORIGINALVERSIONID = "originalVersionId";
171   
172    public static final String KEY_ATTACHMENT_DTO = "imageDetailsDTO";
173   
174    public static final String KEY_GROUP_NAME = "name";
175   
176    public static final String KEY_GROUP_ACTIVE = "active";
177   
178    public static final String KEY_GROUP_LOCAL = "local";
179   
180    public static final String KEY_GROUP_CREATION_DATE = "createdDate";
181   
182    public static final String KEY_GROUP_REVISION_DATE = "updatedDate";
183   
184    public static final String KEY_GROUP_DESCRIPTION = "description";
185   
186    public static final String KEY_GROUP_MEMBERUSERS = "memberusers";
187   
188    public static final String KEY_GROUP_MEMBERGROUPS = "membergroups";
189   
190    public static final String KEY_USER_NAME = "name";
191   
192    public static final String KEY_USER_ACTIVE = "active";
193   
194    public static final String KEY_USER_CREATION_DATE = "createdDate";
195   
196    public static final String KEY_USER_REVISION_DATE = "updatedDate";
197   
198    public static final String KEY_USER_FIRSTNAME = "firstName";
199   
200    public static final String KEY_USER_LASTNAME = "lastName";
201   
202    public static final String KEY_USER_DISPLAYNAME = "displayName";
203   
204    public static final String KEY_USER_EMAIL = "emailAddress";
205   
206    public static final String KEY_USER_PASSWORD = "credential";
207   
208    /**
209    * 2012-03-07 17:16:48.158
210    */
211    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
212   
213    /**
214    * pattern to find the end of "intentionally damaged" CDATA end sections. Confluence does this to nest CDATA
215    * sections inside CDATA sections. Interestingly it does not care if there is a > after the ]].
216    */
217    private static final Pattern FIND_BROKEN_CDATA_PATTERN = Pattern.compile("]] ");
218   
219    /**
220    * replacement to repair the CDATA
221    */
222    private static final String REPAIRED_CDATA_END = "]]";
223   
224    private static final XMLInputFactory XML_INPUT_FACTORY = XMLInputFactory.newInstance();
225   
226    private File directory;
227   
228    private File entities;
229   
230    private File descriptor;
231   
232    private File tree;
233   
234    private Map<Integer, List<Integer>> pages = new LinkedHashMap<>();
235   
 
236  3 toggle public ConfluenceXMLPackage(InputSource source)
237    throws IOException, FilterException, XMLStreamException, FactoryConfigurationError, ConfigurationException
238    {
239  3 InputStream stream;
240   
241  3 if (source instanceof InputStreamInputSource) {
242  3 stream = ((InputStreamInputSource) source).getInputStream();
243    } else {
244  0 throw new FilterException(
245    String.format("Unsupported input source of type [%s]", source.getClass().getName()));
246    }
247   
248  3 try {
249    // Get temporary folder
250  3 this.directory = File.createTempFile("confluencexml", "");
251  3 this.directory.delete();
252  3 this.directory.mkdir();
253  3 this.directory.deleteOnExit();
254   
255    // Extract the zip
256  3 ZipArchiveInputStream zais = new ZipArchiveInputStream(stream);
257  80 for (ZipArchiveEntry zipEntry = zais.getNextZipEntry(); zipEntry != null; zipEntry =
258    zais.getNextZipEntry()) {
259  77 if (!zipEntry.isDirectory()) {
260  41 String path = zipEntry.getName();
261  41 File file = new File(this.directory, path);
262   
263  41 if (path.equals("entities.xml")) {
264  3 this.entities = file;
265  38 } else if (path.equals("exportDescriptor.properties")) {
266  3 this.descriptor = file;
267    }
268   
269  41 FileUtils.copyInputStreamToFile(new CloseShieldInputStream(zais), file);
270    }
271    }
272    } finally {
273  3 source.close();
274    }
275   
276    // Initialize
277   
278  3 createTree();
279    }
280   
 
281  704 toggle private PropertiesConfiguration newProperties()
282    {
283  704 PropertiesConfiguration properties = new PropertiesConfiguration();
284   
285  704 properties.setDelimiterParsingDisabled(true);
286   
287  704 return properties;
288    }
289   
 
290  136 toggle public Date getDate(PropertiesConfiguration properties, String key) throws ParseException
291    {
292  136 String str = properties.getString(key);
293   
294  136 return str != null ? DATE_FORMAT.parse(str) : null;
295    }
296   
 
297  31 toggle public List<Integer> getIntegertList(PropertiesConfiguration properties, String key)
298    {
299  31 return getIntegertList(properties, key, null);
300    }
301   
 
302  42 toggle public List<Integer> getIntegertList(PropertiesConfiguration properties, String key, List<Integer> def)
303    {
304  42 List<Object> list = properties.getList(key, null);
305   
306  42 if (list == null) {
307  8 return def;
308    }
309   
310  34 if (list.isEmpty()) {
311  0 return Collections.emptyList();
312    }
313   
314  34 if (list.get(0) instanceof Integer) {
315  0 return (List) list;
316    }
317   
318  34 List<Integer> integerList = new ArrayList<>(list.size());
319  34 for (Object element : list) {
320  83 integerList.add(Integer.valueOf(element.toString()));
321    }
322   
323  34 return integerList;
324    }
325   
 
326  20 toggle public PropertiesConfiguration getContentProperties(PropertiesConfiguration properties, String key)
327    throws ConfigurationException
328    {
329  20 List<Integer> elements = getIntegertList(properties, key);
330   
331  20 if (elements == null) {
332  0 return null;
333    }
334   
335  20 PropertiesConfiguration contentProperties = new PropertiesConfiguration();
336  20 for (Integer element : elements) {
337  60 PropertiesConfiguration contentProperty = getObjectProperties(element);
338  60 if (contentProperty != null) {
339  60 String name = contentProperty.getString("name");
340   
341  60 Object value = contentProperty.getString("longValue", null);
342  60 if (Strings.isNullOrEmpty((String) value)) {
343  20 value = contentProperty.getString("dateValue", null);
344  20 if (Strings.isNullOrEmpty((String) value)) {
345  20 value = contentProperty.getString("stringValue", null);
346    } else {
347    // TODO: dateValue
348    }
349    } else {
350  40 value = contentProperty.getLong("longValue", null);
351    }
352   
353  60 contentProperties.setProperty(name, value);
354    }
355    }
356   
357  20 return contentProperties;
358   
359    }
360   
 
361  13 toggle public EntityReference getReferenceFromId(PropertiesConfiguration currentProperties, String key)
362    throws ConfigurationException
363    {
364  13 Integer pageId = currentProperties.getInteger(key, null);
365  13 if (pageId != null) {
366  13 PropertiesConfiguration pageProperties = getPageProperties(pageId);
367   
368  13 int spaceId = pageProperties.getInt(KEY_PAGE_SPACE);
369  13 int currentSpaceId = currentProperties.getInt(KEY_PAGE_SPACE);
370   
371  13 EntityReference spaceReference;
372  13 if (spaceId != currentSpaceId) {
373  0 spaceReference = new EntityReference(getSpaceName(currentSpaceId), EntityType.SPACE);
374    } else {
375  13 spaceReference = null;
376    }
377   
378  13 return new EntityReference(pageProperties.getString(KEY_PAGE_TITLE), EntityType.DOCUMENT, spaceReference);
379    }
380   
381  0 return null;
382    }
383   
 
384  0 toggle public String getSpaceName(int spaceId) throws ConfigurationException
385    {
386  0 PropertiesConfiguration spaceProperties = getSpaceProperties(spaceId);
387   
388  0 return spaceProperties.getString(KEY_SPACE_NAME);
389    }
390   
 
391  3 toggle public Map<Integer, List<Integer>> getPages()
392    {
393  3 return this.pages;
394    }
395   
 
396  3 toggle private void createTree()
397    throws XMLStreamException, FactoryConfigurationError, IOException, ConfigurationException, FilterException
398    {
399  3 this.tree = new File(this.directory, "tree");
400  3 this.tree.mkdir();
401   
402  3 try (InputStream stream = new FileInputStream(getEntities())) {
403  3 XMLStreamReader xmlReader = XML_INPUT_FACTORY.createXMLStreamReader(stream);
404   
405  3 xmlReader.nextTag();
406   
407  707 for (xmlReader.nextTag(); xmlReader.isStartElement(); xmlReader.nextTag()) {
408  704 String elementName = xmlReader.getLocalName();
409   
410  704 if (elementName.equals("object")) {
411  704 readObject(xmlReader);
412    } else {
413  0 StAXUtils.skipElement(xmlReader);
414    }
415    }
416    }
417    }
418   
 
419  704 toggle private void readObject(XMLStreamReader xmlReader)
420    throws XMLStreamException, ConfigurationException, FilterException
421    {
422  704 String type = xmlReader.getAttributeValue(null, "class");
423   
424  704 if (type != null) {
425  704 if (type.equals("Page")) {
426  27 readPageObject(xmlReader);
427  677 } else if (type.equals("Space")) {
428  5 readSpaceObject(xmlReader);
429  672 } else if (type.equals("InternalUser")) {
430  5 readUserObject(xmlReader);
431  667 } else if (type.equals("InternalGroup")) {
432  11 readGroupObject(xmlReader);
433  656 } else if (type.equals("HibernateMembership")) {
434  11 readMembershipObject(xmlReader);
435  645 } else if (type.equals("BodyContent")) {
436  43 readBodyContentObject(xmlReader);
437  602 } else if (type.equals("SpaceDescription")) {
438  5 readSpaceDescriptionObject(xmlReader);
439  597 } else if (type.equals("SpacePermission")) {
440  147 readSpacePermissionObject(xmlReader);
441  450 } else if (type.equals("Attachment")) {
442  34 readAttachmentObject(xmlReader);
443    } else {
444  416 PropertiesConfiguration properties = newProperties();
445   
446  416 int id = readObjectProperties(xmlReader, properties);
447   
448    // Save page
449  416 saveObjectProperties(properties, id);
450    }
451    }
452    }
453   
 
454  704 toggle private int readObjectProperties(XMLStreamReader xmlReader, PropertiesConfiguration properties)
455    throws XMLStreamException, FilterException
456    {
457  704 int id = -1;
458   
459  5629 for (xmlReader.nextTag(); xmlReader.isStartElement(); xmlReader.nextTag()) {
460  4925 String elementName = xmlReader.getLocalName();
461   
462  4925 if (elementName.equals("id")) {
463  696 String idName = xmlReader.getAttributeValue(null, "name");
464   
465  696 if (idName != null && idName.equals("id")) {
466  691 id = Integer.valueOf(xmlReader.getElementText());
467   
468  691 properties.setProperty("id", id);
469    } else {
470  5 StAXUtils.skipElement(xmlReader);
471    }
472  4229 } else if (elementName.equals("property")) {
473  4054 String propertyName = xmlReader.getAttributeValue(null, "name");
474   
475  4054 properties.setProperty(propertyName, readProperty(xmlReader));
476  175 } else if (elementName.equals("collection")) {
477  160 String propertyName = xmlReader.getAttributeValue(null, "name");
478   
479  160 properties.setProperty(propertyName, readProperty(xmlReader));
480    } else {
481  15 StAXUtils.skipElement(xmlReader);
482    }
483    }
484   
485  704 return id;
486    }
487   
 
488  34 toggle private void readAttachmentObject(XMLStreamReader xmlReader)
489    throws XMLStreamException, FilterException, ConfigurationException
490    {
491  34 PropertiesConfiguration properties = newProperties();
492   
493  34 int attachmentId = readObjectProperties(xmlReader, properties);
494   
495  34 Integer pageId = getAttachmentPageId(properties);
496   
497  34 if (pageId != null) {
498    // Save attachment
499  33 saveAttachmentProperties(properties, pageId, attachmentId);
500    }
501    }
502   
 
503  34 toggle private Integer getAttachmentPageId(PropertiesConfiguration properties)
504    {
505  34 Integer pageId = getInteger(properties, KEY_ATTACHMENT_CONTAINERCONTENT, null);
506   
507  34 if (pageId == null) {
508  7 pageId = properties.getInteger(KEY_ATTACHMENT_CONTENT, null);
509    }
510   
511  34 return pageId;
512    }
513   
 
514  5 toggle private void readSpaceObject(XMLStreamReader xmlReader)
515    throws XMLStreamException, FilterException, ConfigurationException
516    {
517  5 PropertiesConfiguration properties = newProperties();
518   
519  5 int spaceId = readObjectProperties(xmlReader, properties);
520   
521    // Save page
522  5 saveSpaceProperties(properties, spaceId);
523   
524    // Register space
525  5 List<Integer> spacePages = this.pages.get(spaceId);
526  5 if (spacePages == null) {
527  2 spacePages = new LinkedList<>();
528  2 this.pages.put(spaceId, spacePages);
529    }
530    }
531   
 
532  5 toggle private void readSpaceDescriptionObject(XMLStreamReader xmlReader)
533    throws XMLStreamException, FilterException, ConfigurationException
534    {
535  5 PropertiesConfiguration properties = newProperties();
536   
537  5 int descriptionId = readObjectProperties(xmlReader, properties);
538   
539  5 properties.setProperty(KEY_PAGE_HOMEPAGE, true);
540   
541    // Save page
542  5 savePageProperties(properties, descriptionId);
543    }
544   
 
545  147 toggle private void readSpacePermissionObject(XMLStreamReader xmlReader)
546    throws XMLStreamException, ConfigurationException, FilterException
547    {
548  147 PropertiesConfiguration properties = newProperties();
549   
550  147 int permissionId = readObjectProperties(xmlReader, properties);
551   
552  147 Integer spaceId = properties.getInteger("space", null);
553  147 if (spaceId != null) {
554    // Save attachment
555  111 saveSpacePermissionsProperties(properties, spaceId, permissionId);
556    }
557    }
558   
 
559  43 toggle private void readBodyContentObject(XMLStreamReader xmlReader)
560    throws XMLStreamException, ConfigurationException, FilterException
561    {
562  43 PropertiesConfiguration properties = newProperties();
563  43 properties.setDelimiterParsingDisabled(true);
564   
565  43 readObjectProperties(xmlReader, properties);
566   
567  43 Integer pageId = properties.getInteger("content", null);
568  43 if (pageId != null) {
569  38 savePageProperties(properties, pageId);
570    }
571    }
572   
 
573  27 toggle private void readPageObject(XMLStreamReader xmlReader)
574    throws XMLStreamException, ConfigurationException, FilterException
575    {
576  27 PropertiesConfiguration properties = newProperties();
577   
578  27 int pageId = readObjectProperties(xmlReader, properties);
579   
580    // Save page
581  27 savePageProperties(properties, pageId);
582   
583    // Register only current pages (they will take care of handling there history)
584  27 Integer originalVersion = (Integer) properties.getProperty("originalVersion");
585  27 if (originalVersion == null) {
586  19 Integer spaceId = (Integer) properties.getInteger("space", null);
587  19 List<Integer> spacePages = this.pages.get(spaceId);
588  19 if (spacePages == null) {
589  3 spacePages = new LinkedList<>();
590  3 this.pages.put(spaceId, spacePages);
591    }
592  19 spacePages.add(pageId);
593    }
594    }
595   
 
596  5 toggle private void readUserObject(XMLStreamReader xmlReader)
597    throws XMLStreamException, ConfigurationException, FilterException
598    {
599  5 PropertiesConfiguration properties = newProperties();
600   
601  5 int pageId = readObjectProperties(xmlReader, properties);
602   
603    // Save page
604  5 saveObjectProperties("users", properties, pageId);
605    }
606   
 
607  11 toggle private void readGroupObject(XMLStreamReader xmlReader)
608    throws XMLStreamException, ConfigurationException, FilterException
609    {
610  11 PropertiesConfiguration properties = newProperties();
611   
612  11 int pageId = readObjectProperties(xmlReader, properties);
613   
614    // Save page
615  11 saveObjectProperties("groups", properties, pageId);
616    }
617   
 
618  11 toggle private void readMembershipObject(XMLStreamReader xmlReader)
619    throws ConfigurationException, XMLStreamException, FilterException
620    {
621  11 PropertiesConfiguration properties = newProperties();
622   
623  11 readObjectProperties(xmlReader, properties);
624   
625  11 Integer parentGroup = properties.getInteger("parentGroup", null);
626   
627  11 if (parentGroup != null) {
628  11 PropertiesConfiguration groupProperties = getGroupProperties(parentGroup);
629   
630  11 Integer userMember = properties.getInteger("userMember", null);
631   
632  11 if (userMember != null) {
633  11 List<Integer> users = new ArrayList<>(
634    getIntegertList(groupProperties, KEY_GROUP_MEMBERUSERS, Collections.<Integer>emptyList()));
635  11 users.add(userMember);
636  11 groupProperties.setProperty(KEY_GROUP_MEMBERUSERS, users);
637    }
638   
639  11 Integer groupMember = properties.getInteger("groupMember", null);
640   
641  11 if (groupMember != null) {
642  0 List<Integer> groups = new ArrayList<>(
643    getIntegertList(groupProperties, KEY_GROUP_MEMBERGROUPS, Collections.<Integer>emptyList()));
644  0 groups.add(groupMember);
645  0 groupProperties.setProperty(KEY_GROUP_MEMBERGROUPS, groups);
646    }
647   
648  11 saveObjectProperties("groups", groupProperties, parentGroup);
649    }
650    }
651   
 
652  4652 toggle private Object readProperty(XMLStreamReader xmlReader) throws XMLStreamException, FilterException
653    {
654  4652 String propertyClass = xmlReader.getAttributeValue(null, "class");
655   
656  4652 if (propertyClass == null) {
657  3601 return fixCData(xmlReader.getElementText());
658  1051 } else if (propertyClass.equals("java.util.List") || propertyClass.equals("java.util.Collection")) {
659  146 return readListProperty(xmlReader);
660  905 } else if (propertyClass.equals("java.util.Set")) {
661  8 return readSetProperty(xmlReader);
662  897 } else if (propertyClass.equals("Page") || propertyClass.equals("Space") || propertyClass.equals("BodyContent")
663    || propertyClass.equals("Attachment") || propertyClass.equals("SpaceDescription")
664    || propertyClass.equals("Labelling") || propertyClass.equals("SpacePermission")
665    || propertyClass.equals("InternalGroup") || propertyClass.equals("InternalUser")
666    || propertyClass.equals("Comment") || propertyClass.equals("ContentProperty")) {
667  704 return readObjectReference(xmlReader);
668    } else {
669  193 StAXUtils.skipElement(xmlReader);
670    }
671   
672  193 return null;
673    }
674   
675    /**
676    * to protect content with cdata section inside of cdata elements confluence adds a single space after two
677    * consecutive curly braces. we need to undo this patch as otherwise the content parser will complain about invalid
678    * content. strictly speaking this needs only to be done for string valued properties
679    */
 
680  3601 toggle private String fixCData(String elementText)
681    {
682  3601 if (elementText == null) {
683  0 return elementText;
684    }
685  3601 return FIND_BROKEN_CDATA_PATTERN.matcher(elementText).replaceAll(REPAIRED_CDATA_END);
686    }
687   
 
688  704 toggle private Integer readObjectReference(XMLStreamReader xmlReader) throws FilterException, XMLStreamException
689    {
690  704 xmlReader.nextTag();
691   
692  704 if (!xmlReader.getLocalName().equals("id")) {
693  0 throw new FilterException(
694    String.format("Was expecting id element but found [%s]", xmlReader.getLocalName()));
695    }
696   
697  704 Integer id = Integer.valueOf(xmlReader.getElementText());
698   
699  704 xmlReader.nextTag();
700   
701  704 return id;
702    }
703   
 
704  146 toggle private List<Object> readListProperty(XMLStreamReader xmlReader) throws XMLStreamException, FilterException
705    {
706  146 List<Object> list = new ArrayList<>();
707   
708  536 for (xmlReader.nextTag(); xmlReader.isStartElement(); xmlReader.nextTag()) {
709  390 list.add(readProperty(xmlReader));
710    }
711   
712  146 return list;
713    }
714   
 
715  8 toggle private Set<Object> readSetProperty(XMLStreamReader xmlReader) throws XMLStreamException, FilterException
716    {
717  8 Set<Object> set = new LinkedHashSet<>();
718   
719  56 for (xmlReader.nextTag(); xmlReader.isStartElement(); xmlReader.nextTag()) {
720  48 set.add(readProperty(xmlReader));
721    }
722   
723  8 return set;
724    }
725   
 
726  121 toggle private File getSpacesFolder()
727    {
728  121 return new File(this.tree, "spaces");
729    }
730   
 
731  121 toggle private File getSpaceFolder(int spaceId)
732    {
733  121 return new File(getSpacesFolder(), String.valueOf(spaceId));
734    }
735   
 
736  237 toggle private File getPagesFolder()
737    {
738  237 return new File(this.tree, "pages");
739    }
740   
 
741  547 toggle private File getObjectsFolder(String folderName)
742    {
743  547 return new File(this.tree, folderName);
744    }
745   
 
746  3 toggle private File getUsersFolder()
747    {
748  3 return getObjectsFolder("users");
749    }
750   
 
751  3 toggle private File getGroupsFolder()
752    {
753  3 return getObjectsFolder("groups");
754    }
755   
 
756  237 toggle private File getPageFolder(int pageId)
757    {
758  237 return new File(getPagesFolder(), String.valueOf(pageId));
759    }
760   
 
761  541 toggle private File getObjectFolder(String folderName, int objectId)
762    {
763  541 return new File(getObjectsFolder(folderName), String.valueOf(objectId));
764    }
765   
 
766  139 toggle private File getPagePropertiesFile(int pageId)
767    {
768  139 File folder = getPageFolder(pageId);
769   
770  139 return new File(folder, "properties.properties");
771    }
772   
 
773  541 toggle private File getObjectPropertiesFile(String folderName, int propertyId)
774    {
775  541 File folder = getObjectFolder(folderName, propertyId);
776   
777  541 return new File(folder, "properties.properties");
778    }
779   
 
780  32 toggle public Collection<Integer> getAttachments(int pageId)
781    {
782  32 File folder = getAttachmentsFolder(pageId);
783   
784  32 Collection<Integer> attachments;
785  32 if (folder.exists()) {
786  11 String[] attachmentFolders = folder.list();
787   
788  11 attachments = new TreeSet<>();
789  11 for (String attachmentIdString : attachmentFolders) {
790  33 if (NumberUtils.isNumber(attachmentIdString)) {
791  33 attachments.add(Integer.valueOf(attachmentIdString));
792    }
793    }
794    } else {
795  21 attachments = Collections.emptyList();
796    }
797   
798  32 return attachments;
799    }
800   
 
801  98 toggle private File getAttachmentsFolder(int pageId)
802    {
803  98 return new File(getPageFolder(pageId), "attachments");
804    }
805   
 
806  111 toggle private File getSpacePermissionsFolder(int spaceId)
807    {
808  111 return new File(getSpaceFolder(spaceId), "permissions");
809    }
810   
 
811  66 toggle private File getAttachmentFolder(int pageId, int attachmentId)
812    {
813  66 return new File(getAttachmentsFolder(pageId), String.valueOf(attachmentId));
814    }
815   
 
816  111 toggle private File getSpacePermissionFolder(int spaceId, int permissionId)
817    {
818  111 return new File(getSpacePermissionsFolder(spaceId), String.valueOf(permissionId));
819    }
820   
 
821  66 toggle private File getAttachmentPropertiesFile(int pageId, int attachmentId)
822    {
823  66 File folder = getAttachmentFolder(pageId, attachmentId);
824   
825  66 return new File(folder, "properties.properties");
826    }
827   
 
828  111 toggle private File getSpacePermissionPropertiesFile(int spaceId, int permissionId)
829    {
830  111 File folder = getSpacePermissionFolder(spaceId, permissionId);
831   
832  111 return new File(folder, "properties.properties");
833    }
834   
 
835  10 toggle private File getSpacePropertiesFile(int spaceId)
836    {
837  10 File folder = getSpaceFolder(spaceId);
838   
839  10 return new File(folder, "properties.properties");
840    }
841   
 
842  139 toggle public PropertiesConfiguration getPageProperties(int pageId) throws ConfigurationException
843    {
844  139 File file = getPagePropertiesFile(pageId);
845   
846  139 return new PropertiesConfiguration(file);
847    }
848   
 
849  60 toggle public PropertiesConfiguration getObjectProperties(Integer objectId) throws ConfigurationException
850    {
851  60 return getObjectProperties("objects", objectId);
852    }
853   
 
854  541 toggle public PropertiesConfiguration getObjectProperties(String folder, Integer objectId) throws ConfigurationException
855    {
856  541 int id;
857  541 if (objectId != null) {
858  541 id = (Integer) objectId;
859    } else {
860  0 return null;
861    }
862   
863  541 File file = getObjectPropertiesFile(folder, id);
864   
865  541 return new PropertiesConfiguration(file);
866    }
867   
 
868  16 toggle public PropertiesConfiguration getUserProperties(Integer userId) throws ConfigurationException
869    {
870  16 return getObjectProperties("users", userId);
871    }
872   
 
873  3 toggle public Collection<Integer> getUsers()
874    {
875  3 File folder = getUsersFolder();
876   
877  3 Collection<Integer> users;
878  3 if (folder.exists()) {
879  2 String[] userFolders = folder.list();
880   
881  2 users = new TreeSet<>();
882  2 for (String userIdString : userFolders) {
883  5 if (NumberUtils.isNumber(userIdString)) {
884  5 users.add(Integer.valueOf(userIdString));
885    }
886    }
887    } else {
888  1 users = Collections.emptyList();
889    }
890   
891  3 return users;
892    }
893   
 
894  3 toggle public Collection<Integer> getGroups()
895    {
896  3 File folder = getGroupsFolder();
897   
898  3 Collection<Integer> groups;
899  3 if (folder.exists()) {
900  2 String[] groupFolders = folder.list();
901   
902  2 groups = new TreeSet<>();
903  2 for (String groupIdString : groupFolders) {
904  11 if (NumberUtils.isNumber(groupIdString)) {
905  11 groups.add(Integer.valueOf(groupIdString));
906    }
907    }
908    } else {
909  1 groups = Collections.emptyList();
910    }
911   
912  3 return groups;
913    }
914   
 
915  22 toggle public PropertiesConfiguration getGroupProperties(Integer groupId) throws ConfigurationException
916    {
917  22 return getObjectProperties("groups", groupId);
918    }
919   
 
920  66 toggle public PropertiesConfiguration getAttachmentProperties(int pageId, int attachmentId) throws ConfigurationException
921    {
922  66 File file = getAttachmentPropertiesFile(pageId, attachmentId);
923   
924  66 return new PropertiesConfiguration(file);
925    }
926   
 
927  111 toggle public PropertiesConfiguration getSpacePermissionProperties(int spaceId, int permissionId)
928    throws ConfigurationException
929    {
930  111 File file = getSpacePermissionPropertiesFile(spaceId, permissionId);
931   
932  111 return new PropertiesConfiguration(file);
933    }
934   
 
935  10 toggle public PropertiesConfiguration getSpaceProperties(int spaceId) throws ConfigurationException
936    {
937  10 File file = getSpacePropertiesFile(spaceId);
938   
939  10 return new PropertiesConfiguration(file);
940    }
941   
 
942  70 toggle private void savePageProperties(PropertiesConfiguration properties, int pageId) throws ConfigurationException
943    {
944  70 PropertiesConfiguration fileProperties = getPageProperties(pageId);
945   
946  70 fileProperties.copy(properties);
947   
948  70 fileProperties.save();
949    }
950   
 
951  416 toggle private void saveObjectProperties(PropertiesConfiguration properties, int objectId) throws ConfigurationException
952    {
953  416 saveObjectProperties("objects", properties, objectId);
954    }
955   
 
956  443 toggle private void saveObjectProperties(String folder, PropertiesConfiguration properties, int objectId)
957    throws ConfigurationException
958    {
959  443 PropertiesConfiguration fileProperties = getObjectProperties(folder, objectId);
960   
961  443 fileProperties.copy(properties);
962   
963  443 fileProperties.save();
964    }
965   
 
966  33 toggle private void saveAttachmentProperties(PropertiesConfiguration properties, int pageId, int attachmentId)
967    throws ConfigurationException
968    {
969  33 PropertiesConfiguration fileProperties = getAttachmentProperties(pageId, attachmentId);
970   
971  33 fileProperties.copy(properties);
972   
973  33 fileProperties.save();
974    }
975   
 
976  111 toggle private void saveSpacePermissionsProperties(PropertiesConfiguration properties, int spaceId, int permissionId)
977    throws ConfigurationException
978    {
979  111 PropertiesConfiguration fileProperties = getSpacePermissionProperties(spaceId, permissionId);
980   
981  111 fileProperties.copy(properties);
982   
983  111 fileProperties.save();
984    }
985   
 
986  5 toggle private void saveSpaceProperties(PropertiesConfiguration properties, int spaceId) throws ConfigurationException
987    {
988  5 PropertiesConfiguration fileProperties = getSpaceProperties(spaceId);
989   
990  5 fileProperties.copy(properties);
991   
992  5 fileProperties.save();
993    }
994   
 
995  3 toggle public File getEntities()
996    {
997  3 return this.entities;
998    }
999   
 
1000  0 toggle public File getDescriptor()
1001    {
1002  0 return this.descriptor;
1003    }
1004   
 
1005  25 toggle public File getAttachmentFile(int pageId, int attachmentId, int version) throws FileNotFoundException
1006    {
1007  25 File attachmentsFolder = new File(this.directory, "attachments");
1008  25 File attachmentsPageFolder = new File(attachmentsFolder, String.valueOf(pageId));
1009  25 File attachmentFolder = new File(attachmentsPageFolder, String.valueOf(attachmentId));
1010   
1011    // In old version the file name is the version
1012  25 File file = new File(attachmentFolder, String.valueOf(version));
1013   
1014  25 if (file.exists()) {
1015  25 return file;
1016    }
1017   
1018    // In recent version the name is always 1
1019  0 file = new File(attachmentFolder, "1");
1020   
1021  0 if (file.exists()) {
1022  0 return file;
1023    }
1024   
1025  0 throw new FileNotFoundException(file.getAbsolutePath());
1026    }
1027   
 
1028  3 toggle public void close() throws IOException
1029    {
1030  3 if (this.tree != null) {
1031  3 FileUtils.deleteDirectory(this.tree);
1032    }
1033    }
1034   
 
1035  58 toggle public String getAttachmentName(PropertiesConfiguration attachmentProperties)
1036    {
1037  58 String attachmentName = attachmentProperties.getString(ConfluenceXMLPackage.KEY_ATTACHMENT_TITLE, null);
1038  58 if (attachmentName == null) {
1039  11 attachmentName = attachmentProperties.getString(ConfluenceXMLPackage.KEY_ATTACHMENT_NAME);
1040    }
1041   
1042  58 return attachmentName;
1043    }
1044   
 
1045  37 toggle public Integer getAttachementVersion(PropertiesConfiguration attachmentProperties)
1046    {
1047  37 Integer version = getInteger(attachmentProperties, ConfluenceXMLPackage.KEY_ATTACHMENT_VERSION, null);
1048  37 if (version == null) {
1049  7 version = getInteger(attachmentProperties, ConfluenceXMLPackage.KEY_ATTACHMENT_ATTACHMENTVERSION, null);
1050    }
1051   
1052  37 return version;
1053    }
1054   
 
1055  25 toggle public int getAttachmentOriginalVersionId(PropertiesConfiguration attachmentProperties, int def)
1056    {
1057  25 Integer originalRevisionId =
1058    getInteger(attachmentProperties, ConfluenceXMLPackage.KEY_ATTACHMENT_ORIGINALVERSIONID, null);
1059  25 return originalRevisionId != null ? originalRevisionId
1060    : getInteger(attachmentProperties, ConfluenceXMLPackage.KEY_ATTACHMENT_ORIGINALVERSION, def);
1061    }
1062   
 
1063  128 toggle public Integer getInteger(PropertiesConfiguration properties, String key, Integer def)
1064    {
1065  128 try {
1066  128 return properties.getInteger(key, def);
1067    } catch (Exception e) {
1068    // Usually mean the field does not have the expected format
1069   
1070  20 return def;
1071    }
1072    }
1073    }