ODFTOOLKIT-479 - Adding Java Microbenchmark Harness (JHM) performance tests - just a not running draft yet
diff --git a/benchmark/pom.xml b/benchmark/pom.xml
new file mode 100644
index 0000000..46086a7
--- /dev/null
+++ b/benchmark/pom.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License. -->
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+    <artifactId>odftoolkit</artifactId>
+    <groupId>org.apache.odftoolkit</groupId>
+    <version>0.7.0-incubating-SNAPSHOT</version>
+  </parent>
+
+    <groupId>org.apache.odftoolkit</groupId>
+    <artifactId>benchmark</artifactId>
+    <version>1.0</version>
+    <packaging>jar</packaging>
+
+    <name>JMH benchmark sample: Java</name>
+
+    <!--
+       This is the demo/sample template build script for building Java benchmarks with JMH.
+       Edit as needed.
+    -->
+
+    <dependencies>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-core</artifactId>
+            <version>${jmh.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-generator-annprocess</artifactId>
+            <version>${jmh.version}</version>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>${project.groupId}</groupId>
+			<artifactId>odfdom-java</artifactId>
+			<version>0.9.0-incubating-SNAPSHOT</version>
+		</dependency>        
+    </dependencies>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+        <!--
+            JMH version to use with this project.
+          -->
+        <jmh.version>1.19</jmh.version>
+
+        <!--
+            Java source/target to use for compilation.
+          -->
+        <javac.target>1.8</javac.target>
+
+        <!--
+            Name of the benchmark Uber-JAR to generate.
+          -->
+        <uberjar.name>benchmarks</uberjar.name>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <compilerVersion>${javac.target}</compilerVersion>
+                    <source>${javac.target}</source>
+                    <target>${javac.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <finalName>${uberjar.name}</finalName>
+                            <transformers>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.openjdk.jmh.Main</mainClass>
+                                </transformer>
+                            </transformers>
+                            <filters>
+                                <filter>
+                                    <!--
+                                        Shading signed JARs will fail without this.
+                                        http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
+                                    -->
+                                    <artifact>*:*</artifact>
+                                    <excludes>
+                                        <exclude>META-INF/*.SF</exclude>
+                                        <exclude>META-INF/*.DSA</exclude>
+                                        <exclude>META-INF/*.RSA</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-deploy-plugin</artifactId>
+                    <version>2.8.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>2.5.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>2.9.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>2.6</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-site-plugin</artifactId>
+                    <version>3.3</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <version>2.2.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.17</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+</project>
diff --git a/benchmark/src/main/java/org/apache/odftoolkit/ODFDOMBenchmark.java b/benchmark/src/main/java/org/apache/odftoolkit/ODFDOMBenchmark.java
new file mode 100644
index 0000000..cd5183c
--- /dev/null
+++ b/benchmark/src/main/java/org/apache/odftoolkit/ODFDOMBenchmark.java
@@ -0,0 +1,402 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.odftoolkit;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.CodeSource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import org.odftoolkit.odfdom.doc.OdfDocument;
+import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
+import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
+import org.odftoolkit.odfdom.dom.element.office.OfficeSpreadsheetElement;
+import org.odftoolkit.odfdom.dom.element.table.TableTableCellElement;
+import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
+import org.odftoolkit.odfdom.dom.element.table.TableTableRowElement;
+import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph;
+import org.odftoolkit.odfdom.pkg.OdfFileDom;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.w3c.dom.NodeList;
+
+/**
+ * See JIRA issue https://issues.apache.org/jira/browse/ODFTOOLKIT-479
+ * for details!
+ */
+public class ODFDOMBenchmark {
+
+    private static final Logger LOG = Logger.getLogger(ODFDOMBenchmark.class.getName());
+    private static final String TEST_FILE_DIR_NAME = "performance";
+    public ODFDOMBenchmark() {
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.Throughput)
+    @Fork(3)
+    @Measurement(iterations = 3)
+    @Warmup(iterations = 1)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    public OdfFileDom testPerformance(ExecutionPlan plan) {
+        OdfFileDom dom = null;
+        try {
+            long start, end;
+            OdfDocument doc = null;
+
+            if (plan.testFileStreams == null) {
+                return dom;
+            }
+            LOG.info("Starting the test!");
+            for (int i = 0; i < plan.count; i++) {
+                int j = -1;
+                for (String filename : plan.testFileStreams.keySet()) {
+                	LOG.info("Starting reading " + filename);
+                    j++;
+                    start = System.currentTimeMillis();
+                    doc = OdfDocument.loadDocument(plan.testFileStreams.get(filename));
+                    end = System.currentTimeMillis();
+                    plan.totalLoadTimeForEach[j] += end - start;
+                    plan.totalTime[0] += end - start;
+                    if (i == 0) {
+                        System.gc();
+                        plan.memoryfootprint[3 * j] = Runtime.getRuntime().totalMemory()
+                                - Runtime.getRuntime().freeMemory();
+                    }
+                    LOG.info("Starting parsing!");
+                    start = System.currentTimeMillis();
+                    dom = doc.getContentDom();
+                    end = System.currentTimeMillis();
+                    LOG.info("Stop parsing!");
+                    plan.totalParseTimeForEach[j] += end - start;
+                    plan.totalTime[1] += end - start;
+                    if (i == 0) {
+                        System.gc();
+                        plan.memoryfootprint[3 * j + 1] = Runtime.getRuntime().totalMemory()
+                                - Runtime.getRuntime().freeMemory();
+                    }
+
+                    start = System.currentTimeMillis();
+                    doc.save(plan.rootPath + File.separator + filename);
+                    end = System.currentTimeMillis();
+                    plan.totalSaveTimeForEach[j] += end - start;
+                    plan.totalTime[2] += end - start;
+
+                    doc = null;
+                    dom = null;
+                    if (i == 0) {
+                        System.gc();
+                        plan.memoryfootprint[3 * j + 2] = Runtime.getRuntime().totalMemory()
+                                - Runtime.getRuntime().freeMemory();
+                    }
+                }
+            }
+
+            for (int i = 0; i < 3; i++) {
+                plan.totalTime[i] = plan.totalTime[i] / plan.count;
+            }
+
+            for (int i = 0; i < plan.testFileStreams.size(); i++) {
+                plan.totalLoadTimeForEach[i] = plan.totalLoadTimeForEach[i] / plan.count;
+                plan.totalParseTimeForEach[i] = plan.totalParseTimeForEach[i] / plan.count;
+                plan.totalSaveTimeForEach[i] = plan.totalSaveTimeForEach[i] / plan.count;
+            }
+
+        } catch (Exception e) {
+            Logger.getLogger(ODFDOMBenchmark.class.getName()).log(java.util.logging.Level.SEVERE, null, e);
+
+        }
+        return dom;
+    }
+
+    @State(Scope.Benchmark)
+    public static class ExecutionPlan {
+
+        public double[] totalTime = new double[3];
+        public double[] totalLoadTimeForEach = null;
+        public double[] totalSaveTimeForEach = null;
+        public double[] totalParseTimeForEach = null;
+        public double[] memoryfootprint = null;
+        public String time_spreadsheet = null;
+        public String memory_spreadsheet = null;
+        public String reportFileFolder = null;
+        public int count;
+        public String rootPath;
+        public URL jarLocation;
+        public Map<String, InputStream> testFileStreams;
+        public String outputPath;
+
+        @Setup(Level.Iteration)
+        public void setUp() {
+
+            CodeSource src = ODFDOMBenchmark.class.getProtectionDomain().getCodeSource();
+            if (src != null) {
+                jarLocation = src.getLocation();
+            }else{
+                LOG.severe("Could not locate JAR file!");
+            }
+
+            // jar file URL
+            rootPath = jarLocation.toExternalForm();
+            // directory containing the JAR
+            rootPath = rootPath.substring(6, rootPath.lastIndexOf("/"));
+
+            outputPath = rootPath + File.separatorChar + TEST_FILE_DIR_NAME;
+            new File(outputPath).mkdir();
+            String executeTimesTest = System.getProperty("executetimes");
+            if (executeTimesTest != null) {
+                count = Integer.parseInt(executeTimesTest);
+            } else {
+                count = 1;
+            }
+            reportFileFolder = getOutputPath() + File.separatorChar;
+            memory_spreadsheet = reportFileFolder + "memorylog.ods";
+            time_spreadsheet = reportFileFolder + "timelog.ods";
+
+            testFileStreams = new HashMap<String, InputStream>();
+            readFileList(jarLocation);
+            if (testFileStreams == null) {
+                LOG.severe("No test files found!");
+                return;
+            }
+
+            totalTime[0] = 0;
+            totalTime[1] = 0;
+            totalTime[2] = 0;
+
+            totalLoadTimeForEach = new double[testFileStreams.size()];
+            totalSaveTimeForEach = new double[testFileStreams.size()];
+            totalParseTimeForEach = new double[testFileStreams.size()];
+            memoryfootprint = new double[testFileStreams.size() * 3];
+
+            for (int i = 0; i < testFileStreams.size(); i++) {
+                totalLoadTimeForEach[i] = 0;
+                totalSaveTimeForEach[i] = 0;
+                totalParseTimeForEach[i] = 0;
+                memoryfootprint[3 * i] = 0;
+                memoryfootprint[3 * i + 1] = 0;
+                memoryfootprint[3 * i + 2] = 0;
+            }
+        }
+
+        @TearDown(Level.Iteration)
+        public void writeToLog() throws Exception {
+            FileInputStream timefile, memoryfile;
+            OdfDocument timedoc, memorydoc;
+
+            if (testFileStreams == null) {
+                return;
+            }
+
+            try {
+                timefile = new FileInputStream(time_spreadsheet);
+                timedoc = OdfDocument.loadDocument(timefile);
+            } catch (FileNotFoundException e) {
+                //Create an empty spreadsheet
+                timedoc = OdfSpreadsheetDocument.newSpreadsheetDocument();
+                OfficeSpreadsheetElement spreadsheet = (OfficeSpreadsheetElement) timedoc.getContentDom().getElementsByTagNameNS(
+                        OdfDocumentNamespace.OFFICE.getUri(), "spreadsheet").item(0);
+                spreadsheet.removeChild(spreadsheet.getFirstChild());
+            }
+
+            try {
+                memoryfile = new FileInputStream(memory_spreadsheet);
+                memorydoc = OdfDocument.loadDocument(memoryfile);
+            } catch (FileNotFoundException e) {
+                //Create an empty spreadsheet
+                memorydoc = OdfSpreadsheetDocument.newSpreadsheetDocument();
+                OfficeSpreadsheetElement spreadsheet = (OfficeSpreadsheetElement) memorydoc.getContentDom().getElementsByTagNameNS(
+                        OdfDocumentNamespace.OFFICE.getUri(), "spreadsheet").item(0);
+                spreadsheet.removeChild(spreadsheet.getFirstChild());
+            }
+
+            String[] summaryName = new String[]{"Load All Documents", "Parse All Documents", "Save All Documents"};
+            updateTableCells(timedoc, "Summary", totalTime, summaryName);
+            updateTableCells(timedoc, "Load ODF", totalLoadTimeForEach, testFileStreams.keySet().toArray(new String[0]));
+            updateTableCells(timedoc, "Parse ODF", totalParseTimeForEach, testFileStreams.keySet().toArray(new String[0]));
+            updateTableCells(timedoc, "Save ODF", totalSaveTimeForEach, testFileStreams.keySet().toArray(new String[0]));
+
+            String[] memorylabel = new String[testFileStreams.size() * 3];
+            int i = -1;
+            for (String testFileName : testFileStreams.keySet()) {
+                i++;
+
+                memorylabel[3 * i] = "load " + testFileName;
+                memorylabel[3 * i + 1] = "parse " + testFileName;
+                memorylabel[3 * i + 2] = "save " + testFileName;
+            }
+            updateTableCells(memorydoc, "Memory footprint", memoryfootprint, memorylabel);
+
+            timedoc.save(time_spreadsheet);
+            LOG.log(java.util.logging.Level.INFO, "[PerformaceTest] Test results are written to {0}", time_spreadsheet);
+            memorydoc.save(memory_spreadsheet);
+            LOG.log(java.util.logging.Level.INFO, "[PerformaceTest] Test results are written to {0}", memory_spreadsheet);
+        }
+
+        private String getOutputPath() {
+            String path = null;
+            File outputpath = new File(rootPath, "performance-reports");
+            if (!outputpath.exists()) {
+                outputpath.mkdir();
+            }
+            path = outputpath.getPath();
+            return path;
+        }
+
+        private void readFileList(URL jar) {
+            try {
+                LOG.log(java.util.logging.Level.INFO, "[PerformaceTest] Reading test documents from JAR {0}", jar);
+                ZipInputStream zip = null;
+                ZipFile zf;
+                File jarFile = new File(jar.toExternalForm().substring(6).replace('/', File.separatorChar));
+                zf = new ZipFile(jarFile);
+                try {
+                    zip = new ZipInputStream(jar.openStream());
+                    while (true) {
+                        ZipEntry e = zip.getNextEntry();
+                        if (e == null) {
+                            break;
+                        }
+                        String name = e.getName();
+                        if (name.startsWith(TEST_FILE_DIR_NAME) && !e.isDirectory() && (name.endsWith("ods") || name.endsWith("odp") || name.endsWith("odt"))) {
+                            LOG.log(java.util.logging.Level.INFO, "[PerformaceTest] Reading test document {0}", name);
+                            testFileStreams.put(name, zf.getInputStream(zf.getEntry(name)));
+                        }
+                    }
+                } catch (IOException ex) {
+                    Logger.getLogger(ODFDOMBenchmark.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+                } finally {
+                    try {
+                        zip.close();
+                    } catch (IOException ex) {
+                        Logger.getLogger(ODFDOMBenchmark.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+                    }
+                }
+            } catch (IOException ex) {
+                Logger.getLogger(ODFDOMBenchmark.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+            }
+        }
+
+        private void updateTableCells(OdfDocument odfdoc, String tablename,
+                double[] values, String[] labels) {
+            int i = 0, j = 0;
+            TableTableRowElement td;
+            TableTableCellElement cell;
+            OdfFileDom dom;
+            NodeList tableList;
+            TableTableElement myTable;
+            NodeList lst;
+            OdfTextParagraph p;
+            OfficeSpreadsheetElement spreadsheet = null;
+
+            try {
+                dom = odfdoc.getContentDom();
+                tableList = dom.getElementsByTagNameNS(
+                        OdfDocumentNamespace.TABLE.getUri(), "table");
+                spreadsheet = (OfficeSpreadsheetElement) dom.getElementsByTagNameNS(
+                        OdfDocumentNamespace.OFFICE.getUri(), "spreadsheet").item(0);
+
+                i = 0;
+                if (tableList.getLength() > 0) {
+                    for (; i < tableList.getLength(); i++) {
+                        String currentname = ((TableTableElement) tableList.item(i)).getTableNameAttribute();
+                        if (currentname == null) {
+                            currentname = "";
+                        }
+                        if (currentname.equalsIgnoreCase(tablename)) {
+                            break;
+                        }
+                    }
+                }
+                if (i < tableList.getLength()) //table with the specific table name is found
+                {
+                    myTable = (TableTableElement) tableList.item(i);
+                } else { //table with the specific table name is not found. Create table
+                    myTable = dom.newOdfElement(TableTableElement.class);
+                    myTable.setTableNameAttribute(tablename);
+                    spreadsheet.appendChild(myTable);
+                }
+
+                lst = myTable.getElementsByTagNameNS(OdfDocumentNamespace.TABLE.getUri(), "table-row");
+                if (lst.getLength() == 0) { //the first table row is not existed. Create table row
+                    td = dom.newOdfElement(TableTableRowElement.class);
+                    cell = dom.newOdfElement(TableTableCellElement.class);
+                    p = dom.newOdfElement(OdfTextParagraph.class);
+                    if (tablename.startsWith("Memory")) {
+                        p.setTextContent("memory(b)");
+                    } else {
+                        p.setTextContent("time(ms)");
+                    }
+                    td.appendChild(cell);
+                    cell.appendChild(p);
+                    myTable.appendChild(td);
+                } else {
+                    td = (TableTableRowElement) lst.item(0); //the first table row is existed.
+                }
+                cell = dom.newOdfElement(TableTableCellElement.class);
+                td.appendChild(cell);
+                p = dom.newOdfElement(OdfTextParagraph.class);
+                cell.appendChild(p);
+
+                for (i = 1; i < values.length + 1; i++) {
+                    if (i < lst.getLength()) { //table row is existed
+                        td = (TableTableRowElement) lst.item(i);
+                    } else { //table row is not existed.
+                        td = dom.newOdfElement(TableTableRowElement.class);
+                        myTable.appendChild(td);
+                        //append first cell with labels
+                        cell = dom.newOdfElement(TableTableCellElement.class);
+                        td.appendChild(cell);
+                        p = dom.newOdfElement(OdfTextParagraph.class);
+                        p.setTextContent(labels[i]);
+                        cell.appendChild(p);
+                    }
+                    cell = dom.newOdfElement(TableTableCellElement.class);
+                    cell.setOfficeValueTypeAttribute("float");
+                    cell.setOfficeValueAttribute(new Double(values[j]));
+                    p = dom.newOdfElement(OdfTextParagraph.class);
+                    p.setTextContent(values[j] + "");
+                    cell.appendChild(p);
+                    td.appendChild(cell);
+                    j++;
+                }
+            } catch (Exception e) {
+                LOG.log(java.util.logging.Level.SEVERE, null, e);
+            }
+        }
+    }
+}
diff --git a/benchmark/src/main/resources/performance/Presentation1_INVALID.odp b/benchmark/src/main/resources/performance/Presentation1_INVALID.odp
new file mode 100644
index 0000000..5df2ea5
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation1_INVALID.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Presentation2.odp b/benchmark/src/main/resources/performance/Presentation2.odp
new file mode 100644
index 0000000..2c2a7df
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation2.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Presentation3.odp b/benchmark/src/main/resources/performance/Presentation3.odp
new file mode 100644
index 0000000..f3e3adc
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation3.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Presentation4.odp b/benchmark/src/main/resources/performance/Presentation4.odp
new file mode 100644
index 0000000..f32c7af
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation4.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Presentation5.odp b/benchmark/src/main/resources/performance/Presentation5.odp
new file mode 100644
index 0000000..e5b7588
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation5.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Presentation7.odp b/benchmark/src/main/resources/performance/Presentation7.odp
new file mode 100644
index 0000000..9002ac8
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Presentation7.odp
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Text1.odt b/benchmark/src/main/resources/performance/Text1.odt
new file mode 100644
index 0000000..4761107
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Text1.odt
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Text3.odt b/benchmark/src/main/resources/performance/Text3.odt
new file mode 100644
index 0000000..d72df2d
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Text3.odt
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Text4.odt b/benchmark/src/main/resources/performance/Text4.odt
new file mode 100644
index 0000000..15f208e
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Text4.odt
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Text6.odt b/benchmark/src/main/resources/performance/Text6.odt
new file mode 100644
index 0000000..61bd0d6
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Text6.odt
Binary files differ
diff --git a/benchmark/src/main/resources/performance/Text7.odt b/benchmark/src/main/resources/performance/Text7.odt
new file mode 100644
index 0000000..c691f63
--- /dev/null
+++ b/benchmark/src/main/resources/performance/Text7.odt
Binary files differ
diff --git a/benchmark/src/main/resources/performance/spreadsheet1.ods b/benchmark/src/main/resources/performance/spreadsheet1.ods
new file mode 100644
index 0000000..363bb89
--- /dev/null
+++ b/benchmark/src/main/resources/performance/spreadsheet1.ods
Binary files differ
diff --git a/benchmark/src/main/resources/performance/spreadsheet2.ods b/benchmark/src/main/resources/performance/spreadsheet2.ods
new file mode 100644
index 0000000..4876065
--- /dev/null
+++ b/benchmark/src/main/resources/performance/spreadsheet2.ods
Binary files differ
diff --git a/benchmark/src/main/resources/performance/spreadsheet3.ods b/benchmark/src/main/resources/performance/spreadsheet3.ods
new file mode 100644
index 0000000..60e984a
--- /dev/null
+++ b/benchmark/src/main/resources/performance/spreadsheet3.ods
Binary files differ
diff --git a/benchmark/src/main/resources/performance/spreadsheet4.ods b/benchmark/src/main/resources/performance/spreadsheet4.ods
new file mode 100644
index 0000000..a34f9ca
--- /dev/null
+++ b/benchmark/src/main/resources/performance/spreadsheet4.ods
Binary files differ
diff --git a/benchmark/src/main/resources/performance/spreadsheet5.ods b/benchmark/src/main/resources/performance/spreadsheet5.ods
new file mode 100644
index 0000000..fd4d56f
--- /dev/null
+++ b/benchmark/src/main/resources/performance/spreadsheet5.ods
Binary files differ
diff --git a/pom.xml b/pom.xml
index a20ea5a..c533260 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-
 <!--
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
@@ -110,7 +109,8 @@
         <module>odfdom</module>
         <module>validator</module>
         <module>simple</module>
-    </modules>
+        <module>benchmark</module>
+  </modules>
 
     <name>Apache ODF Toolkit</name>
     <description>
@@ -389,27 +389,27 @@
                                 <phase>prepare-package</phase>
                                 <configuration>
                                     <tasks>
-                                        <mkdir dir="${basedir}/target/${project.version}-bin" />
+                                        <mkdir dir="${basedir}/target/${project.version}-bin"/>
                                         <copy todir="${basedir}/target/${project.version}-bin" flatten="true">
                                               <fileset dir="${basedir}">
-                                                <include name="*.txt" />
-                                                <include name="KEYS" />
-                                                <include name="odfdom/target/*.jar" />
-                                                <include name="simple/target/*.jar" />
-                                                <include name="validator/target/*.?ar" />
-                                                <include name="xslt-runner/target/*.jar" />
-                                                <include name="xslt-runner-task/target/*.jar" />
-                                                <exclude name="**/target/**-javadoc.jar" />
-                                                <exclude name="**/target/**-sources.jar" />
-                                                <exclude name="**/target/**-jar-with-dependencies.jar" />
+                                                <include name="*.txt"/>
+                                                <include name="KEYS"/>
+                                                <include name="odfdom/target/*.jar"/>
+                                                <include name="simple/target/*.jar"/>
+                                                <include name="validator/target/*.?ar"/>
+                                                <include name="xslt-runner/target/*.jar"/>
+                                                <include name="xslt-runner-task/target/*.jar"/>
+                                                <exclude name="**/target/**-javadoc.jar"/>
+                                                <exclude name="**/target/**-sources.jar"/>
+                                                <exclude name="**/target/**-jar-with-dependencies.jar"/>
                                               </fileset>
                                         </copy>
-                                        <mkdir dir="${basedir}/target/${project.version}-docs" />
+                                        <mkdir dir="${basedir}/target/${project.version}-docs"/>
                                         <copy todir="${basedir}/target/${project.version}-docs" flatten="true">
                                             <fileset dir="${basedir}">
-                                                <include name="*.txt" />
-                                                <include name="KEYS" />
-                                                <include name="**/target/*-javadoc.jar" />
+                                                <include name="*.txt"/>
+                                                <include name="KEYS"/>
+                                                <include name="**/target/*-javadoc.jar"/>
                                             </fileset>
                                         </copy>
                                         </tasks>
@@ -425,32 +425,32 @@
                                     <tasks>
                                         <checksum algorithm="MD5" fileext=".md5">
                                               <fileset dir="${basedir}/target">
-                                                <include name="*.zip" />
-                                                <include name="*.tar.gz" />
-                                                <include name="*.tar.bz2" />
+                                                <include name="*.zip"/>
+                                                <include name="*.tar.gz"/>
+                                                <include name="*.tar.bz2"/>
                                               </fileset>
                                         </checksum>
                                         <checksum algorithm="SHA-512" fileext=".sha">
                                               <fileset dir="${basedir}/target">
-                                                <include name="*.zip" />
-                                                <include name="*.tar.gz" />
-                                                <include name="*.tar.bz2" />
+                                                <include name="*.zip"/>
+                                                <include name="*.tar.gz"/>
+                                                <include name="*.tar.bz2"/>
                                               </fileset>
                                         </checksum>
-                                        <checksum file="target/odftoolkit-${project.version}-src.zip" algorithm="SHA-512" property="checksum" />
+                                        <checksum file="target/odftoolkit-${project.version}-src.zip" algorithm="SHA-512" property="checksum"/>
                                         <copy todir="${basedir}/target/release/${project.version}/">
                                             <fileset dir="${basedir}/target">
-                                                <include name="*-source-release.*" />
+                                                <include name="*-source-release.*"/>
                                             </fileset>
                                         </copy>
                                         <copy todir="${basedir}/target/release/${project.version}/binaries">
                                             <fileset dir="${basedir}/target">
-                                                <include name="*-bin.*" />
+                                                <include name="*-bin.*"/>
                                             </fileset>
                                         </copy>
                                         <copy todir="${basedir}/target/release/${project.version}/docs">
                                             <fileset dir="${basedir}/target">
-                                                <include name="*-doc.*" />
+                                                <include name="*-doc.*"/>
                                             </fileset>
                                         </copy>
                                         <echo file="${basedir}/target/vote.txt">
@@ -475,12 +475,12 @@
                                             [ ] +1 Release this package as Apache ODF Toolkit ${project.version}
                                             [ ] -1 Do not release this package because...${line.separator}
                                         </echo>
-                                        <echo />
+                                        <echo/>
                                         <echo>
                                             The release candidate has been prepared in:    ${basedir}/target/${project.version}
 											A release vote template has been generated for you:    file://${basedir}/target/vote.txt
 										</echo>
-										<echo />
+										<echo/>
 									</tasks>
 								</configuration>
 							</execution>
@@ -515,4 +515,4 @@
 			</build>
 		</profile>
 	</profiles>
-</project>
+</project>
\ No newline at end of file