OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 80 | Rev 144 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 80 Rev 83
Line 16... Line 16...
16
import static org.openconcerto.openoffice.ODPackage.RootElement.CONTENT;
16
import static org.openconcerto.openoffice.ODPackage.RootElement.CONTENT;
17
import static org.openconcerto.openoffice.ODPackage.RootElement.META;
17
import static org.openconcerto.openoffice.ODPackage.RootElement.META;
18
import static org.openconcerto.openoffice.ODPackage.RootElement.STYLES;
18
import static org.openconcerto.openoffice.ODPackage.RootElement.STYLES;
19
import org.openconcerto.openoffice.spreadsheet.SpreadSheet;
19
import org.openconcerto.openoffice.spreadsheet.SpreadSheet;
20
import org.openconcerto.openoffice.text.TextDocument;
20
import org.openconcerto.openoffice.text.TextDocument;
21
import org.openconcerto.utils.CollectionMap;
-
 
22
import org.openconcerto.utils.CopyUtils;
21
import org.openconcerto.utils.CopyUtils;
23
import org.openconcerto.utils.ExceptionUtils;
22
import org.openconcerto.utils.ExceptionUtils;
24
import org.openconcerto.utils.FileUtils;
23
import org.openconcerto.utils.FileUtils;
25
import org.openconcerto.utils.ProductInfo;
24
import org.openconcerto.utils.ProductInfo;
26
import org.openconcerto.utils.PropertiesUtils;
25
import org.openconcerto.utils.PropertiesUtils;
-
 
26
import org.openconcerto.utils.SetMap;
27
import org.openconcerto.utils.StreamUtils;
27
import org.openconcerto.utils.StreamUtils;
28
import org.openconcerto.utils.StringInputStream;
28
import org.openconcerto.utils.StringInputStream;
29
import org.openconcerto.utils.StringUtils;
29
import org.openconcerto.utils.StringUtils;
30
import org.openconcerto.utils.Tuple2;
30
import org.openconcerto.utils.Tuple2;
31
import org.openconcerto.utils.Tuple3;
31
import org.openconcerto.utils.Tuple3;
Line 61... Line 61...
61
import java.util.Properties;
61
import java.util.Properties;
62
import java.util.Set;
62
import java.util.Set;
63
import java.util.zip.ZipEntry;
63
import java.util.zip.ZipEntry;
64
 
64
 
65
import net.jcip.annotations.GuardedBy;
65
import net.jcip.annotations.GuardedBy;
66
import net.jcip.annotations.Immutable;
-
 
67
 
66
 
68
import org.jdom.Attribute;
67
import org.jdom.Attribute;
69
import org.jdom.DocType;
68
import org.jdom.DocType;
70
import org.jdom.Document;
69
import org.jdom.Document;
71
import org.jdom.Element;
70
import org.jdom.Element;
Line 115... Line 114...
115
    /**
114
    /**
116
     * Root element of an OpenDocument document. See section 22.2.1 of v1.2-part1-cd04.
115
     * Root element of an OpenDocument document. See section 22.2.1 of v1.2-part1-cd04.
117
     * 
116
     * 
118
     * @author Sylvain CUAZ
117
     * @author Sylvain CUAZ
119
     */
118
     */
-
 
119
    // full name needed for javac 1.6.0_45
120
    @Immutable
120
    @net.jcip.annotations.Immutable
121
    public static enum RootElement {
121
    public static enum RootElement {
122
        /** Contains the entire document, see 3.1.2 of OpenDocument-v1.2-part1-cd04 */
122
        /** Contains the entire document, see 3.1.2 of OpenDocument-v1.2-part1-cd04 */
123
        SINGLE_CONTENT("office", "document", null),
123
        SINGLE_CONTENT("office", "document", null),
124
        /** Document content and automatic styles used in the content, see 3.1.3.2 */
124
        /** Document content and automatic styles used in the content, see 3.1.3.2 */
125
        CONTENT("office", "document-content", "content.xml"),
125
        CONTENT("office", "document-content", "content.xml"),
Line 270... Line 270...
270
        }
270
        }
271
    }
271
    }
272
 
272
 
273
    private static final int mimetypeZipEndOffset = 250;
273
    private static final int mimetypeZipEndOffset = 250;
274
 
274
 
275
    // ATTN ins is *not* always closed
275
    // ATTN ins is *not* closed if f != null
276
    private static ODPackage create(final File f, InputStream ins, final String name) throws IOException {
276
    private static ODPackage create(final File f, InputStream ins, final String name) throws IOException {
277
        // first use extension
277
        // first use extension
278
        final Tuple2<ContentTypeVersioned, Boolean> fromExt = name != null ? ContentTypeVersioned.fromExtension(FileUtils.getExtension(name)) : Tuple2.<ContentTypeVersioned, Boolean> nullInstance();
278
        final Tuple2<ContentTypeVersioned, Boolean> fromExt = name != null ? ContentTypeVersioned.fromExtension(FileUtils.getExtension(name)) : Tuple2.<ContentTypeVersioned, Boolean> nullInstance();
279
        ContentTypeVersioned contentType = fromExt.get0();
279
        ContentTypeVersioned contentType = fromExt.get0();
280
        Boolean flat = fromExt.get1();
280
        Boolean flat = fromExt.get1();
Line 315... Line 315...
315
        assert contentType == null || contentType == res.getContentType();
315
        assert contentType == null || contentType == res.getContentType();
316
        return res;
316
        return res;
317
    }
317
    }
318
 
318
 
319
    private static ContentTypeVersioned getType(final InputStream in) throws IOException {
319
    private static ContentTypeVersioned getType(final InputStream in) throws IOException {
-
 
320
        // don't want to close underlying stream
-
 
321
        @SuppressWarnings("resource")
320
        final DataInputStream ins = new DataInputStream(in, true);
322
        final DataInputStream ins = new DataInputStream(in, true);
321
        if (ins.read() != 'P' || ins.read() != 'K')
323
        if (ins.read() != 'P' || ins.read() != 'K')
322
            return null;
324
            return null;
323
        if (ins.skip(16) != 16)
325
        if (ins.skip(16) != 16)
324
            return null;
326
            return null;
Line 581... Line 583...
581
     * 
583
     * 
582
     * @return all problems indexed by package entry names, i.e. empty if all OK, <code>null</code>
584
     * @return all problems indexed by package entry names, i.e. empty if all OK, <code>null</code>
583
     *         if validation couldn't occur.
585
     *         if validation couldn't occur.
584
     */
586
     */
585
    public final Map<String, String> validateSubDocuments() {
587
    public final Map<String, String> validateSubDocuments() {
586
        return this.validateSubDocuments(true);
588
        return this.validateSubDocuments(true, true);
587
    }
589
    }
588
 
590
 
589
    public final Map<String, String> validateSubDocuments(final boolean allowChangeToValidate) {
591
    public final Map<String, String> validateSubDocuments(final boolean allowChangeToValidate, final boolean ignoreForeign) {
590
        final OOXML ooxml = this.getFormatVersion().getXML();
592
        final OOXML ooxml = this.getFormatVersion().getXML();
591
        if (!ooxml.canValidate())
593
        if (!ooxml.canValidate())
592
            return null;
594
            return null;
593
        final Map<String, String> res = new HashMap<String, String>();
595
        final Map<String, String> res = new HashMap<String, String>();
594
        for (final String s : subdocNames) {
596
        for (final String s : subdocNames) {
Line 598... Line 600...
598
                    // OpenOffice do not generate DocType declaration
600
                    // OpenOffice do not generate DocType declaration
599
                    final DocType docType = RootElement.fromDocument(doc).createDocType(ooxml.getVersion());
601
                    final DocType docType = RootElement.fromDocument(doc).createDocType(ooxml.getVersion());
600
                    if (docType != null && doc.getDocType() == null)
602
                    if (docType != null && doc.getDocType() == null)
601
                        doc.setDocType(docType);
603
                        doc.setDocType(docType);
602
                }
604
                }
603
                final String valid = ooxml.getValidator(doc).isValid();
605
                final String valid = ooxml.getValidator(doc, ignoreForeign).isValid();
604
                if (valid != null)
606
                if (valid != null)
605
                    res.put(s, valid);
607
                    res.put(s, valid);
606
            }
608
            }
607
        }
609
        }
608
        final String valid = ooxml.getValidator(this.createManifest().getDocument()).isValid();
610
        final String valid = ooxml.getValidator(this.createManifest().getDocument(), ignoreForeign).isValid();
609
        if (valid != null)
611
        if (valid != null)
610
            res.put(Manifest.ENTRY_NAME, valid);
612
            res.put(Manifest.ENTRY_NAME, valid);
611
        return res;
613
        return res;
612
    }
614
    }
613
 
615
 
Line 914... Line 916...
914
        return checkStyles(contentDoc, styles);
916
        return checkStyles(contentDoc, styles);
915
    }
917
    }
916
 
918
 
917
    static private final String checkStyles(ODXMLDocument doc, Element styles) {
919
    static private final String checkStyles(ODXMLDocument doc, Element styles) {
918
        try {
920
        try {
919
            final CollectionMap<String, String> stylesNames = getStylesNames(doc, styles, doc.getChild("automatic-styles"));
921
            final SetMap<String, String> stylesNames = getStylesNames(doc, styles, doc.getChild("automatic-styles"));
920
            // text:style-name : text:p, text:span
922
            // text:style-name : text:p, text:span
921
            // table:style-name : table:table, table:row, table:column, table:cell
923
            // table:style-name : table:table, table:row, table:column, table:cell
922
            // draw:style-name : draw:text-box
924
            // draw:style-name : draw:text-box
923
            // style:data-style-name : <style:style style:family="table-cell">
925
            // style:data-style-name : <style:style style:family="table-cell">
924
            // TODO check by family
926
            // TODO check by family
925
            final Set<String> names = new HashSet<String>(stylesNames.values());
927
            final Set<String> names = new HashSet<String>(stylesNames.allValues());
926
            final Iterator attrs = doc.getXPath(".//@text:style-name | .//@table:style-name | .//@draw:style-name | .//@style:data-style-name | .//@style:list-style-name")
928
            final Iterator attrs = doc.getXPath(".//@text:style-name | .//@table:style-name | .//@draw:style-name | .//@style:data-style-name | .//@style:list-style-name")
927
                    .selectNodes(doc.getDocument()).iterator();
929
                    .selectNodes(doc.getDocument()).iterator();
928
            while (attrs.hasNext()) {
930
            while (attrs.hasNext()) {
929
                final Attribute attr = (Attribute) attrs.next();
931
                final Attribute attr = (Attribute) attrs.next();
930
                if (!names.contains(attr.getValue()))
932
                if (!names.contains(attr.getValue()))
Line 937... Line 939...
937
            return ExceptionUtils.getStackTrace(e);
939
            return ExceptionUtils.getStackTrace(e);
938
        }
940
        }
939
        return null;
941
        return null;
940
    }
942
    }
941
 
943
 
942
    static private final CollectionMap<String, String> getStylesNames(final ODXMLDocument doc, final Element styles, final Element autoStyles) throws IllegalStateException {
944
    static private final SetMap<String, String> getStylesNames(final ODXMLDocument doc, final Element styles, final Element autoStyles) throws IllegalStateException {
943
        // section 14.1 § Style Name : style:family + style:name is unique
945
        // section 14.1 § Style Name : style:family + style:name is unique
944
        final CollectionMap<String, String> res = new CollectionMap<String, String>(HashSet.class);
946
        final SetMap<String, String> res = new SetMap<String, String>();
945
 
947
 
946
        final List<Element> nodes = new ArrayList<Element>();
948
        final List<Element> nodes = new ArrayList<Element>();
947
        if (styles != null)
949
        if (styles != null)
948
            nodes.add(styles);
950
            nodes.add(styles);
949
        if (autoStyles != null)
951
        if (autoStyles != null)
Line 956... Line 958...
956
                    final Attribute attr = (Attribute) iter.next();
958
                    final Attribute attr = (Attribute) iter.next();
957
                    final String styleName = attr.getValue();
959
                    final String styleName = attr.getValue();
958
                    final String family = attr.getParent().getAttributeValue("family", attr.getNamespace());
960
                    final String family = attr.getParent().getAttributeValue("family", attr.getNamespace());
959
                    if (res.getNonNull(family).contains(styleName))
961
                    if (res.getNonNull(family).contains(styleName))
960
                        throw new IllegalStateException("duplicate style in " + family + " :  " + styleName);
962
                        throw new IllegalStateException("duplicate style in " + family + " :  " + styleName);
961
                    res.put(family, styleName);
963
                    res.add(family, styleName);
962
                }
964
                }
963
            }
965
            }
964
            {
966
            {
965
                final List<String> dataStyles = Arrays.asList("number-style", "currency-style", "percentage-style", "date-style", "time-style", "boolean-style", "text-style");
967
                final List<String> dataStyles = Arrays.asList("number-style", "currency-style", "percentage-style", "date-style", "time-style", "boolean-style", "text-style");
966
                final String xpDataStyles = org.openconcerto.utils.CollectionUtils.join(dataStyles, " | ", new ITransformer<String, String>() {
968
                final String xpDataStyles = org.openconcerto.utils.CollectionUtils.join(dataStyles, " | ", new ITransformer<String, String>() {
Line 970... Line 972...
970
                    }
972
                    }
971
                });
973
                });
972
                final Iterator listIter = doc.getXPath("./text:list-style | " + xpDataStyles).selectNodes(nodes).iterator();
974
                final Iterator listIter = doc.getXPath("./text:list-style | " + xpDataStyles).selectNodes(nodes).iterator();
973
                while (listIter.hasNext()) {
975
                while (listIter.hasNext()) {
974
                    final Element elem = (Element) listIter.next();
976
                    final Element elem = (Element) listIter.next();
975
                    res.put(elem.getQualifiedName(), elem.getAttributeValue("name", doc.getVersion().getSTYLE()));
977
                    res.add(elem.getQualifiedName(), elem.getAttributeValue("name", doc.getVersion().getSTYLE()));
976
                }
978
                }
977
            }
979
            }
978
        } catch (JDOMException e) {
980
        } catch (JDOMException e) {
979
            throw new IllegalStateException(e);
981
            throw new IllegalStateException(e);
980
        }
982
        }
Line 1155... Line 1157...
1155
        }
1157
        }
1156
 
1158
 
1157
        return manifest;
1159
        return manifest;
1158
    }
1160
    }
1159
 
1161
 
-
 
1162
    /**
-
 
1163
     * Save this package to the passed stream.
-
 
1164
     * 
-
 
1165
     * @param out the stream to write to, it will be closed.
-
 
1166
     * @throws IOException if an error occurs.
-
 
1167
     */
1160
    public final void save(OutputStream out) throws IOException {
1168
    public final void save(OutputStream out) throws IOException {
1161
        // from 22.2.1 (D1.2)
1169
        // from 22.2.1 (D1.2)
1162
        if (this.isSingle()) {
1170
        if (this.isSingle()) {
1163
            // assert we can use this copy constructor (instead of the slower CopyUtils)
1171
            // assert we can use this copy constructor (instead of the slower CopyUtils)
1164
            assert this.getClass() == ODPackage.class;
1172
            assert this.getClass() == ODPackage.class;