diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 7f78832c0..b5af81686 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -152,6 +152,7 @@ org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
@@ -197,6 +198,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
@@ -244,6 +246,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=inser
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
@@ -321,6 +324,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do n
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
index a38e1bfcf..4ad8c933c 100644
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -1,12 +1,75 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_Apache POI
+cleanup_settings_version=2
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
formatter_profile=_Apache POI
formatter_settings_version=12
org.eclipse.jdt.ui.exception.name=e
org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
org.eclipse.jdt.ui.javadoc=false
org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=10
org.eclipse.jdt.ui.overrideannotation=false
+org.eclipse.jdt.ui.staticondemandthreshold=10
org.eclipse.jdt.ui.text.custom_code_templates=/**\n * @return the ${bare_field_name}\n *//**\n * @param ${param} the ${bare_field_name} to set\n *//**\n *\n * ${tags}\n *//* \=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\n Licensed to the Apache Software Foundation (ASF) under one or more\n contributor license agreements. See the NOTICE file distributed with\n this work for additional information regarding copyright ownership.\n The ASF licenses this file to You under the Apache License, Version 2.0\n (the "License"); you may not use this file except in compliance with\n the License. You may obtain a copy of the License at\n\n http\://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an "AS IS" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\= *//**\n *\n * ${tags}\n *//**\n * \n *//**\n *\n * ${tags}\n *//* (non-Javadoc)\n * ${see_to_overridden}\n *//**\n * ${tags}\n * ${see_to_target}\n */${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}\n\n\n\n// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();// ${todo} Auto-generated method stub\n${body_statement}${body_statement}\n// ${todo} Auto-generated constructor stubreturn ${field};${field} \= ${param};
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
@@ -21,10 +84,12 @@ sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=true
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
@@ -40,6 +105,7 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
sp_cleanup.remove_trailing_whitespaces=false
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
@@ -53,10 +119,13 @@ sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_blocks=true
sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/.settings/org.moreunit.prefs b/.settings/org.moreunit.prefs
new file mode 100644
index 000000000..659afaf8c
--- /dev/null
+++ b/.settings/org.moreunit.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.moreunit.preferences.version=2
+org.moreunit.unitsourcefolder=ApachePOI\:src/java\:ApachePOI\:src/testcases\#ApachePOI\:src/java\:ApachePOI\:src/ooxml/testcases\#ApachePOI\:src/java\:ApachePOI\:src/scratchpad/testcases\#ApachePOI\:src/java\:ApachePOI\:src/excelant/testcases\#ApachePOI\:src/java\:ApachePOI\:src/integrationtest
+org.moreunit.useprojectsettings=true
diff --git a/KEYS b/KEYS
index 340f8504d..6e9b6ca5d 100644
--- a/KEYS
+++ b/KEYS
@@ -1796,3 +1796,348 @@ qoiVaXWfFHwg8u4bSHunrzNja17GyaZHdCEmM9vFzlaqBkoLWCMwIcaKnX9stQJp
FZwpzgut7DanaPcCDk7LMBbntaJwRC72M0qcj16SUAdAuGt1yQ==
=0DjT
-----END PGP PUBLIC KEY BLOCK-----
+
+pub 4096R/B4812553 2014-02-26 [expires: 2019-02-25]
+uid David North
+uid David North (Oxford CompSoc)
+uid David North (ASF Committer ID)
+
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+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
+=keWk
+-----END PGP PUBLIC KEY BLOCK-----
+pub 4096R/27B9F635 2015-06-22
+uid Dominik Stadler
+sub 4096R/EF9D5EA6 2015-06-22
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+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
+kg==
+=rPGm
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/build.xml b/build.xml
index 9fa34a84e..d7b5482b4 100644
--- a/build.xml
+++ b/build.xml
@@ -47,8 +47,8 @@ under the License.
The Apache POI project Ant build.
-
-
+
+
@@ -56,7 +56,7 @@ under the License.
-
+
@@ -82,7 +82,11 @@ under the License.
-
+
+
+
@@ -175,8 +179,8 @@ under the License.
value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.6.0/xmlbeans-2.6.0.jar"/>
-
-
+
+
@@ -194,14 +198,14 @@ under the License.
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
-
+
@@ -281,7 +286,7 @@ under the License.
-
+
@@ -289,14 +294,14 @@ under the License.
-
+
-
+
@@ -331,7 +336,7 @@ under the License.
-
+
@@ -360,6 +365,8 @@ under the License.
- compile Compile all files from main, ooxml and scratchpad
- test Run all unit tests from main, ooxml and scratchpad
- jar Produce jar files
+ - jar-src Produce source-jar files
+ - assemble Produce the zipped distribution files
- site Generate all documentation (Requires Apache Forrest)
- dist Create a distribution (Requires Apache Forrest)
@@ -409,6 +416,7 @@ under the License.
+
@@ -417,9 +425,13 @@ under the License.
+
+
+
+
@@ -721,7 +733,7 @@ under the License.
-
+
@@ -976,7 +988,7 @@ under the License.
-
+
@@ -1280,7 +1292,7 @@ under the License.
description="Generates the API documentation">
@@ -1440,7 +1452,7 @@ under the License.
-
+
@@ -1508,12 +1520,12 @@ under the License.
-
+
@@ -1628,6 +1640,14 @@ under the License.
Use ${dist.dir}/multisign.sh to create md5 checksums and GPG signatures
+
+
+
+
+
+
+
+
@@ -1744,7 +1764,30 @@ under the License.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doap_POI.rdf b/doap_POI.rdf
index e0123c2a8..17dee9ff6 100644
--- a/doap_POI.rdf
+++ b/doap_POI.rdf
@@ -19,22 +19,56 @@
Java
+
+
+ Apache POI 3.12
+ 2015-05-11
+ 3.12
+
+
+
+
+ Apache POI 3.11
+ 2014-12-21
+ 3.11
+
+
+
+
+ Apache POI 3.10.1
+ 2014-08-18
+ 3.10.1
+
+
+
+
+ Apache POI 3.10
+ 2014-02-08
+ 3.10
+
+ Apache POI 3.92012-12-033.9
+
+ Apache POI 3.82012-03-263.8
+
+ Apache POI 3.72010-10-293.7
+
+ Apache POI 3.62009-12-14
diff --git a/legal/NOTICE b/legal/NOTICE
index e5aa5f5a7..be2eae70d 100644
--- a/legal/NOTICE
+++ b/legal/NOTICE
@@ -1,5 +1,5 @@
Apache POI
-Copyright 2003-2014 The Apache Software Foundation
+Copyright 2003-2015 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
diff --git a/osgi/pom.xml b/osgi/pom.xml
new file mode 100644
index 000000000..2849467a9
--- /dev/null
+++ b/osgi/pom.xml
@@ -0,0 +1,229 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache
+ apache
+ 10
+
+
+
+ org.apache.poi
+ poi-bundle
+ bundle
+ Apache POI OSGi bundle
+
+ OSGi bundle that contains Apache POI, and the dependencies.
+
+ http://poi.apache.org/
+ ${poi.version}
+
+
+
+ 1.6
+ 1.6
+ 4.4.0
+
+
+
+
+ ${project.groupId}
+ poi
+ ${poi.version}
+
+
+ ${project.groupId}
+ poi-scratchpad
+ ${poi.version}
+
+
+ ${project.groupId}
+ poi-ooxml
+ ${poi.version}
+
+
+
+
+ junit
+ junit
+ 4.12
+
+
+ org.ops4j.pax.exam
+ pax-exam-junit4
+ ${pax.exam.version}
+ test
+
+
+ org.ops4j.pax.exam
+ pax-exam-container-native
+ ${pax.exam.version}
+ test
+
+
+ org.apache.felix
+ org.apache.felix.framework
+ 4.6.0
+ test
+
+
+ org.ops4j.pax.exam
+ pax-exam-link-assembly
+ ${pax.exam.version}
+ test
+
+
+ org.ops4j.pax.url
+ pax-url-aether
+ 2.3.0
+ test
+
+
+ javax.inject
+ javax.inject
+ 1
+ test
+
+
+ org.osgi
+ org.osgi.core
+ 5.0.0
+ provided
+
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+
+ org.apache.poi.osgi.Activator
+
+
+ poi;inline=true,
+ poi-scratchpad;inline=true,
+ poi-ooxml;inline=true,
+ poi-ooxml-schemas,
+ xmlbeans
+
+ true
+ ${project.url}
+
+ org.apache.poi.*
+
+
+ !org.junit,
+ *,
+ org.apache.xmlbeans.impl.xpath.saxon;resolution:=optional,
+ org.apache.xmlbeans.impl.xquery.saxon;resolution:=optional,
+ org.bouncycastle.cert;resolution:=optional,
+ org.bouncycastle.cert.ocsp;resolution:=optional,
+ org.bouncycastle.cms.bc;resolution:=optional,
+ org.bouncycastle.cert.jcajce;resolution:=optional,
+ org.bouncycastle.operator;resolution:=optional,
+ org.bouncycastle.operator.bc;resolution:=optional,
+ org.bouncycastle.tsp;resolution:=optional,
+ org.openxmlformats.schemas.officeDocument.x2006.math;resolution:=optional,
+ org.openxmlformats.schemas.schemaLibrary.x2006.main;resolution:=optional,
+ schemasMicrosoftComOfficePowerpoint;resolution:=optional,
+ schemasMicrosoftComOfficeWord;resolution:=optional,
+
+
+
+
+
+ maven-compiler-plugin
+ 3.2
+
+
+ ${maven.compiler.target}
+
+
+
+
+
+
+
+ java6
+
+ [1.6,)
+
+
+
+
+ maven-assembly-plugin
+
+
+ pre-integration-test
+
+ single
+
+
+ test-bundles.xml
+ test
+ false
+
+
+
+
+
+ maven-failsafe-plugin
+ 2.10
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+ WARN
+
+
+
+
+
+
+
+
+
+
+ The Apache Software Founation
+ http://www.apache.org
+
+
+ http://svn.apache.org/viewvc/poi/trunk/osgi
+ scm:svn:http://svn.apache.org/repos/asf/poi/trunk/osgi
+ scm:svn:https://svn.apache.org/repos/asf/poi/trunk/osgi
+
+
diff --git a/osgi/src/main/java/org/apache/poi/osgi/Activator.java b/osgi/src/main/java/org/apache/poi/osgi/Activator.java
new file mode 100644
index 000000000..2f0212bd4
--- /dev/null
+++ b/osgi/src/main/java/org/apache/poi/osgi/Activator.java
@@ -0,0 +1,28 @@
+/* ====================================================================
+ 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.poi.osgi;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+ public void start(BundleContext context) throws Exception {
+ }
+ public void stop(BundleContext context) throws Exception {
+ }
+}
diff --git a/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java b/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java
new file mode 100644
index 000000000..738d96b99
--- /dev/null
+++ b/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java
@@ -0,0 +1,84 @@
+/* ====================================================================
+ 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.poi.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.bundle;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.options;
+
+import javax.inject.Inject;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Test to ensure that all our main formats can create, write
+ * and read back in, when running under OSGi
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerMethod.class)
+public class TestOSGiBundle {
+
+ private final File TARGET = new File("target");
+
+ @Inject
+ private BundleContext bc;
+
+ @Configuration
+ public Option[] configuration() throws IOException, URISyntaxException {
+ File base = new File(TARGET, "test-bundles");
+ return options(
+ junitBundles(),
+ bundle(new File(base, "poi-bundle.jar").toURI().toURL().toString()));
+ }
+
+ @Test
+ public void testHSSF() throws Exception {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet s = wb.createSheet("OSGi");
+ s.createRow(0).createCell(0).setCellValue("With OSGi");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ wb.write(baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+
+ wb = new HSSFWorkbook(bais);
+ assertEquals(1, wb.getNumberOfSheets());
+
+ s = wb.getSheet("OSGi");
+ assertEquals("With OSGi", s.getRow(0).getCell(0).toString());
+ }
+}
diff --git a/osgi/test-bundles.xml b/osgi/test-bundles.xml
new file mode 100644
index 000000000..11502761e
--- /dev/null
+++ b/osgi/test-bundles.xml
@@ -0,0 +1,34 @@
+
+
+ bundles
+
+ dir
+
+ false
+
+
+
+ ${artifact.artifactId}.jar
+
+ org.apache.poi:poi-bundle
+
+
+
+
diff --git a/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java b/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java
index bf6bcd1f8..8d1a0a9c8 100644
--- a/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java
+++ b/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java
@@ -93,12 +93,12 @@ public class ReadCustomPropertySets
out(" No. of sections: " + sectionCount);
/* Print the list of sections: */
- List sections = ps.getSections();
+ List sections = ps.getSections();
int nr = 0;
- for (Iterator i = sections.iterator(); i.hasNext();)
+ for (Iterator i = sections.iterator(); i.hasNext();)
{
/* Print a single section: */
- Section sec = (Section) i.next();
+ Section sec = i.next();
out(" Section " + nr++ + ":");
String s = hex(sec.getFormatID().getBytes());
s = s.substring(0, s.length() - 1);
diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java
index ff8a0b73c..d2141b050 100644
--- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java
+++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java
@@ -50,5 +50,7 @@ public class CreateCells {
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
+
+ wb.close();
}
}
diff --git a/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java b/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java
index d0ce7674e..dd1398b86 100644
--- a/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java
+++ b/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java
@@ -21,6 +21,8 @@ package org.apache.poi.ss.examples;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
+import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -31,10 +33,9 @@ import java.io.IOException;
* Excel Conditional Formatting -- Examples
*
*
- * Based on the code snippets from http://www.contextures.com/xlcondformat03.html
+ * Partly based on the code snippets from
+ * http://www.contextures.com/xlcondformat03.html
*
- *
- * @author Yegor Kozlov
*/
public class ConditionalFormats {
@@ -46,6 +47,7 @@ public class ConditionalFormats {
sameCell(wb.createSheet("Same Cell"));
multiCell(wb.createSheet("MultiCell"));
+ overlapping(wb.createSheet("Overlapping"));
errors(wb.createSheet("Errors"));
hideDupplicates(wb.createSheet("Hide Dups"));
formatDuplicates(wb.createSheet("Duplicates"));
@@ -53,6 +55,9 @@ public class ConditionalFormats {
expiry(wb.createSheet("Expiry"));
shadeAlt(wb.createSheet("Shade Alt"));
shadeBands(wb.createSheet("Shade Bands"));
+ iconSets(wb.createSheet("Icon Sets"));
+
+ // TODO Add colour scales, data bars etc, see bug #58130
// Write the output to a file
String file = "cf-poi.xls";
@@ -60,7 +65,7 @@ public class ConditionalFormats {
FileOutputStream out = new FileOutputStream(file);
wb.write(out);
out.close();
-
+ System.out.println("Generated: " + file);
}
/**
@@ -139,6 +144,71 @@ public class ConditionalFormats {
sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)");
}
+
+ /**
+ * Multiple conditional formatting rules can apply to
+ * one cell, some combining, some beating others.
+ * Done in order of the rules added to the
+ * SheetConditionalFormatting object
+ */
+ static void overlapping(Sheet sheet) {
+ for (int i=0; i<40; i++) {
+ int rn = i+1;
+ Row r = sheet.createRow(i);
+ r.createCell(0).setCellValue("This is row " + rn + " (" + i + ")");
+ String str = "";
+ if (rn%2 == 0) str = str + "even ";
+ if (rn%3 == 0) str = str + "x3 ";
+ if (rn%5 == 0) str = str + "x5 ";
+ if (rn%10 == 0) str = str + "x10 ";
+ if (str.length() == 0) str = "nothing special...";
+ r.createCell(1).setCellValue("It is " + str);
+ }
+ sheet.autoSizeColumn(0);
+ sheet.autoSizeColumn(1);
+
+ sheet.getRow(1).createCell(3).setCellValue("Even rows are blue");
+ sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background");
+ sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold");
+ sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)");
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Row divides by 10, red (will beat #1)
+ ConditionalFormattingRule rule1 =
+ sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0");
+ FontFormatting font1 = rule1.createFontFormatting();
+ font1.setFontColorIndex(IndexedColors.RED.index);
+
+ // Condition 2: Row is even, blue
+ ConditionalFormattingRule rule2 =
+ sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0");
+ FontFormatting font2 = rule2.createFontFormatting();
+ font2.setFontColorIndex(IndexedColors.BLUE.index);
+
+ // Condition 3: Row divides by 5, bold
+ ConditionalFormattingRule rule3 =
+ sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0");
+ FontFormatting font3 = rule3.createFontFormatting();
+ font3.setFontStyle(false, true);
+
+ // Condition 4: Row divides by 3, grey background
+ ConditionalFormattingRule rule4 =
+ sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0");
+ PatternFormatting fill4 = rule4.createPatternFormatting();
+ fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
+ fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ // Apply
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A1:F41")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+ sheetCF.addConditionalFormatting(regions, rule2);
+ sheetCF.addConditionalFormatting(regions, rule3);
+ sheetCF.addConditionalFormatting(regions, rule4);
+ }
/**
* Use Excel conditional formatting to check for errors,
@@ -346,4 +416,64 @@ public class ConditionalFormats {
sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows");
sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)");
}
+
+ /**
+ * Icon Sets / Multi-States allow you to have icons shown which vary
+ * based on the values, eg Red traffic light / Yellow traffic light /
+ * Green traffic light
+ */
+ static void iconSets(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("Icon Sets");
+ Row r = sheet.createRow(1);
+ r.createCell(0).setCellValue("Reds");
+ r.createCell(1).setCellValue(0);
+ r.createCell(2).setCellValue(0);
+ r.createCell(3).setCellValue(0);
+ r = sheet.createRow(2);
+ r.createCell(0).setCellValue("Yellows");
+ r.createCell(1).setCellValue(5);
+ r.createCell(2).setCellValue(5);
+ r.createCell(3).setCellValue(5);
+ r = sheet.createRow(3);
+ r.createCell(0).setCellValue("Greens");
+ r.createCell(1).setCellValue(10);
+ r.createCell(2).setCellValue(10);
+ r.createCell(3).setCellValue(10);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") };
+ ConditionalFormattingRule rule1 =
+ sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS);
+ IconMultiStateFormatting im1 = rule1.getMultiStateFormatting();
+ im1.getThresholds()[0].setRangeType(RangeType.MIN);
+ im1.getThresholds()[1].setRangeType(RangeType.PERCENT);
+ im1.getThresholds()[1].setValue(33d);
+ im1.getThresholds()[2].setRangeType(RangeType.MAX);
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") };
+ ConditionalFormattingRule rule2 =
+ sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS);
+ IconMultiStateFormatting im2 = rule1.getMultiStateFormatting();
+ im2.getThresholds()[0].setRangeType(RangeType.PERCENT);
+ im2.getThresholds()[0].setValue(0d);
+ im2.getThresholds()[1].setRangeType(RangeType.PERCENT);
+ im2.getThresholds()[1].setValue(33d);
+ im2.getThresholds()[2].setRangeType(RangeType.PERCENT);
+ im2.getThresholds()[2].setValue(67d);
+ sheetCF.addConditionalFormatting(regions, rule2);
+
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") };
+ ConditionalFormattingRule rule3 =
+ sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE);
+ IconMultiStateFormatting im3 = rule1.getMultiStateFormatting();
+ im3.setIconOnly(true);
+ im3.getThresholds()[0].setRangeType(RangeType.MIN);
+ im3.getThresholds()[1].setRangeType(RangeType.NUMBER);
+ im3.getThresholds()[1].setValue(3d);
+ im3.getThresholds()[2].setRangeType(RangeType.NUMBER);
+ im3.getThresholds()[2].setValue(7d);
+ sheetCF.addConditionalFormatting(regions, rule3);
+ }
}
diff --git a/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java b/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java
index b5480cf59..bcfb5dffe 100644
--- a/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java
+++ b/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java
@@ -289,7 +289,7 @@ public class ToHtml {
private void fontStyle(CellStyle style) {
Font font = wb.getFontAt(style.getFontIndex());
- if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_NORMAL)
+ if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_BOLD)
out.format(" font-weight: bold;%n");
if (font.getItalic())
out.format(" font-style: italic;%n");
@@ -309,8 +309,12 @@ public class ToHtml {
style = wb.getCellStyleAt((short) 0);
StringBuilder sb = new StringBuilder();
Formatter fmt = new Formatter(sb);
- fmt.format("style_%02x", style.getIndex());
- return fmt.toString();
+ try {
+ fmt.format("style_%02x", style.getIndex());
+ return fmt.toString();
+ } finally {
+ fmt.close();
+ }
}
private void styleOut(String attr, K key, Map mapping) {
diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java
index 6ed76081b..aa96056e4 100644
--- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java
+++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java
@@ -114,16 +114,17 @@ public class AligningCells {
// Make the selection
CTRowImpl ctRow = (CTRowImpl) row.getCTRow();
- List spanList = new ArrayList();
// Add object with format start_coll:end_coll. For example 1:3 will span from
// cell 1 to cell 3, where the column index starts with 0
//
// You can add multiple spans for one row
Object span = start_column + ":" + end_column;
+
+ List
+ * @param formula1 - formula for the valued, compared with the cell
+ * @param formula2 - second formula (only used with
+ * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and
+ * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations)
+ */
+ public HSSFConditionalFormattingRule createConditionalFormattingRule(
+ byte comparisonOperation,
+ String formula1,
+ String formula2) {
+ CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
+ return new HSSFConditionalFormattingRule(_sheet, rr);
+ }
public HSSFConditionalFormattingRule createConditionalFormattingRule(
byte comparisonOperation,
String formula1) {
-
- HSSFWorkbook wb = _sheet.getWorkbook();
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, null);
- return new HSSFConditionalFormattingRule(wb, rr);
+ return new HSSFConditionalFormattingRule(_sheet, rr);
}
- /**
- * A factory method allowing to create a conditional formatting rule with a formula.
- *
- * The formatting rules are applied by Excel when the value of the formula not equal to 0.
- * TODO - formulas containing cell references are currently not parsed properly
- * @param formula - formula for the valued, compared with the cell
- */
- public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
- HSSFWorkbook wb = _sheet.getWorkbook();
- CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
- return new HSSFConditionalFormattingRule(wb, rr);
- }
+ /**
+ * A factory method allowing to create a conditional formatting rule with a formula.
+ *
+ * The formatting rules are applied by Excel when the value of the formula not equal to 0.
+ * TODO - formulas containing cell references are currently not parsed properly
+ * @param formula - formula for the valued, compared with the cell
+ */
+ public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
+ CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
+ return new HSSFConditionalFormattingRule(_sheet, rr);
+ }
- /**
- * Adds a copy of HSSFConditionalFormatting object to the sheet
- *
This method could be used to copy HSSFConditionalFormatting object
- * from one sheet to another. For example:
- *
- *
- * @param cf HSSFConditionalFormatting object
- * @return index of the new Conditional Formatting object
- */
- public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
- CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
+ /**
+ * A factory method allowing the creation of conditional formatting
+ * rules using an Icon Set / Multi-State formatting.
+ * The thresholds for it will be created, but will be empty
+ * and require configuring with
+ * {@link HSSFConditionalFormattingRule#getMultiStateFormatting()}
+ * then
+ * {@link HSSFIconMultiStateFormatting#getThresholds()}
+ */
+ public HSSFConditionalFormattingRule createConditionalFormattingRule(
+ IconSet iconSet) {
+ CFRule12Record rr = CFRule12Record.create(_sheet, iconSet);
+ return new HSSFConditionalFormattingRule(_sheet, rr);
+ }
- return _conditionalFormattingTable.add(cfraClone);
- }
+ // TODO Support types beyond CELL_VALUE_IS and FORMULA and ICONs
+
+ /**
+ * Adds a copy of HSSFConditionalFormatting object to the sheet
+ *
This method could be used to copy HSSFConditionalFormatting object
+ * from one sheet to another. For example:
+ *
+ *
+ * @param cf HSSFConditionalFormatting object
+ * @return index of the new Conditional Formatting object
+ */
+ public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
+ CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
+
+ return _conditionalFormattingTable.add(cfraClone);
+ }
public int addConditionalFormatting( ConditionalFormatting cf ) {
return addConditionalFormatting((HSSFConditionalFormatting)cf);
}
- /**
- * @deprecated use CellRangeAddress instead of Region
- */
- public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
- return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules);
- }
- /**
- * Allows to add a new Conditional Formatting set to the sheet.
- *
- * @param regions - list of rectangular regions to apply conditional formatting rules
- * @param cfRules - set of up to three conditional formatting rules
- *
- * @return index of the newly created Conditional Formatting object
- */
- public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
- if (regions == null) {
- throw new IllegalArgumentException("regions must not be null");
- }
- for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
+ /**
+ * @deprecated use CellRangeAddress instead of Region
+ */
+ public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
+ return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules);
+ }
+ /**
+ * Allows to add a new Conditional Formatting set to the sheet.
+ *
+ * @param regions - list of rectangular regions to apply conditional formatting rules
+ * @param cfRules - set of up to three conditional formatting rules
+ *
+ * @return index of the newly created Conditional Formatting object
+ */
+ public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
+ if (regions == null) {
+ throw new IllegalArgumentException("regions must not be null");
+ }
+ for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
- if (cfRules == null) {
- throw new IllegalArgumentException("cfRules must not be null");
- }
- if (cfRules.length == 0) {
- throw new IllegalArgumentException("cfRules must not be empty");
- }
- if (cfRules.length > 3) {
- throw new IllegalArgumentException("Number of rules must not exceed 3");
- }
+ if (cfRules == null) {
+ throw new IllegalArgumentException("cfRules must not be null");
+ }
+ if (cfRules.length == 0) {
+ throw new IllegalArgumentException("cfRules must not be empty");
+ }
+ if (cfRules.length > 3) {
+ throw new IllegalArgumentException("Number of rules must not exceed 3");
+ }
- CFRuleRecord[] rules = new CFRuleRecord[cfRules.length];
- for (int i = 0; i != cfRules.length; i++) {
- rules[i] = cfRules[i].getCfRuleRecord();
- }
- CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
- return _conditionalFormattingTable.add(cfra);
- }
+ CFRuleBase[] rules = new CFRuleBase[cfRules.length];
+ for (int i = 0; i != cfRules.length; i++) {
+ rules[i] = cfRules[i].getCfRuleRecord();
+ }
+ CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
+ return _conditionalFormattingTable.add(cfra);
+ }
public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) {
HSSFConditionalFormattingRule[] hfRules;
@@ -164,70 +178,61 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor
return addConditionalFormatting(regions, hfRules);
}
- public int addConditionalFormatting(CellRangeAddress[] regions,
- HSSFConditionalFormattingRule rule1)
- {
- return addConditionalFormatting(regions,
- rule1 == null ? null : new HSSFConditionalFormattingRule[]
- {
- rule1
- });
- }
+ public int addConditionalFormatting(CellRangeAddress[] regions,
+ HSSFConditionalFormattingRule rule1) {
+ return addConditionalFormatting(regions, rule1 == null ?
+ null : new HSSFConditionalFormattingRule[] { rule1 }
+ );
+ }
public int addConditionalFormatting(CellRangeAddress[] regions,
- ConditionalFormattingRule rule1)
- {
+ ConditionalFormattingRule rule1) {
return addConditionalFormatting(regions, (HSSFConditionalFormattingRule)rule1);
}
- public int addConditionalFormatting(CellRangeAddress[] regions,
- HSSFConditionalFormattingRule rule1,
- HSSFConditionalFormattingRule rule2)
- {
- return addConditionalFormatting(regions,
- new HSSFConditionalFormattingRule[]
- {
- rule1, rule2
- });
- }
+ public int addConditionalFormatting(CellRangeAddress[] regions,
+ HSSFConditionalFormattingRule rule1,
+ HSSFConditionalFormattingRule rule2) {
+ return addConditionalFormatting(regions,
+ new HSSFConditionalFormattingRule[] { rule1, rule2 });
+ }
public int addConditionalFormatting(CellRangeAddress[] regions,
ConditionalFormattingRule rule1,
- ConditionalFormattingRule rule2)
- {
+ ConditionalFormattingRule rule2) {
return addConditionalFormatting(regions,
(HSSFConditionalFormattingRule)rule1,
(HSSFConditionalFormattingRule)rule2
- );
+ );
}
- /**
- * gets Conditional Formatting object at a particular index
- *
- * @param index
- * of the Conditional Formatting object to fetch
- * @return Conditional Formatting object
- */
- public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
- CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
- if (cf == null) {
- return null;
- }
- return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf);
- }
+ /**
+ * gets Conditional Formatting object at a particular index
+ *
+ * @param index
+ * of the Conditional Formatting object to fetch
+ * @return Conditional Formatting object
+ */
+ public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
+ CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
+ if (cf == null) {
+ return null;
+ }
+ return new HSSFConditionalFormatting(_sheet, cf);
+ }
- /**
- * @return number of Conditional Formatting objects of the sheet
- */
- public int getNumConditionalFormattings() {
- return _conditionalFormattingTable.size();
- }
+ /**
+ * @return number of Conditional Formatting objects of the sheet
+ */
+ public int getNumConditionalFormattings() {
+ return _conditionalFormattingTable.size();
+ }
- /**
- * removes a Conditional Formatting object by index
- * @param index of a Conditional Formatting object to remove
- */
- public void removeConditionalFormatting(int index) {
- _conditionalFormattingTable.remove(index);
- }
+ /**
+ * removes a Conditional Formatting object by index
+ * @param index of a Conditional Formatting object to remove
+ */
+ public void removeConditionalFormatting(int index) {
+ _conditionalFormattingTable.remove(index);
+ }
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
index 503ed64d6..65ec1a33e 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
@@ -65,6 +65,7 @@ import org.apache.poi.hssf.record.UnknownRecord;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.record.common.UnicodeString;
import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.EntryUtils;
@@ -205,6 +206,19 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
this(fs,true);
}
+ /**
+ * Given a POI POIFSFileSystem object, read in its Workbook along
+ * with all related nodes, and populate the high and low level models.
+ *
This calls {@link #HSSFWorkbook(POIFSFileSystem, boolean)} with
+ * preserve nodes set to true.
+ *
+ * @see #HSSFWorkbook(POIFSFileSystem, boolean)
+ * @see org.apache.poi.poifs.filesystem.POIFSFileSystem
+ * @exception IOException if the stream cannot be read
+ */
+ public HSSFWorkbook(NPOIFSFileSystem fs) throws IOException {
+ this(fs.getRoot(),true);
+ }
/**
* Given a POI POIFSFileSystem object, read in its Workbook and populate
@@ -248,7 +262,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
// check for an encrypted .xlsx file - they get OLE2 wrapped
try {
- directory.getEntry("EncryptedPackage");
+ directory.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
throw new EncryptedDocumentException("The supplied spreadsheet seems to be an Encrypted .xlsx file. " +
"It must be decrypted before use by XSSF, it cannot be used by HSSF");
} catch (FileNotFoundException e) {
@@ -378,7 +392,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public HSSFWorkbook(InputStream s, boolean preserveNodes)
throws IOException
{
- this(new POIFSFileSystem(s), preserveNodes);
+ this(new NPOIFSFileSystem(s).getRoot(), preserveNodes);
}
/**
@@ -1276,7 +1290,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
throws IOException
{
byte[] bytes = getBytes();
- POIFSFileSystem fs = new POIFSFileSystem();
+ NPOIFSFileSystem fs = new NPOIFSFileSystem();
// For tracking what we've written out, used if we're
// going to be preserving nodes
@@ -1843,7 +1857,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
throws IOException {
// check if we were created by POIFS otherwise create a new dummy POIFS for storing the package data
if (directory == null) {
- directory = new POIFSFileSystem().getRoot();
+ directory = new NPOIFSFileSystem().getRoot();
preserveNodes = true;
}
diff --git a/src/java/org/apache/poi/hssf/util/HSSFColor.java b/src/java/org/apache/poi/hssf/util/HSSFColor.java
index f438e1b00..d7a1cb587 100644
--- a/src/java/org/apache/poi/hssf/util/HSSFColor.java
+++ b/src/java/org/apache/poi/hssf/util/HSSFColor.java
@@ -204,6 +204,13 @@ public class HSSFColor implements Color {
{
return BLACK.hexString;
}
+
+ public static HSSFColor toHSSFColor(Color color) {
+ if (color != null && !(color instanceof HSSFColor)) {
+ throw new IllegalArgumentException("Only HSSFColor objects are supported");
+ }
+ return (HSSFColor)color;
+ }
/**
* Class BLACK
diff --git a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
index 8a2bf0045..2c5716d2a 100644
--- a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
+++ b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
@@ -16,6 +16,8 @@
==================================================================== */
package org.apache.poi.poifs.crypt;
+import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -132,8 +134,8 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
super.close();
int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
- calculateChecksum(fileOut, oleStreamSize);
- dir.createDocument("EncryptedPackage", oleStreamSize, new EncryptedPackageWriter());
+ calculateChecksum(fileOut, (int)_pos);
+ dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter());
createEncryptionInfoEntry(dir, fileOut);
} catch (GeneralSecurityException e) {
throw new IOException(e);
diff --git a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java
index 0c80c6c2b..f6477fb9b 100644
--- a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java
+++ b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java
@@ -36,7 +36,7 @@ public class DataSpaceMapUtils {
public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException {
DataSpaceMapEntry dsme = new DataSpaceMapEntry(
new int[]{ 0 }
- , new String[]{ "EncryptedPackage" }
+ , new String[]{ Decryptor.DEFAULT_POIFS_ENTRY }
, "StrongEncryptionDataSpace"
);
DataSpaceMap dsm = new DataSpaceMap(new DataSpaceMapEntry[]{dsme});
diff --git a/src/java/org/apache/poi/poifs/crypt/Decryptor.java b/src/java/org/apache/poi/poifs/crypt/Decryptor.java
index af449290e..eb94dca98 100644
--- a/src/java/org/apache/poi/poifs/crypt/Decryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/Decryptor.java
@@ -25,10 +25,12 @@ import javax.crypto.SecretKey;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public abstract class Decryptor {
public static final String DEFAULT_PASSWORD="VelvetSweatshop";
+ public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage";
protected final EncryptionInfoBuilder builder;
private SecretKey secretKey;
@@ -83,7 +85,9 @@ public abstract class Decryptor {
public InputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
-
+ public InputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
+ return getDataStream(fs.getRoot());
+ }
public InputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
index 0418befe2..3aafb90ca 100644
--- a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
+++ b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
@@ -68,14 +69,27 @@ public class EncryptionInfo {
public static BitField flagAES = BitFieldFactory.getInstance(0x20);
+ /**
+ * Opens for decryption
+ */
public EncryptionInfo(POIFSFileSystem fs) throws IOException {
this(fs.getRoot());
}
-
+ /**
+ * Opens for decryption
+ */
+ public EncryptionInfo(OPOIFSFileSystem fs) throws IOException {
+ this(fs.getRoot());
+ }
+ /**
+ * Opens for decryption
+ */
public EncryptionInfo(NPOIFSFileSystem fs) throws IOException {
this(fs.getRoot());
}
-
+ /**
+ * Opens for decryption
+ */
public EncryptionInfo(DirectoryNode dir) throws IOException {
this(dir.createDocumentInputStream("EncryptionInfo"), false);
}
@@ -131,7 +145,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without fs parameter
+ * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required)
*/
@Deprecated
public EncryptionInfo(POIFSFileSystem fs, EncryptionMode encryptionMode) {
@@ -139,7 +153,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without fs parameter
+ * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required)
*/
@Deprecated
public EncryptionInfo(NPOIFSFileSystem fs, EncryptionMode encryptionMode) {
@@ -147,7 +161,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without dir parameter
+ * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (dir parameter no longer required)
*/
@Deprecated
public EncryptionInfo(DirectoryNode dir, EncryptionMode encryptionMode) {
@@ -155,7 +169,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without fs parameter
+ * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
*/
@Deprecated
public EncryptionInfo(
@@ -171,7 +185,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without fs parameter
+ * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
*/
@Deprecated
public EncryptionInfo(
@@ -187,7 +201,7 @@ public class EncryptionInfo {
}
/**
- * @deprecated use constructor without dir parameter
+ * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
*/
@Deprecated
public EncryptionInfo(
@@ -202,6 +216,11 @@ public class EncryptionInfo {
this(encryptionMode, cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
}
+ /**
+ * Prepares for encryption, using the given Encryption Mode, and
+ * all other parameters as default.
+ * @see #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)
+ */
public EncryptionInfo(EncryptionMode encryptionMode) {
this(encryptionMode, null, null, -1, -1, null);
}
diff --git a/src/java/org/apache/poi/poifs/crypt/Encryptor.java b/src/java/org/apache/poi/poifs/crypt/Encryptor.java
index abfd69330..d40f8ae5d 100644
--- a/src/java/org/apache/poi/poifs/crypt/Encryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/Encryptor.java
@@ -24,9 +24,11 @@ import javax.crypto.SecretKey;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public abstract class Encryptor {
+ protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY;
private SecretKey secretKey;
/**
@@ -50,7 +52,9 @@ public abstract class Encryptor {
public OutputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
-
+ public OutputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
+ return getDataStream(fs.getRoot());
+ }
public OutputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
index 40eab54e3..a2d3d6f0e 100644
--- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
@@ -118,7 +118,7 @@ public class BinaryRC4Decryptor extends Decryptor {
public InputStream getDataStream(DirectoryNode dir) throws IOException,
GeneralSecurityException {
- DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage");
+ DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
_length = dis.readLong();
BinaryRC4CipherInputStream cipherStream = new BinaryRC4CipherInputStream(dis, _length);
return cipherStream;
@@ -131,4 +131,4 @@ public class BinaryRC4Decryptor extends Decryptor {
return _length;
}
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
index c1ae13cee..1e470d726 100644
--- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
@@ -40,7 +40,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.DocumentNode;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.BoundedInputStream;
@@ -200,7 +200,7 @@ public class CryptoAPIDecryptor extends Decryptor {
@SuppressWarnings("unused")
public InputStream getDataStream(DirectoryNode dir)
throws IOException, GeneralSecurityException {
- POIFSFileSystem fsOut = new POIFSFileSystem();
+ NPOIFSFileSystem fsOut = new NPOIFSFileSystem();
DocumentNode es = (DocumentNode) dir.getEntry("EncryptedSummary");
DocumentInputStream dis = dir.createDocumentInputStream(es);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -240,6 +240,7 @@ public class CryptoAPIDecryptor extends Decryptor {
sbis = null;
bos.reset();
fsOut.writeFilesystem(bos);
+ fsOut.close();
_length = bos.size();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
return bis;
diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
index 2b2c75b52..1d6ddd398 100644
--- a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
@@ -123,7 +123,7 @@ public class StandardDecryptor extends Decryptor {
}
public InputStream getDataStream(DirectoryNode dir) throws IOException {
- DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage");
+ DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
_length = dis.readLong();
diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
index 7049c715d..ae6304fbb 100644
--- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
+++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
@@ -166,7 +166,7 @@ public class StandardEncryptor extends Encryptor {
void writeToPOIFS() throws IOException {
int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
- dir.createDocument("EncryptedPackage", oleStreamSize, this);
+ dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this);
// TODO: any properties???
}
diff --git a/src/java/org/apache/poi/poifs/dev/POIFSDump.java b/src/java/org/apache/poi/poifs/dev/POIFSDump.java
index ace19d8d1..ce7d9e441 100644
--- a/src/java/org/apache/poi/poifs/dev/POIFSDump.java
+++ b/src/java/org/apache/poi/poifs/dev/POIFSDump.java
@@ -16,27 +16,54 @@
==================================================================== */
package org.apache.poi.poifs.dev;
-import org.apache.poi.poifs.filesystem.*;
-
-import java.io.FileInputStream;
import java.io.File;
-import java.io.IOException;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
import java.util.Iterator;
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.poifs.filesystem.DocumentNode;
+import org.apache.poi.poifs.filesystem.Entry;
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.NPOIFSStream;
+import org.apache.poi.poifs.property.NPropertyTable;
+import org.apache.poi.poifs.storage.HeaderBlock;
+
/**
- *
* Dump internal structure of a OLE2 file into file system
- *
- * @author Yegor Kozlov
*/
public class POIFSDump {
-
public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ System.err.println("Must specify at least one file to dump");
+ System.exit(1);
+ }
+
+ boolean dumpProps = false, dumpMini = false;
for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-dumprops") ||
+ args[i].equalsIgnoreCase("-dump-props") ||
+ args[i].equalsIgnoreCase("-dump-properties")) {
+ dumpProps = true;
+ continue;
+ }
+ if (args[i].equalsIgnoreCase("-dumpmini") ||
+ args[i].equalsIgnoreCase("-dump-mini") ||
+ args[i].equalsIgnoreCase("-dump-ministream") ||
+ args[i].equalsIgnoreCase("-dump-mini-stream")) {
+ dumpMini = true;
+ continue;
+ }
+
System.out.println("Dumping " + args[i]);
FileInputStream is = new FileInputStream(args[i]);
- POIFSFileSystem fs = new POIFSFileSystem(is);
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(is);
is.close();
DirectoryEntry root = fs.getRoot();
@@ -44,13 +71,39 @@ public class POIFSDump {
file.mkdir();
dump(root, file);
+
+ if (dumpProps) {
+ HeaderBlock header = getHeaderBlock(fs);
+ dump(fs, header.getPropertyStart(), "properties", file);
+ }
+ if (dumpMini) {
+ NPropertyTable props = getPropertyTable(fs);
+ int startBlock = props.getRoot().getStartBlock();
+ if (startBlock == POIFSConstants.END_OF_CHAIN) {
+ System.err.println("No Mini Stream in file");
+ } else {
+ dump(fs, startBlock, "mini-stream", file);
+ }
+ }
}
}
-
+
+ protected static HeaderBlock getHeaderBlock(NPOIFSFileSystem fs) throws Exception {
+ Field headerF = NPOIFSFileSystem.class.getDeclaredField("_header");
+ headerF.setAccessible(true);
+ HeaderBlock header = (HeaderBlock)headerF.get(fs);
+ return header;
+ }
+ protected static NPropertyTable getPropertyTable(NPOIFSFileSystem fs) throws Exception {
+ Field ptF = NPOIFSFileSystem.class.getDeclaredField("_property_table");
+ ptF.setAccessible(true);
+ NPropertyTable table = (NPropertyTable)ptF.get(fs);
+ return table;
+ }
public static void dump(DirectoryEntry root, File parent) throws IOException {
- for(Iterator it = root.getEntries(); it.hasNext();){
- Entry entry = (Entry)it.next();
+ for(Iterator it = root.getEntries(); it.hasNext();){
+ Entry entry = it.next();
if(entry instanceof DocumentNode){
DocumentNode node = (DocumentNode)entry;
DocumentInputStream is = new DocumentInputStream(node);
@@ -58,9 +111,12 @@ public class POIFSDump {
is.read(bytes);
is.close();
- FileOutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
- out.write(bytes);
- out.close();
+ OutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
+ try {
+ out.write(bytes);
+ } finally {
+ out.close();
+ }
} else if (entry instanceof DirectoryEntry){
DirectoryEntry dir = (DirectoryEntry)entry;
File file = new File(parent, entry.getName());
@@ -71,4 +127,17 @@ public class POIFSDump {
}
}
}
+ public static void dump(NPOIFSFileSystem fs, int startBlock, String name, File parent) throws IOException {
+ File file = new File(parent, name);
+ FileOutputStream out = new FileOutputStream(file);
+ NPOIFSStream stream = new NPOIFSStream(fs, startBlock);
+
+ byte[] b = new byte[fs.getBigBlockSize()];
+ for (ByteBuffer bb : stream) {
+ int len = bb.remaining();
+ bb.get(b);
+ out.write(b, 0, len);
+ }
+ out.close();
+ }
}
diff --git a/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java b/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java
index 78ed986a4..e321c8b9b 100644
--- a/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java
+++ b/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java
@@ -24,9 +24,10 @@ import java.lang.reflect.Method;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.property.DirectoryProperty;
+import org.apache.poi.poifs.property.Property;
import org.apache.poi.poifs.property.PropertyTable;
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
-import org.apache.poi.poifs.storage.BlockList;
import org.apache.poi.poifs.storage.HeaderBlock;
import org.apache.poi.poifs.storage.ListManagedBlock;
import org.apache.poi.poifs.storage.RawDataBlockList;
@@ -42,111 +43,146 @@ import org.apache.poi.util.IntList;
* down the source of corruption in a file.
*/
public class POIFSHeaderDumper {
- /**
- * Display the entries of multiple POIFS files
- *
- * @param args the names of the files to be displayed
- */
- public static void main(final String args[]) throws Exception {
- if (args.length == 0) {
- System.err.println("Must specify at least one file to view");
- System.exit(1);
- }
+ /**
+ * Display the entries of multiple POIFS files
+ *
+ * @param args the names of the files to be displayed
+ */
+ public static void main(final String args[]) throws Exception {
+ if (args.length == 0) {
+ System.err.println("Must specify at least one file to view");
+ System.exit(1);
+ }
- for (int j = 0; j < args.length; j++) {
- viewFile(args[j]);
- }
- }
+ for (int j = 0; j < args.length; j++) {
+ viewFile(args[j]);
+ }
+ }
- public static void viewFile(final String filename) throws Exception {
- InputStream inp = new FileInputStream(filename);
-
- // Header
- HeaderBlock header_block = new HeaderBlock(inp);
- displayHeader(header_block);
-
- // Raw blocks
- POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
- RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
- displayRawBlocksSummary(data_blocks);
-
- // Main FAT Table
- BlockAllocationTableReader batReader =
- new BlockAllocationTableReader(
- header_block.getBigBlockSize(),
- header_block.getBATCount(),
- header_block.getBATArray(),
- header_block.getXBATCount(),
- header_block.getXBATIndex(),
- data_blocks);
- displayBATReader(batReader);
+ public static void viewFile(final String filename) throws Exception {
+ System.out.println("Dumping headers from: " + filename);
+ InputStream inp = new FileInputStream(filename);
- // Properties Table
- PropertyTable properties =
- new PropertyTable(header_block, data_blocks);
-
- // Mini Fat
- BlockList sbat =
- SmallBlockTableReader.getSmallDocumentBlocks(
- bigBlockSize, data_blocks, properties.getRoot(),
- header_block.getSBATStart()
- );
- }
+ // Header
+ HeaderBlock header_block = new HeaderBlock(inp);
+ displayHeader(header_block);
- public static void displayHeader(HeaderBlock header_block) throws Exception {
- System.out.println("Header Details:");
- System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize());
- System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
- System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
- System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
- System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
- System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
- System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
- System.out.println(" Property table at: " + header_block.getPropertyStart());
- System.out.println("");
- }
+ // Raw blocks
+ POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
+ RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
+ displayRawBlocksSummary(data_blocks);
- public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
- System.out.println("Raw Blocks Details:");
- System.out.println(" Number of blocks: " + data_blocks.blockCount());
-
- Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
- gbm.setAccessible(true);
-
- for(int i=0; i " + bnS);
- }
-
- System.out.println("");
- }
+ // Main FAT Table
+ BlockAllocationTableReader batReader =
+ new BlockAllocationTableReader(
+ header_block.getBigBlockSize(),
+ header_block.getBATCount(),
+ header_block.getBATArray(),
+ header_block.getXBATCount(),
+ header_block.getXBATIndex(),
+ data_blocks);
+ displayBATReader("Big Blocks", batReader);
+
+ // Properties Table
+ PropertyTable properties =
+ new PropertyTable(header_block, data_blocks);
+
+ // Mini Fat
+ BlockAllocationTableReader sbatReader =
+ SmallBlockTableReader._getSmallDocumentBlockReader(
+ bigBlockSize, data_blocks, properties.getRoot(),
+ header_block.getSBATStart()
+ );
+ displayBATReader("Small Blocks", sbatReader);
+
+ // Summary of the properties
+ displayPropertiesSummary(properties);
+ }
+
+ public static void displayHeader(HeaderBlock header_block) throws Exception {
+ System.out.println("Header Details:");
+ System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize());
+ System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
+ System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
+ if (header_block.getBATCount() > 0)
+ System.out.println(" BAT (FAT) block 1 at: " + header_block.getBATArray()[0]);
+ System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
+ System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
+ System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
+ System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
+ System.out.println(" Property table at: " + header_block.getPropertyStart());
+ System.out.println("");
+ }
+
+ public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
+ System.out.println("Raw Blocks Details:");
+ System.out.println(" Number of blocks: " + data_blocks.blockCount());
+
+ Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
+ gbm.setAccessible(true);
+
+ for(int i=0; i " + bnS);
+ }
+
+ System.out.println("");
+ }
+
+ public static void displayPropertiesSummary(PropertyTable properties) {
+ System.out.println("Mini Stream starts at " + properties.getRoot().getStartBlock());
+ System.out.println("Mini Stream length is " + properties.getRoot().getSize());
+ System.out.println();
+
+ System.out.println("Properties and their block start:");
+ displayProperties(properties.getRoot(), "");
+ System.out.println("");
+ }
+ public static void displayProperties(DirectoryProperty prop, String indent) {
+ String nextIndent = indent + " ";
+ System.out.println(indent + "-> " + prop.getName());
+ for (Property cp : prop) {
+ if (cp instanceof DirectoryProperty) {
+ displayProperties((DirectoryProperty)cp, nextIndent);
+ } else {
+ System.out.println(nextIndent + "=> " + cp.getName());
+ System.out.print(nextIndent + " " + cp.getSize() + " bytes in ");
+ if (cp.shouldUseSmallBlocks()) {
+ System.out.print("mini");
+ } else {
+ System.out.print("main");
+ }
+ System.out.println(" stream, starts at " + cp.getStartBlock());
+ }
+ }
+ }
}
diff --git a/src/java/org/apache/poi/poifs/dev/POIFSViewer.java b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java
index 8b8173426..4614376db 100644
--- a/src/java/org/apache/poi/poifs/dev/POIFSViewer.java
+++ b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java
@@ -19,12 +19,12 @@
package org.apache.poi.poifs.dev;
-import java.io.FileInputStream;
+import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
/**
* A simple viewer for POIFS files
@@ -76,10 +76,10 @@ public class POIFSViewer
try
{
POIFSViewable fs =
- new POIFSFileSystem(new FileInputStream(filename));
- List strings = POIFSViewEngine.inspectViewable(fs, true,
+ new NPOIFSFileSystem(new File(filename));
+ List strings = POIFSViewEngine.inspectViewable(fs, true,
0, " ");
- Iterator iter = strings.iterator();
+ Iterator iter = strings.iterator();
while (iter.hasNext())
{
diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
index 567527523..a28870918 100644
--- a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
+++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
@@ -24,7 +24,7 @@ import java.io.*;
import java.util.*;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
-import org.apache.poi.poifs.filesystem.POIFSDocument;
+import org.apache.poi.poifs.filesystem.OPOIFSDocument;
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
import org.apache.poi.poifs.property.DirectoryProperty;
import org.apache.poi.poifs.property.Property;
@@ -240,19 +240,19 @@ public class POIFSReader
if (listeners.hasNext())
{
- int size = property.getSize();
- POIFSDocument document = null;
+ int size = property.getSize();
+ OPOIFSDocument document = null;
if (property.shouldUseSmallBlocks())
{
document =
- new POIFSDocument(name, small_blocks
+ new OPOIFSDocument(name, small_blocks
.fetchBlocks(startBlock, -1), size);
}
else
{
document =
- new POIFSDocument(name, big_blocks
+ new OPOIFSDocument(name, big_blocks
.fetchBlocks(startBlock, -1), size);
}
while (listeners.hasNext())
diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
index 8d39bbfa2..9be71a5cc 100644
--- a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
+++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
@@ -37,8 +37,6 @@ import org.apache.poi.poifs.property.Property;
/**
* Simple implementation of DirectoryEntry
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public class DirectoryNode
extends EntryNode
@@ -50,9 +48,9 @@ public class DirectoryNode
// Our list of entries, kept sorted to preserve order
private ArrayList _entries;
- // Only one of these two will exist
- // the POIFSFileSystem we belong to
- private POIFSFileSystem _ofilesystem;
+ // Only one of these two will exist
+ // the OPOIFSFileSystem we belong to
+ private OPOIFSFileSystem _ofilesystem;
// the NPOIFSFileSytem we belong to
private NPOIFSFileSystem _nfilesystem;
@@ -64,11 +62,11 @@ public class DirectoryNode
* is intended strictly for the internal use of this package
*
* @param property the DirectoryProperty for this DirectoryEntry
- * @param filesystem the POIFSFileSystem we belong to
+ * @param filesystem the OPOIFSFileSystem we belong to
* @param parent the parent of this entry
*/
DirectoryNode(final DirectoryProperty property,
- final POIFSFileSystem filesystem,
+ final OPOIFSFileSystem filesystem,
final DirectoryNode parent)
{
this(property, parent, filesystem, (NPOIFSFileSystem)null);
@@ -86,12 +84,12 @@ public class DirectoryNode
final NPOIFSFileSystem nfilesystem,
final DirectoryNode parent)
{
- this(property, parent, (POIFSFileSystem)null, nfilesystem);
+ this(property, parent, (OPOIFSFileSystem)null, nfilesystem);
}
private DirectoryNode(final DirectoryProperty property,
final DirectoryNode parent,
- final POIFSFileSystem ofilesystem,
+ final OPOIFSFileSystem ofilesystem,
final NPOIFSFileSystem nfilesystem)
{
super(property, parent);
@@ -148,12 +146,24 @@ public class DirectoryNode
/**
* @return the filesystem that this belongs to
*/
- public POIFSFileSystem getFileSystem()
+ public NPOIFSFileSystem getFileSystem()
+ {
+ return _nfilesystem;
+ }
+
+ /**
+ * If this is OPOIFS based, return the NPOIFSFileSystem
+ * that this belong to, otherwise Null if NPOIFS based
+ * @return the filesystem that this belongs to
+ */
+ public OPOIFSFileSystem getOFileSystem()
{
return _ofilesystem;
}
/**
+ * If this is NPOIFS based, return the NPOIFSFileSystem
+ * that this belong to, otherwise Null if OPOIFS based
* @return the filesystem that this belongs to
*/
public NPOIFSFileSystem getNFileSystem()
@@ -210,7 +220,7 @@ public class DirectoryNode
*
* @exception IOException
*/
- DocumentEntry createDocument(final POIFSDocument document)
+ DocumentEntry createDocument(final OPOIFSDocument document)
throws IOException
{
DocumentProperty property = document.getDocumentProperty();
@@ -411,7 +421,7 @@ public class DirectoryNode
if(_nfilesystem != null) {
return createDocument(new NPOIFSDocument(name, _nfilesystem, stream));
} else {
- return createDocument(new POIFSDocument(name, stream));
+ return createDocument(new OPOIFSDocument(name, stream));
}
}
@@ -434,7 +444,7 @@ public class DirectoryNode
if(_nfilesystem != null) {
return createDocument(new NPOIFSDocument(name, size, _nfilesystem, writer));
} else {
- return createDocument(new POIFSDocument(name, size, _path, writer));
+ return createDocument(new OPOIFSDocument(name, size, _path, writer));
}
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
index 6c6b6100c..82959c7ff 100644
--- a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
+++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
@@ -58,7 +58,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu
if(documentNode.getDocument() != null) {
delegate = new ODocumentInputStream(document);
- } else if(parentNode.getFileSystem() != null) {
+ } else if(parentNode.getOFileSystem() != null) {
delegate = new ODocumentInputStream(document);
} else if(parentNode.getNFileSystem() != null) {
delegate = new NDocumentInputStream(document);
@@ -72,7 +72,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu
*
* @param document the Document to be read
*/
- public DocumentInputStream(POIFSDocument document) {
+ public DocumentInputStream(OPOIFSDocument document) {
delegate = new ODocumentInputStream(document);
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java
index 9caafb766..7a5bf6900 100644
--- a/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java
+++ b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java
@@ -27,18 +27,15 @@ import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DocumentProperty;
/**
- * Simple implementation of DocumentEntry
- *
- * @author Marc Johnson (mjohnson at apache dot org)
+ * Simple implementation of DocumentEntry for OPOIFS
*/
-
public class DocumentNode
extends EntryNode
implements DocumentEntry, POIFSViewable
{
// underlying POIFSDocument instance
- private POIFSDocument _document;
+ private OPOIFSDocument _document;
/**
* create a DocumentNode. This method is not public by design; it
@@ -59,8 +56,7 @@ public class DocumentNode
*
* @return the internal POIFSDocument
*/
-
- POIFSDocument getDocument()
+ OPOIFSDocument getDocument()
{
return _document;
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java b/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java
index 4bce0641a..d8a55563a 100644
--- a/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java
+++ b/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java
@@ -124,8 +124,21 @@ public class EntryUtils
* @param target
* is the target POIFS to copy to
*/
- public static void copyNodes( POIFSFileSystem source,
- POIFSFileSystem target ) throws IOException
+ public static void copyNodes( OPOIFSFileSystem source,
+ OPOIFSFileSystem target ) throws IOException
+ {
+ copyNodes( source.getRoot(), target.getRoot() );
+ }
+ /**
+ * Copies all nodes from one POIFS to the other
+ *
+ * @param source
+ * is the source POIFS to copy from
+ * @param target
+ * is the target POIFS to copy to
+ */
+ public static void copyNodes( NPOIFSFileSystem source,
+ NPOIFSFileSystem target ) throws IOException
{
copyNodes( source.getRoot(), target.getRoot() );
}
@@ -140,8 +153,26 @@ public class EntryUtils
* @param target is the target POIFS to copy to
* @param excepts is a list of Entry Names to be excluded from the copy
*/
- public static void copyNodes( POIFSFileSystem source,
- POIFSFileSystem target, List excepts ) throws IOException
+ public static void copyNodes( OPOIFSFileSystem source,
+ OPOIFSFileSystem target, List excepts ) throws IOException
+ {
+ copyNodes(
+ new FilteringDirectoryNode(source.getRoot(), excepts),
+ new FilteringDirectoryNode(target.getRoot(), excepts)
+ );
+ }
+ /**
+ * Copies nodes from one POIFS to the other, minus the excepts.
+ * This delegates the filtering work to {@link FilteringDirectoryNode},
+ * so excepts can be of the form "NodeToExclude" or
+ * "FilteringDirectory/ExcludedChildNode"
+ *
+ * @param source is the source POIFS to copy from
+ * @param target is the target POIFS to copy to
+ * @param excepts is a list of Entry Names to be excluded from the copy
+ */
+ public static void copyNodes( NPOIFSFileSystem source,
+ NPOIFSFileSystem target, List excepts ) throws IOException
{
copyNodes(
new FilteringDirectoryNode(source.getRoot(), excepts),
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java
index 7846ed0df..c94e427b9 100644
--- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java
+++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -143,8 +144,17 @@ public final class NPOIFSDocument implements POIFSViewable {
os.write(buf, 0, readBytes);
}
- os.close();
+ // Pad to the end of the block with -1s
+ int usedInBlock = length % _block_size;
+ if (usedInBlock != 0 && usedInBlock != _block_size) {
+ int toBlockEnd = _block_size - usedInBlock;
+ byte[] padding = new byte[toBlockEnd];
+ Arrays.fill(padding, (byte)0xFF);
+ os.write(padding);
+ }
+ // Tidy and return the length
+ os.close();
return length;
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java
index f21f6a39a..c27ba3cd1 100644
--- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java
+++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java
@@ -36,6 +36,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.apache.poi.EmptyFileException;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
@@ -114,17 +115,18 @@ public class NPOIFSFileSystem extends BlockStore
{
this(true);
- // Mark us as having a single empty BAT at offset 0
+ // Reserve block 0 for the start of the Properties Table
+ // Create a single empty BAT, at pop that at offset 1
_header.setBATCount(1);
- _header.setBATArray(new int[] { 0 });
+ _header.setBATArray(new int[] { 1 });
BATBlock bb = BATBlock.createEmptyBATBlock(bigBlockSize, false);
- bb.setOurBlockIndex(0);
+ bb.setOurBlockIndex(1);
_bat_blocks.add(bb);
- setNextBlock(0, POIFSConstants.FAT_SECTOR_BLOCK);
- setNextBlock(1, POIFSConstants.END_OF_CHAIN);
+ setNextBlock(0, POIFSConstants.END_OF_CHAIN);
+ setNextBlock(1, POIFSConstants.FAT_SECTOR_BLOCK);
- _property_table.setStartBlock(POIFSConstants.END_OF_CHAIN);
+ _property_table.setStartBlock(0);
}
/**
@@ -210,6 +212,9 @@ public class NPOIFSFileSystem extends BlockStore
try {
// Initialize the datasource
if (srcFile != null) {
+ if (srcFile.length() == 0)
+ throw new EmptyFileException();
+
FileBackedDataSource d = new FileBackedDataSource(srcFile, readOnly);
channel = d.getChannel();
_data = d;
@@ -236,7 +241,10 @@ public class NPOIFSFileSystem extends BlockStore
// TODO Decide if we can handle these better whilst
// still sticking to the iterator contract
if(closeChannelOnError) {
- channel.close();
+ if (channel != null) {
+ channel.close();
+ channel = null;
+ }
}
throw e;
}
@@ -369,6 +377,15 @@ public class NPOIFSFileSystem extends BlockStore
return (signature.get() == HeaderBlockConstants._signature);
}
+ /**
+ * Checks if the supplied first 8 bytes of a stream / file
+ * has a POIFS (OLE2) header.
+ */
+ public static boolean hasPOIFSHeader(byte[] header8Bytes) {
+ LongField signature = new LongField(HeaderBlockConstants._signature_offset, header8Bytes);
+ return (signature.get() == HeaderBlockConstants._signature);
+ }
+
/**
* Read and process the PropertiesTable and the
* FAT / XFAT blocks, so that we're ready to
@@ -420,7 +437,7 @@ public class NPOIFSFileSystem extends BlockStore
List sbats = new ArrayList();
_mini_store = new NPOIFSMiniStore(this, _property_table.getRoot(), sbats, _header);
nextAt = _header.getSBATStart();
- for(int i=0; i<_header.getSBATCount(); i++) {
+ for(int i=0; i<_header.getSBATCount() && nextAt != POIFSConstants.END_OF_CHAIN; i++) {
loopDetector.claim(nextAt);
ByteBuffer fatData = getBlockAt(nextAt);
sfat = BATBlock.createBATBlock(bigBlockSize, fatData);
@@ -749,6 +766,10 @@ public class NPOIFSFileSystem extends BlockStore
* to their backing blocks
*/
private void syncWithDataSource() throws IOException {
+ // Mini Stream + SBATs first, as mini-stream details have
+ // to be stored in the Root Property
+ _mini_store.syncWithDataSource();
+
// Properties
NPOIFSStream propStream = new NPOIFSStream(this, _header.getPropertyStart());
_property_table.preWrite();
@@ -769,9 +790,6 @@ public class NPOIFSFileSystem extends BlockStore
ByteBuffer block = getBlockAt(bat.getOurBlockIndex());
BlockAllocationTableWriter.writeBlock(bat, block);
}
-
- // SBATs
- _mini_store.syncWithDataSource();
}
/**
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
index 308ae15c7..b784058bc 100644
--- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
+++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
@@ -242,12 +242,24 @@ public class NPOIFSMiniStore extends BlockStore
}
/**
- * Writes the SBATs to their backing blocks
+ * Writes the SBATs to their backing blocks, and updates
+ * the mini-stream size in the properties. Stream size is
+ * based on full blocks used, not the data within the streams
*/
protected void syncWithDataSource() throws IOException {
- for(BATBlock sbat : _sbat_blocks) {
+ int blocksUsed = 0;
+ for (BATBlock sbat : _sbat_blocks) {
ByteBuffer block = _filesystem.getBlockAt(sbat.getOurBlockIndex());
BlockAllocationTableWriter.writeBlock(sbat, block);
+
+ if (!sbat.hasFreeSectors()) {
+ blocksUsed += _filesystem.getBigBlockSizeDetails().getBATEntriesPerBlock();
+ } else {
+ blocksUsed += sbat.getUsedSectors(false);
+ }
}
+ // Set the size on the root in terms of the number of SBAT blocks
+ // RootProperty.setSize does the sbat -> bytes conversion for us
+ _filesystem._get_property_table().getRoot().setSize(blocksUsed);
}
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java
index 5d444b8cb..da24fc383 100644
--- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java
+++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java
@@ -256,8 +256,10 @@ public class NPOIFSStream implements Iterable
NPOIFSStream toFree = new NPOIFSStream(blockStore, nextBlock);
toFree.free(loopDetector);
- // Mark the end of the stream
- blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN);
+ // Mark the end of the stream, if we have any data
+ if (prevBlock != POIFSConstants.END_OF_CHAIN) {
+ blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN);
+ }
}
}
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java
index a1bc5da95..858e2d9d9 100644
--- a/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java
+++ b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java
@@ -23,9 +23,7 @@ import org.apache.poi.poifs.storage.DataInputBlock;
/**
* This class provides methods to read a DocumentEntry managed by a
- * {@link POIFSFileSystem} instance.
- *
- * @author Marc Johnson (mjohnson at apache dot org)
+ * {@link OPOIFSFileSystem} instance.
*/
public final class ODocumentInputStream extends DocumentInputStream {
/** current offset into the Document */
@@ -41,7 +39,7 @@ public final class ODocumentInputStream extends DocumentInputStream {
private boolean _closed;
/** the actual Document */
- private POIFSDocument _document;
+ private OPOIFSDocument _document;
/** the data block containing the current stream pointer */
private DataInputBlock _currentBlock;
@@ -59,7 +57,7 @@ public final class ODocumentInputStream extends DocumentInputStream {
throw new IOException("Cannot open internal document storage");
}
DocumentNode documentNode = (DocumentNode)document;
- if(documentNode.getDocument() == null) {
+ if (documentNode.getDocument() == null) {
throw new IOException("Cannot open internal document storage");
}
@@ -76,7 +74,7 @@ public final class ODocumentInputStream extends DocumentInputStream {
*
* @param document the Document to be read
*/
- public ODocumentInputStream(POIFSDocument document) {
+ public ODocumentInputStream(OPOIFSDocument document) {
_current_offset = 0;
_marked_offset = 0;
_document_size = document.getSize();
diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java
similarity index 94%
rename from src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java
rename to src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java
index c6b35fd88..05b21baea 100644
--- a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java
+++ b/src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java
@@ -40,11 +40,10 @@ import org.apache.poi.poifs.storage.SmallDocumentBlock;
import org.apache.poi.util.HexDump;
/**
- * This class manages a document in the POIFS filesystem.
- *
- * @author Marc Johnson (mjohnson at apache dot org)
+ * This class manages a document in a old-style
+ * OPOIFS filesystem.
*/
-public final class POIFSDocument implements BATManaged, BlockWritable, POIFSViewable {
+public final class OPOIFSDocument implements BATManaged, BlockWritable, POIFSViewable {
private static final DocumentBlock[] EMPTY_BIG_BLOCK_ARRAY = { };
private static final SmallDocumentBlock[] EMPTY_SMALL_BLOCK_ARRAY = { };
private DocumentProperty _property;
@@ -63,7 +62,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param blocks the big blocks making up the POIFSDocument
* @param length the actual length of the POIFSDocument
*/
- public POIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException {
+ public OPOIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException {
_size = length;
if(blocks.length == 0) {
_bigBigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
@@ -104,7 +103,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param blocks the small blocks making up the POIFSDocument
* @param length the actual length of the POIFSDocument
*/
- public POIFSDocument(String name, SmallDocumentBlock[] blocks, int length) {
+ public OPOIFSDocument(String name, SmallDocumentBlock[] blocks, int length) {
_size = length;
if(blocks.length == 0) {
@@ -126,7 +125,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param blocks the small blocks making up the POIFSDocument
* @param length the actual length of the POIFSDocument
*/
- public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, int length) throws IOException {
+ public OPOIFSDocument(String name, POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, int length) throws IOException {
_size = length;
_bigBigBlockSize = bigBlockSize;
_property = new DocumentProperty(name, _size);
@@ -139,7 +138,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
_small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY);
}
}
- public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException {
+ public OPOIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException {
this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blocks, length);
}
@@ -149,7 +148,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param name the name of the POIFSDocument
* @param stream the InputStream we read data from
*/
- public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, InputStream stream) throws IOException {
+ public OPOIFSDocument(String name, POIFSBigBlockSize bigBlockSize, InputStream stream) throws IOException {
List blocks = new ArrayList();
_size = 0;
@@ -178,7 +177,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
_small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY);
}
}
- public POIFSDocument(String name, InputStream stream) throws IOException {
+ public OPOIFSDocument(String name, InputStream stream) throws IOException {
this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, stream);
}
@@ -190,7 +189,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param path the path of the POIFSDocument
* @param writer the writer who will eventually write the document contents
*/
- public POIFSDocument(String name, int size, POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path, POIFSWriterListener writer) {
+ public OPOIFSDocument(String name, int size, POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path, POIFSWriterListener writer) {
_size = size;
_bigBigBlockSize = bigBlockSize;
_property = new DocumentProperty(name, _size);
@@ -203,14 +202,14 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
_big_store = new BigBlockStore(_bigBigBlockSize, path, name, size, writer);
}
}
- public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) {
+ public OPOIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) {
this(name, size, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, path, writer);
}
/**
* @return array of SmallDocumentBlocks; may be empty, cannot be null
*/
- public BlockWritable[] getSmallBlocks() {
+ public SmallDocumentBlock[] getSmallBlocks() {
return _small_store.getBlocks();
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java
new file mode 100644
index 000000000..19abc48ab
--- /dev/null
+++ b/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java
@@ -0,0 +1,607 @@
+
+/* ====================================================================
+ 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.poi.poifs.filesystem;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.dev.POIFSViewable;
+import org.apache.poi.poifs.property.DirectoryProperty;
+import org.apache.poi.poifs.property.Property;
+import org.apache.poi.poifs.property.PropertyTable;
+import org.apache.poi.poifs.storage.BATBlock;
+import org.apache.poi.poifs.storage.BlockAllocationTableReader;
+import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
+import org.apache.poi.poifs.storage.BlockList;
+import org.apache.poi.poifs.storage.BlockWritable;
+import org.apache.poi.poifs.storage.HeaderBlock;
+import org.apache.poi.poifs.storage.HeaderBlockConstants;
+import org.apache.poi.poifs.storage.HeaderBlockWriter;
+import org.apache.poi.poifs.storage.RawDataBlockList;
+import org.apache.poi.poifs.storage.SmallBlockTableReader;
+import org.apache.poi.poifs.storage.SmallBlockTableWriter;
+import org.apache.poi.util.CloseIgnoringInputStream;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LongField;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ *
This is the main class of the POIFS system; it manages the entire
+ * life cycle of the filesystem.
+ *
This is the older version, which uses more memory, and doesn't
+ * support in-place writes.
+ */
+public class OPOIFSFileSystem
+ implements POIFSViewable
+{
+ private static final POILogger _logger =
+ POILogFactory.getLogger(OPOIFSFileSystem.class);
+
+ /**
+ * Convenience method for clients that want to avoid the auto-close behaviour of the constructor.
+ */
+ public static InputStream createNonClosingInputStream(InputStream is) {
+ return new CloseIgnoringInputStream(is);
+ }
+
+ private PropertyTable _property_table;
+ private List _documents;
+ private DirectoryNode _root;
+
+ /**
+ * What big block size the file uses. Most files
+ * use 512 bytes, but a few use 4096
+ */
+ private POIFSBigBlockSize bigBlockSize =
+ POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
+
+ /**
+ * Constructor, intended for writing
+ */
+ public OPOIFSFileSystem()
+ {
+ HeaderBlock header_block = new HeaderBlock(bigBlockSize);
+ _property_table = new PropertyTable(header_block);
+ _documents = new ArrayList();
+ _root = null;
+ }
+
+ /**
+ * Create a OPOIFSFileSystem from an InputStream. Normally the stream is read until
+ * EOF. The stream is always closed.
+ *
+ * Some streams are usable after reaching EOF (typically those that return true
+ * for markSupported()). In the unlikely case that the caller has such a stream
+ * and needs to use it after this constructor completes, a work around is to wrap the
+ * stream in order to trap the close() call. A convenience method (
+ * createNonClosingInputStream()) has been provided for this purpose:
+ *
+ * Note also the special case of ByteArrayInputStream for which the close()
+ * method does nothing.
+ *
+ * ByteArrayInputStream bais = ...
+ * HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
+ * bais.reset(); // no problem
+ * doSomethingElse(bais);
+ *
+ *
+ * @param stream the InputStream from which to read the data
+ *
+ * @exception IOException on errors reading, or on invalid data
+ */
+
+ public OPOIFSFileSystem(InputStream stream)
+ throws IOException
+ {
+ this();
+ boolean success = false;
+
+ HeaderBlock header_block;
+ RawDataBlockList data_blocks;
+ try {
+ // read the header block from the stream
+ header_block = new HeaderBlock(stream);
+ bigBlockSize = header_block.getBigBlockSize();
+
+ // read the rest of the stream into blocks
+ data_blocks = new RawDataBlockList(stream, bigBlockSize);
+ success = true;
+ } finally {
+ closeInputStream(stream, success);
+ }
+
+
+ // set up the block allocation table (necessary for the
+ // data_blocks to be manageable
+ new BlockAllocationTableReader(header_block.getBigBlockSize(),
+ header_block.getBATCount(),
+ header_block.getBATArray(),
+ header_block.getXBATCount(),
+ header_block.getXBATIndex(),
+ data_blocks);
+
+ // get property table from the document
+ PropertyTable properties =
+ new PropertyTable(header_block, data_blocks);
+
+ // init documents
+ processProperties(
+ SmallBlockTableReader.getSmallDocumentBlocks(
+ bigBlockSize, data_blocks, properties.getRoot(),
+ header_block.getSBATStart()
+ ),
+ data_blocks,
+ properties.getRoot().getChildren(),
+ null,
+ header_block.getPropertyStart()
+ );
+
+ // For whatever reason CLSID of root is always 0.
+ getRoot().setStorageClsid(properties.getRoot().getStorageClsid());
+ }
+ /**
+ * @param stream the stream to be closed
+ * @param success false if an exception is currently being thrown in the calling method
+ */
+ protected void closeInputStream(InputStream stream, boolean success) {
+
+ if(stream.markSupported() && !(stream instanceof ByteArrayInputStream)) {
+ String msg = "POIFS is closing the supplied input stream of type ("
+ + stream.getClass().getName() + ") which supports mark/reset. "
+ + "This will be a problem for the caller if the stream will still be used. "
+ + "If that is the case the caller should wrap the input stream to avoid this close logic. "
+ + "This warning is only temporary and will not be present in future versions of POI.";
+ _logger.log(POILogger.WARN, msg);
+ }
+ try {
+ stream.close();
+ } catch (IOException e) {
+ if(success) {
+ throw new RuntimeException(e);
+ }
+ // else not success? Try block did not complete normally
+ // just print stack trace and leave original ex to be thrown
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Checks that the supplied InputStream (which MUST
+ * support mark and reset, or be a PushbackInputStream)
+ * has a POIFS (OLE2) header at the start of it.
+ * If your InputStream does not support mark / reset,
+ * then wrap it in a PushBackInputStream, then be
+ * sure to always use that, and not the original!
+ * @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
+ */
+ public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
+ // We want to peek at the first 8 bytes
+ byte[] header = IOUtils.peekFirst8Bytes(inp);
+ return hasPOIFSHeader(header);
+ }
+ /**
+ * Checks if the supplied first 8 bytes of a stream / file
+ * has a POIFS (OLE2) header.
+ */
+ public static boolean hasPOIFSHeader(byte[] header8Bytes) {
+ LongField signature = new LongField(HeaderBlockConstants._signature_offset, header8Bytes);
+
+ // Did it match the signature?
+ return (signature.get() == HeaderBlockConstants._signature);
+ }
+
+ /**
+ * Create a new document to be added to the root directory
+ *
+ * @param stream the InputStream from which the document's data
+ * will be obtained
+ * @param name the name of the new POIFSDocument
+ *
+ * @return the new DocumentEntry
+ *
+ * @exception IOException on error creating the new POIFSDocument
+ */
+
+ public DocumentEntry createDocument(final InputStream stream,
+ final String name)
+ throws IOException
+ {
+ return getRoot().createDocument(name, stream);
+ }
+
+ /**
+ * create a new DocumentEntry in the root entry; the data will be
+ * provided later
+ *
+ * @param name the name of the new DocumentEntry
+ * @param size the size of the new DocumentEntry
+ * @param writer the writer of the new DocumentEntry
+ *
+ * @return the new DocumentEntry
+ *
+ * @exception IOException
+ */
+
+ public DocumentEntry createDocument(final String name, final int size,
+ final POIFSWriterListener writer)
+ throws IOException
+ {
+ return getRoot().createDocument(name, size, writer);
+ }
+
+ /**
+ * create a new DirectoryEntry in the root directory
+ *
+ * @param name the name of the new DirectoryEntry
+ *
+ * @return the new DirectoryEntry
+ *
+ * @exception IOException on name duplication
+ */
+
+ public DirectoryEntry createDirectory(final String name)
+ throws IOException
+ {
+ return getRoot().createDirectory(name);
+ }
+
+ /**
+ * Write the filesystem out
+ *
+ * @param stream the OutputStream to which the filesystem will be
+ * written
+ *
+ * @exception IOException thrown on errors writing to the stream
+ */
+
+ public void writeFilesystem(final OutputStream stream)
+ throws IOException
+ {
+
+ // get the property table ready
+ _property_table.preWrite();
+
+ // create the small block store, and the SBAT
+ SmallBlockTableWriter sbtw =
+ new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot());
+
+ // create the block allocation table
+ BlockAllocationTableWriter bat =
+ new BlockAllocationTableWriter(bigBlockSize);
+
+ // create a list of BATManaged objects: the documents plus the
+ // property table and the small block table
+ List bm_objects = new ArrayList();
+
+ bm_objects.addAll(_documents);
+ bm_objects.add(_property_table);
+ bm_objects.add(sbtw);
+ bm_objects.add(sbtw.getSBAT());
+
+ // walk the list, allocating space for each and assigning each
+ // a starting block number
+ Iterator iter = bm_objects.iterator();
+
+ while (iter.hasNext())
+ {
+ BATManaged bmo = ( BATManaged ) iter.next();
+ int block_count = bmo.countBlocks();
+
+ if (block_count != 0)
+ {
+ bmo.setStartBlock(bat.allocateSpace(block_count));
+ }
+ else
+ {
+
+ // Either the BATManaged object is empty or its data
+ // is composed of SmallBlocks; in either case,
+ // allocating space in the BAT is inappropriate
+ }
+ }
+
+ // allocate space for the block allocation table and take its
+ // starting block
+ int batStartBlock = bat.createBlocks();
+
+ // get the extended block allocation table blocks
+ HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize);
+ BATBlock[] xbat_blocks =
+ header_block_writer.setBATBlocks(bat.countBlocks(),
+ batStartBlock);
+
+ // set the property table start block
+ header_block_writer.setPropertyStart(_property_table.getStartBlock());
+
+ // set the small block allocation table start block
+ header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock());
+
+ // set the small block allocation table block count
+ header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount());
+
+ // the header is now properly initialized. Make a list of
+ // writers (the header block, followed by the documents, the
+ // property table, the small block store, the small block
+ // allocation table, the block allocation table, and the
+ // extended block allocation table blocks)
+ List writers = new ArrayList();
+
+ writers.add(header_block_writer);
+ writers.addAll(_documents);
+ writers.add(_property_table);
+ writers.add(sbtw);
+ writers.add(sbtw.getSBAT());
+ writers.add(bat);
+ for (int j = 0; j < xbat_blocks.length; j++)
+ {
+ writers.add(xbat_blocks[ j ]);
+ }
+
+ // now, write everything out
+ iter = writers.iterator();
+ while (iter.hasNext())
+ {
+ BlockWritable writer = ( BlockWritable ) iter.next();
+
+ writer.writeBlocks(stream);
+ }
+ }
+
+ /**
+ * read in a file and write it back out again
+ *
+ * @param args names of the files; arg[ 0 ] is the input file,
+ * arg[ 1 ] is the output file
+ *
+ * @exception IOException
+ */
+
+ public static void main(String args[])
+ throws IOException
+ {
+ if (args.length != 2)
+ {
+ System.err.println(
+ "two arguments required: input filename and output filename");
+ System.exit(1);
+ }
+ FileInputStream istream = new FileInputStream(args[ 0 ]);
+ FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
+
+ new OPOIFSFileSystem(istream).writeFilesystem(ostream);
+ istream.close();
+ ostream.close();
+ }
+
+ /**
+ * get the root entry
+ *
+ * @return the root entry
+ */
+
+ public DirectoryNode getRoot()
+ {
+ if (_root == null)
+ {
+ _root = new DirectoryNode(_property_table.getRoot(), this, null);
+ }
+ return _root;
+ }
+
+ /**
+ * open a document in the root entry's list of entries
+ *
+ * @param documentName the name of the document to be opened
+ *
+ * @return a newly opened DocumentInputStream
+ *
+ * @exception IOException if the document does not exist or the
+ * name is that of a DirectoryEntry
+ */
+
+ public DocumentInputStream createDocumentInputStream(
+ final String documentName)
+ throws IOException
+ {
+ return getRoot().createDocumentInputStream(documentName);
+ }
+
+ /**
+ * add a new POIFSDocument
+ *
+ * @param document the POIFSDocument being added
+ */
+
+ void addDocument(final OPOIFSDocument document)
+ {
+ _documents.add(document);
+ _property_table.addProperty(document.getDocumentProperty());
+ }
+
+ /**
+ * add a new DirectoryProperty
+ *
+ * @param directory the DirectoryProperty being added
+ */
+
+ void addDirectory(final DirectoryProperty directory)
+ {
+ _property_table.addProperty(directory);
+ }
+
+ /**
+ * remove an entry
+ *
+ * @param entry to be removed
+ */
+
+ void remove(EntryNode entry)
+ {
+ _property_table.removeProperty(entry.getProperty());
+ if (entry.isDocumentEntry())
+ {
+ _documents.remove((( DocumentNode ) entry).getDocument());
+ }
+ }
+
+ private void processProperties(final BlockList small_blocks,
+ final BlockList big_blocks,
+ final Iterator properties,
+ final DirectoryNode dir,
+ final int headerPropertiesStartAt)
+ throws IOException
+ {
+ while (properties.hasNext())
+ {
+ Property property = properties.next();
+ String name = property.getName();
+ DirectoryNode parent = (dir == null)
+ ? (( DirectoryNode ) getRoot())
+ : dir;
+
+ if (property.isDirectory())
+ {
+ DirectoryNode new_dir =
+ ( DirectoryNode ) parent.createDirectory(name);
+
+ new_dir.setStorageClsid( property.getStorageClsid() );
+
+ processProperties(
+ small_blocks, big_blocks,
+ (( DirectoryProperty ) property).getChildren(),
+ new_dir, headerPropertiesStartAt);
+ }
+ else
+ {
+ int startBlock = property.getStartBlock();
+ int size = property.getSize();
+ OPOIFSDocument document = null;
+
+ if (property.shouldUseSmallBlocks())
+ {
+ document =
+ new OPOIFSDocument(name,
+ small_blocks.fetchBlocks(startBlock, headerPropertiesStartAt),
+ size);
+ }
+ else
+ {
+ document =
+ new OPOIFSDocument(name,
+ big_blocks.fetchBlocks(startBlock, headerPropertiesStartAt),
+ size);
+ }
+ parent.createDocument(document);
+ }
+ }
+ }
+
+ /* ********** START begin implementation of POIFSViewable ********** */
+
+ /**
+ * Get an array of objects, some of which may implement
+ * POIFSViewable
+ *
+ * @return an array of Object; may not be null, but may be empty
+ */
+
+ public Object [] getViewableArray()
+ {
+ if (preferArray())
+ {
+ return (( POIFSViewable ) getRoot()).getViewableArray();
+ }
+ return new Object[ 0 ];
+ }
+
+ /**
+ * Get an Iterator of objects, some of which may implement
+ * POIFSViewable
+ *
+ * @return an Iterator; may not be null, but may have an empty
+ * back end store
+ */
+
+ public Iterator getViewableIterator()
+ {
+ if (!preferArray())
+ {
+ return (( POIFSViewable ) getRoot()).getViewableIterator();
+ }
+ return Collections.emptyList().iterator();
+ }
+
+ /**
+ * Give viewers a hint as to whether to call getViewableArray or
+ * getViewableIterator
+ *
+ * @return true if a viewer should call getViewableArray, false if
+ * a viewer should call getViewableIterator
+ */
+
+ public boolean preferArray()
+ {
+ return (( POIFSViewable ) getRoot()).preferArray();
+ }
+
+ /**
+ * Provides a short description of the object, to be used when a
+ * POIFSViewable object has not provided its contents.
+ *
+ * @return short description
+ */
+
+ public String getShortDescription()
+ {
+ return "POIFS FileSystem";
+ }
+
+ /**
+ * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+ */
+ public int getBigBlockSize() {
+ return bigBlockSize.getBigBlockSize();
+ }
+ /**
+ * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+ */
+ public POIFSBigBlockSize getBigBlockSizeDetails() {
+ return bigBlockSize;
+ }
+
+ /* ********** END begin implementation of POIFSViewable ********** */
+} // end public class OPOIFSFileSystem
+
diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
index 7169d91f9..5afb4eb8f 100644
--- a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
+++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
@@ -19,44 +19,22 @@
package org.apache.poi.poifs.filesystem;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PushbackInputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.poi.poifs.common.POIFSBigBlockSize;
-import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
-import org.apache.poi.poifs.property.DirectoryProperty;
-import org.apache.poi.poifs.property.Property;
-import org.apache.poi.poifs.property.PropertyTable;
-import org.apache.poi.poifs.storage.*;
import org.apache.poi.util.CloseIgnoringInputStream;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.LongField;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
/**
- * This is the main class of the POIFS system; it manages the entire
- * life cycle of the filesystem.
- *
- * @author Marc Johnson (mjohnson at apache dot org)
+ * Transition class for the move from {@link POIFSFileSystem} to
+ * {@link OPOIFSFileSystem}, and from {@link NPOIFSFileSystem} to
+ * {@link POIFSFileSystem}. Currently, this is OPOIFS-powered
*/
public class POIFSFileSystem
+ extends NPOIFSFileSystem // TODO Temporary workaround during #56791
implements POIFSViewable
{
- private static final POILogger _logger =
- POILogFactory.getLogger(POIFSFileSystem.class);
-
/**
* Convenience method for clients that want to avoid the auto-close behaviour of the constructor.
*/
@@ -64,26 +42,12 @@ public class POIFSFileSystem
return new CloseIgnoringInputStream(is);
}
- private PropertyTable _property_table;
- private List _documents;
- private DirectoryNode _root;
-
- /**
- * What big block size the file uses. Most files
- * use 512 bytes, but a few use 4096
- */
- private POIFSBigBlockSize bigBlockSize =
- POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
-
/**
* Constructor, intended for writing
*/
public POIFSFileSystem()
{
- HeaderBlock header_block = new HeaderBlock(bigBlockSize);
- _property_table = new PropertyTable(header_block);
- _documents = new ArrayList();
- _root = null;
+ super();
}
/**
@@ -118,76 +82,7 @@ public class POIFSFileSystem
public POIFSFileSystem(InputStream stream)
throws IOException
{
- this();
- boolean success = false;
-
- HeaderBlock header_block;
- RawDataBlockList data_blocks;
- try {
- // read the header block from the stream
- header_block = new HeaderBlock(stream);
- bigBlockSize = header_block.getBigBlockSize();
-
- // read the rest of the stream into blocks
- data_blocks = new RawDataBlockList(stream, bigBlockSize);
- success = true;
- } finally {
- closeInputStream(stream, success);
- }
-
-
- // set up the block allocation table (necessary for the
- // data_blocks to be manageable
- new BlockAllocationTableReader(header_block.getBigBlockSize(),
- header_block.getBATCount(),
- header_block.getBATArray(),
- header_block.getXBATCount(),
- header_block.getXBATIndex(),
- data_blocks);
-
- // get property table from the document
- PropertyTable properties =
- new PropertyTable(header_block, data_blocks);
-
- // init documents
- processProperties(
- SmallBlockTableReader.getSmallDocumentBlocks(
- bigBlockSize, data_blocks, properties.getRoot(),
- header_block.getSBATStart()
- ),
- data_blocks,
- properties.getRoot().getChildren(),
- null,
- header_block.getPropertyStart()
- );
-
- // For whatever reason CLSID of root is always 0.
- getRoot().setStorageClsid(properties.getRoot().getStorageClsid());
- }
- /**
- * @param stream the stream to be closed
- * @param success false if an exception is currently being thrown in the calling method
- */
- private void closeInputStream(InputStream stream, boolean success) {
-
- if(stream.markSupported() && !(stream instanceof ByteArrayInputStream)) {
- String msg = "POIFS is closing the supplied input stream of type ("
- + stream.getClass().getName() + ") which supports mark/reset. "
- + "This will be a problem for the caller if the stream will still be used. "
- + "If that is the case the caller should wrap the input stream to avoid this close logic. "
- + "This warning is only temporary and will not be present in future versions of POI.";
- _logger.log(POILogger.WARN, msg);
- }
- try {
- stream.close();
- } catch (IOException e) {
- if(success) {
- throw new RuntimeException(e);
- }
- // else not success? Try block did not complete normally
- // just print stack trace and leave original ex to be thrown
- e.printStackTrace();
- }
+ super(stream);
}
/**
@@ -200,180 +95,14 @@ public class POIFSFileSystem
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
*/
public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
- // We want to peek at the first 8 bytes
- inp.mark(8);
-
- byte[] header = new byte[8];
- IOUtils.readFully(inp, header);
- LongField signature = new LongField(HeaderBlockConstants._signature_offset, header);
-
- // Wind back those 8 bytes
- if(inp instanceof PushbackInputStream) {
- PushbackInputStream pin = (PushbackInputStream)inp;
- pin.unread(header);
- } else {
- inp.reset();
- }
-
- // Did it match the signature?
- return (signature.get() == HeaderBlockConstants._signature);
+ return NPOIFSFileSystem.hasPOIFSHeader(inp);
}
-
/**
- * Create a new document to be added to the root directory
- *
- * @param stream the InputStream from which the document's data
- * will be obtained
- * @param name the name of the new POIFSDocument
- *
- * @return the new DocumentEntry
- *
- * @exception IOException on error creating the new POIFSDocument
+ * Checks if the supplied first 8 bytes of a stream / file
+ * has a POIFS (OLE2) header.
*/
-
- public DocumentEntry createDocument(final InputStream stream,
- final String name)
- throws IOException
- {
- return getRoot().createDocument(name, stream);
- }
-
- /**
- * create a new DocumentEntry in the root entry; the data will be
- * provided later
- *
- * @param name the name of the new DocumentEntry
- * @param size the size of the new DocumentEntry
- * @param writer the writer of the new DocumentEntry
- *
- * @return the new DocumentEntry
- *
- * @exception IOException
- */
-
- public DocumentEntry createDocument(final String name, final int size,
- final POIFSWriterListener writer)
- throws IOException
- {
- return getRoot().createDocument(name, size, writer);
- }
-
- /**
- * create a new DirectoryEntry in the root directory
- *
- * @param name the name of the new DirectoryEntry
- *
- * @return the new DirectoryEntry
- *
- * @exception IOException on name duplication
- */
-
- public DirectoryEntry createDirectory(final String name)
- throws IOException
- {
- return getRoot().createDirectory(name);
- }
-
- /**
- * Write the filesystem out
- *
- * @param stream the OutputStream to which the filesystem will be
- * written
- *
- * @exception IOException thrown on errors writing to the stream
- */
-
- public void writeFilesystem(final OutputStream stream)
- throws IOException
- {
-
- // get the property table ready
- _property_table.preWrite();
-
- // create the small block store, and the SBAT
- SmallBlockTableWriter sbtw =
- new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot());
-
- // create the block allocation table
- BlockAllocationTableWriter bat =
- new BlockAllocationTableWriter(bigBlockSize);
-
- // create a list of BATManaged objects: the documents plus the
- // property table and the small block table
- List bm_objects = new ArrayList();
-
- bm_objects.addAll(_documents);
- bm_objects.add(_property_table);
- bm_objects.add(sbtw);
- bm_objects.add(sbtw.getSBAT());
-
- // walk the list, allocating space for each and assigning each
- // a starting block number
- Iterator iter = bm_objects.iterator();
-
- while (iter.hasNext())
- {
- BATManaged bmo = ( BATManaged ) iter.next();
- int block_count = bmo.countBlocks();
-
- if (block_count != 0)
- {
- bmo.setStartBlock(bat.allocateSpace(block_count));
- }
- else
- {
-
- // Either the BATManaged object is empty or its data
- // is composed of SmallBlocks; in either case,
- // allocating space in the BAT is inappropriate
- }
- }
-
- // allocate space for the block allocation table and take its
- // starting block
- int batStartBlock = bat.createBlocks();
-
- // get the extended block allocation table blocks
- HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize);
- BATBlock[] xbat_blocks =
- header_block_writer.setBATBlocks(bat.countBlocks(),
- batStartBlock);
-
- // set the property table start block
- header_block_writer.setPropertyStart(_property_table.getStartBlock());
-
- // set the small block allocation table start block
- header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock());
-
- // set the small block allocation table block count
- header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount());
-
- // the header is now properly initialized. Make a list of
- // writers (the header block, followed by the documents, the
- // property table, the small block store, the small block
- // allocation table, the block allocation table, and the
- // extended block allocation table blocks)
- List writers = new ArrayList();
-
- writers.add(header_block_writer);
- writers.addAll(_documents);
- writers.add(_property_table);
- writers.add(sbtw);
- writers.add(sbtw.getSBAT());
- writers.add(bat);
- for (int j = 0; j < xbat_blocks.length; j++)
- {
- writers.add(xbat_blocks[ j ]);
- }
-
- // now, write everything out
- iter = writers.iterator();
- while (iter.hasNext())
- {
- BlockWritable writer = ( BlockWritable ) iter.next();
-
- writer.writeBlocks(stream);
- }
+ public static boolean hasPOIFSHeader(byte[] header8Bytes) {
+ return NPOIFSFileSystem.hasPOIFSHeader(header8Bytes);
}
/**
@@ -388,216 +117,7 @@ public class POIFSFileSystem
public static void main(String args[])
throws IOException
{
- if (args.length != 2)
- {
- System.err.println(
- "two arguments required: input filename and output filename");
- System.exit(1);
- }
- FileInputStream istream = new FileInputStream(args[ 0 ]);
- FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
-
- new POIFSFileSystem(istream).writeFilesystem(ostream);
- istream.close();
- ostream.close();
+ OPOIFSFileSystem.main(args);
}
-
- /**
- * get the root entry
- *
- * @return the root entry
- */
-
- public DirectoryNode getRoot()
- {
- if (_root == null)
- {
- _root = new DirectoryNode(_property_table.getRoot(), this, null);
- }
- return _root;
- }
-
- /**
- * open a document in the root entry's list of entries
- *
- * @param documentName the name of the document to be opened
- *
- * @return a newly opened DocumentInputStream
- *
- * @exception IOException if the document does not exist or the
- * name is that of a DirectoryEntry
- */
-
- public DocumentInputStream createDocumentInputStream(
- final String documentName)
- throws IOException
- {
- return getRoot().createDocumentInputStream(documentName);
- }
-
- /**
- * add a new POIFSDocument
- *
- * @param document the POIFSDocument being added
- */
-
- void addDocument(final POIFSDocument document)
- {
- _documents.add(document);
- _property_table.addProperty(document.getDocumentProperty());
- }
-
- /**
- * add a new DirectoryProperty
- *
- * @param directory the DirectoryProperty being added
- */
-
- void addDirectory(final DirectoryProperty directory)
- {
- _property_table.addProperty(directory);
- }
-
- /**
- * remove an entry
- *
- * @param entry to be removed
- */
-
- void remove(EntryNode entry)
- {
- _property_table.removeProperty(entry.getProperty());
- if (entry.isDocumentEntry())
- {
- _documents.remove((( DocumentNode ) entry).getDocument());
- }
- }
-
- private void processProperties(final BlockList small_blocks,
- final BlockList big_blocks,
- final Iterator properties,
- final DirectoryNode dir,
- final int headerPropertiesStartAt)
- throws IOException
- {
- while (properties.hasNext())
- {
- Property property = properties.next();
- String name = property.getName();
- DirectoryNode parent = (dir == null)
- ? (( DirectoryNode ) getRoot())
- : dir;
-
- if (property.isDirectory())
- {
- DirectoryNode new_dir =
- ( DirectoryNode ) parent.createDirectory(name);
-
- new_dir.setStorageClsid( property.getStorageClsid() );
-
- processProperties(
- small_blocks, big_blocks,
- (( DirectoryProperty ) property).getChildren(),
- new_dir, headerPropertiesStartAt);
- }
- else
- {
- int startBlock = property.getStartBlock();
- int size = property.getSize();
- POIFSDocument document = null;
-
- if (property.shouldUseSmallBlocks())
- {
- document =
- new POIFSDocument(name,
- small_blocks.fetchBlocks(startBlock, headerPropertiesStartAt),
- size);
- }
- else
- {
- document =
- new POIFSDocument(name,
- big_blocks.fetchBlocks(startBlock, headerPropertiesStartAt),
- size);
- }
- parent.createDocument(document);
- }
- }
- }
-
- /* ********** START begin implementation of POIFSViewable ********** */
-
- /**
- * Get an array of objects, some of which may implement
- * POIFSViewable
- *
- * @return an array of Object; may not be null, but may be empty
- */
-
- public Object [] getViewableArray()
- {
- if (preferArray())
- {
- return (( POIFSViewable ) getRoot()).getViewableArray();
- }
- return new Object[ 0 ];
- }
-
- /**
- * Get an Iterator of objects, some of which may implement
- * POIFSViewable
- *
- * @return an Iterator; may not be null, but may have an empty
- * back end store
- */
-
- public Iterator getViewableIterator()
- {
- if (!preferArray())
- {
- return (( POIFSViewable ) getRoot()).getViewableIterator();
- }
- return Collections.emptyList().iterator();
- }
-
- /**
- * Give viewers a hint as to whether to call getViewableArray or
- * getViewableIterator
- *
- * @return true if a viewer should call getViewableArray, false if
- * a viewer should call getViewableIterator
- */
-
- public boolean preferArray()
- {
- return (( POIFSViewable ) getRoot()).preferArray();
- }
-
- /**
- * Provides a short description of the object, to be used when a
- * POIFSViewable object has not provided its contents.
- *
- * @return short description
- */
-
- public String getShortDescription()
- {
- return "POIFS FileSystem";
- }
-
- /**
- * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
- */
- public int getBigBlockSize() {
- return bigBlockSize.getBigBlockSize();
- }
- /**
- * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
- */
- public POIFSBigBlockSize getBigBlockSizeDetails() {
- return bigBlockSize;
- }
-
- /* ********** END begin implementation of POIFSViewable ********** */
-} // end public class POIFSFileSystem
+}
diff --git a/src/java/org/apache/poi/poifs/property/DirectoryProperty.java b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java
index a73221af2..d86e73ada 100644
--- a/src/java/org/apache/poi/poifs/property/DirectoryProperty.java
+++ b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java
@@ -28,10 +28,8 @@ import java.util.Set;
/**
* Directory property
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
-public class DirectoryProperty extends Property implements Parent { // TODO - fix instantiable superclass
+public class DirectoryProperty extends Property implements Parent, Iterable { // TODO - fix instantiable superclass
/** List of Property instances */
private List _children;
@@ -241,6 +239,13 @@ public class DirectoryProperty extends Property implements Parent { // TODO - fi
{
return _children.iterator();
}
+ /**
+ * Get an iterator over the children of this Parent, alias for
+ * {@link #getChildren()} which supports foreach use
+ */
+ public Iterator iterator() {
+ return getChildren();
+ }
/**
* Add a new child to the collection of children
diff --git a/src/java/org/apache/poi/poifs/property/DocumentProperty.java b/src/java/org/apache/poi/poifs/property/DocumentProperty.java
index 67c8b0307..3ba3c0889 100644
--- a/src/java/org/apache/poi/poifs/property/DocumentProperty.java
+++ b/src/java/org/apache/poi/poifs/property/DocumentProperty.java
@@ -19,12 +19,10 @@
package org.apache.poi.poifs.property;
-import org.apache.poi.poifs.filesystem.POIFSDocument;
+import org.apache.poi.poifs.filesystem.OPOIFSDocument;
/**
* Trivial extension of Property for POIFSDocuments
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public class DocumentProperty
@@ -32,7 +30,7 @@ public class DocumentProperty
{
// the POIFSDocument this property is associated with
- private POIFSDocument _document;
+ private OPOIFSDocument _document;
/**
* Constructor
@@ -72,7 +70,7 @@ public class DocumentProperty
* @param doc the associated POIFSDocument
*/
- public void setDocument(POIFSDocument doc)
+ public void setDocument(OPOIFSDocument doc)
{
_document = doc;
}
@@ -83,7 +81,7 @@ public class DocumentProperty
* @return the associated document
*/
- public POIFSDocument getDocument()
+ public OPOIFSDocument getDocument()
{
return _document;
}
diff --git a/src/java/org/apache/poi/poifs/property/PropertyTable.java b/src/java/org/apache/poi/poifs/property/PropertyTable.java
index 45a973415..75ca4a03b 100644
--- a/src/java/org/apache/poi/poifs/property/PropertyTable.java
+++ b/src/java/org/apache/poi/poifs/property/PropertyTable.java
@@ -21,14 +21,13 @@ import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.storage.BlockWritable;
import org.apache.poi.poifs.storage.HeaderBlock;
import org.apache.poi.poifs.storage.PropertyBlock;
import org.apache.poi.poifs.storage.RawDataBlockList;
/**
- * This class embodies the Property Table for the {@link POIFSFileSystem};
+ * This class embodies the Property Table for the {@link org.apache.poi.poifs.filesystem.POIFSFileSystem};
* this is basically the directory for all of the documents in the
* filesystem.
*
diff --git a/src/java/org/apache/poi/poifs/property/PropertyTableBase.java b/src/java/org/apache/poi/poifs/property/PropertyTableBase.java
index b3690c5c2..477cf036d 100644
--- a/src/java/org/apache/poi/poifs/property/PropertyTableBase.java
+++ b/src/java/org/apache/poi/poifs/property/PropertyTableBase.java
@@ -111,6 +111,11 @@ public abstract class PropertyTableBase implements BATManaged {
while (!children.empty())
{
Property property = children.pop();
+ if (property == null)
+ {
+ // unknown / unsupported / corrupted property, skip
+ continue;
+ }
root.addChild(property);
if (property.isDirectory())
diff --git a/src/java/org/apache/poi/poifs/property/RootProperty.java b/src/java/org/apache/poi/poifs/property/RootProperty.java
index b934a2601..5a8f3d52e 100644
--- a/src/java/org/apache/poi/poifs/property/RootProperty.java
+++ b/src/java/org/apache/poi/poifs/property/RootProperty.java
@@ -22,8 +22,6 @@ import org.apache.poi.poifs.storage.SmallDocumentBlock;
/**
* Root property
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public final class RootProperty extends DirectoryProperty {
private static final String NAME = "Root Entry";
diff --git a/src/java/org/apache/poi/poifs/storage/BATBlock.java b/src/java/org/apache/poi/poifs/storage/BATBlock.java
index 8712e65f6..53099644a 100644
--- a/src/java/org/apache/poi/poifs/storage/BATBlock.java
+++ b/src/java/org/apache/poi/poifs/storage/BATBlock.java
@@ -30,8 +30,6 @@ import org.apache.poi.util.LittleEndian;
/**
* A block of block allocation table entries. BATBlocks are created
* only through a static factory method: createBATBlocks.
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public final class BATBlock extends BigBlock {
/**
@@ -301,6 +299,21 @@ public final class BATBlock extends BigBlock {
public boolean hasFreeSectors() {
return _has_free_sectors;
}
+ /**
+ * How many sectors in this block are taken?
+ * Note that calling {@link #hasFreeSectors()} is much quicker
+ */
+ public int getUsedSectors(boolean isAnXBAT) {
+ int usedSectors = 0;
+ int toCheck = _values.length;
+ if (isAnXBAT) toCheck--; // Last is a chain location
+ for(int k=0; k= _values.length) {
diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java
index 8b6efd36e..2f9528318 100644
--- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java
+++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java
@@ -25,13 +25,66 @@ import org.apache.poi.poifs.property.RootProperty;
/**
* This class implements reading the small document block list from an
* existing file
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public final class SmallBlockTableReader {
+ private static BlockList prepareSmallDocumentBlocks(
+ final POIFSBigBlockSize bigBlockSize,
+ final RawDataBlockList blockList, final RootProperty root,
+ final int sbatStart)
+ throws IOException
+ {
+ // Fetch the blocks which hold the Small Blocks stream
+ ListManagedBlock [] smallBlockBlocks =
+ blockList.fetchBlocks(root.getStartBlock(), -1);
+
+ // Turn that into a list
+ BlockList list =new SmallDocumentBlockList(
+ SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks));
+
+ return list;
+ }
+ private static BlockAllocationTableReader prepareReader(
+ final POIFSBigBlockSize bigBlockSize,
+ final RawDataBlockList blockList, final BlockList list,
+ final RootProperty root, final int sbatStart)
+ throws IOException
+ {
+ // Process the SBAT and blocks
+ return new BlockAllocationTableReader(bigBlockSize,
+ blockList.fetchBlocks(sbatStart, -1),
+ list);
+ }
+
+ /**
+ * Fetch the small document block reader from an existing file, normally
+ * needed for debugging and low level dumping. You should typically call
+ * {@link #getSmallDocumentBlocks(POIFSBigBlockSize, RawDataBlockList, RootProperty, int)}
+ * instead.
+ *
+ * @param blockList the raw data from which the small block table
+ * will be extracted
+ * @param root the root property (which contains the start block
+ * and small block table size)
+ * @param sbatStart the start block of the SBAT
+ *
+ * @return the small document block reader
+ *
+ * @exception IOException
+ */
+ public static BlockAllocationTableReader _getSmallDocumentBlockReader(
+ final POIFSBigBlockSize bigBlockSize,
+ final RawDataBlockList blockList, final RootProperty root,
+ final int sbatStart)
+ throws IOException
+ {
+ BlockList list = prepareSmallDocumentBlocks(
+ bigBlockSize, blockList, root, sbatStart);
+ return prepareReader(
+ bigBlockSize, blockList, list, root, sbatStart);
+ }
/**
- * fetch the small document block list from an existing file
+ * Fetch the small document block list from an existing file
*
* @param blockList the raw data from which the small block table
* will be extracted
@@ -49,18 +102,9 @@ public final class SmallBlockTableReader {
final int sbatStart)
throws IOException
{
- // Fetch the blocks which hold the Small Blocks stream
- ListManagedBlock [] smallBlockBlocks =
- blockList.fetchBlocks(root.getStartBlock(), -1);
-
- // Turn that into a list
- BlockList list =new SmallDocumentBlockList(
- SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks));
-
- // Process
- new BlockAllocationTableReader(bigBlockSize,
- blockList.fetchBlocks(sbatStart, -1),
- list);
+ BlockList list = prepareSmallDocumentBlocks(
+ bigBlockSize, blockList, root, sbatStart);
+ prepareReader(bigBlockSize, blockList, list, root, sbatStart);
return list;
}
}
diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
index 2db7bf4c7..9c98bb459 100644
--- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
+++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
@@ -22,7 +22,7 @@ package org.apache.poi.poifs.storage;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
-import org.apache.poi.poifs.filesystem.POIFSDocument;
+import org.apache.poi.poifs.filesystem.OPOIFSDocument;
import org.apache.poi.poifs.property.RootProperty;
import java.util.*;
@@ -40,7 +40,7 @@ public class SmallBlockTableWriter
implements BlockWritable, BATManaged
{
private BlockAllocationTableWriter _sbat;
- private List _small_blocks;
+ private List _small_blocks;
private int _big_block_count;
private RootProperty _root;
@@ -50,20 +50,17 @@ public class SmallBlockTableWriter
* @param documents a List of POIFSDocument instances
* @param root the Filesystem's root property
*/
-
public SmallBlockTableWriter(final POIFSBigBlockSize bigBlockSize,
- final List documents,
+ final List documents,
final RootProperty root)
{
_sbat = new BlockAllocationTableWriter(bigBlockSize);
- _small_blocks = new ArrayList();
+ _small_blocks = new ArrayList();
_root = root;
- Iterator iter = documents.iterator();
- while (iter.hasNext())
+ for (OPOIFSDocument doc : documents)
{
- POIFSDocument doc = ( POIFSDocument ) iter.next();
- BlockWritable[] blocks = doc.getSmallBlocks();
+ SmallDocumentBlock[] blocks = doc.getSmallBlocks();
if (blocks.length != 0)
{
@@ -143,11 +140,8 @@ public class SmallBlockTableWriter
public void writeBlocks(final OutputStream stream)
throws IOException
{
- Iterator iter = _small_blocks.iterator();
-
- while (iter.hasNext())
- {
- (( BlockWritable ) iter.next()).writeBlocks(stream);
+ for (BlockWritable block : _small_blocks) {
+ block.writeBlocks(stream);
}
}
diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
index 8c726caa0..d09bf9ecf 100644
--- a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
+++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
@@ -29,8 +29,6 @@ import org.apache.poi.poifs.common.POIFSBigBlockSize;
/**
* Storage for documents that are too small to use regular
* DocumentBlocks for their data
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock {
private static final int BLOCK_SHIFT = 6;
@@ -49,7 +47,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
System.arraycopy(data, index * _block_size, _data, 0, _block_size);
}
- private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize)
+ protected SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize)
{
_bigBlockSize = bigBlockSize;
_blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
@@ -110,7 +108,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
*
* @return number of big blocks the list encompasses
*/
- public static int fill(POIFSBigBlockSize bigBlockSize, List blocks)
+ public static int fill(POIFSBigBlockSize bigBlockSize, List blocks)
{
int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
@@ -168,12 +166,12 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
*
* @return a List of SmallDocumentBlock's extracted from the input
*/
- public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks)
+ public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks)
throws IOException
{
int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
- List sdbs = new ArrayList();
+ List sdbs = new ArrayList();
for (int j = 0; j < blocks.length; j++)
{
@@ -204,6 +202,11 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
{
return size * _block_size;
}
+
+ protected int getSmallBlocksPerBigBlock()
+ {
+ return _blocks_per_big_block;
+ }
private static SmallDocumentBlock makeEmptySmallDocumentBlock(POIFSBigBlockSize bigBlockSize)
{
diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java
index a510f8e8f..cc6bb7c17 100644
--- a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java
+++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java
@@ -23,24 +23,19 @@ import java.util.*;
/**
* A list of SmallDocumentBlocks instances, and methods to manage the list
- *
- * @author Marc Johnson (mjohnson at apache dot org)
*/
-
public class SmallDocumentBlockList
extends BlockListImpl
{
-
/**
* Constructor SmallDocumentBlockList
*
* @param blocks a list of SmallDocumentBlock instances
*/
- public SmallDocumentBlockList(final List blocks)
+ public SmallDocumentBlockList(final List blocks)
{
- setBlocks(( SmallDocumentBlock [] ) blocks
- .toArray(new SmallDocumentBlock[ blocks.size() ]));
+ setBlocks(blocks.toArray(new SmallDocumentBlock[blocks.size()]));
}
-} // end public class SmallDocumentBlockList
+}
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java b/src/java/org/apache/poi/sl/draw/DrawAutoShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java
rename to src/java/org/apache/poi/sl/draw/DrawAutoShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawBackground.java b/src/java/org/apache/poi/sl/draw/DrawBackground.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawBackground.java
rename to src/java/org/apache/poi/sl/draw/DrawBackground.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawConnectorShape.java b/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawConnectorShape.java
rename to src/java/org/apache/poi/sl/draw/DrawConnectorShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java b/src/java/org/apache/poi/sl/draw/DrawFactory.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java
rename to src/java/org/apache/poi/sl/draw/DrawFactory.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFontManager.java b/src/java/org/apache/poi/sl/draw/DrawFontManager.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFontManager.java
rename to src/java/org/apache/poi/sl/draw/DrawFontManager.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFreeformShape.java b/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFreeformShape.java
rename to src/java/org/apache/poi/sl/draw/DrawFreeformShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java b/src/java/org/apache/poi/sl/draw/DrawGroupShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java
rename to src/java/org/apache/poi/sl/draw/DrawGroupShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java
rename to src/java/org/apache/poi/sl/draw/DrawMasterSheet.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java
rename to src/java/org/apache/poi/sl/draw/DrawPaint.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPictureShape.java b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawPictureShape.java
rename to src/java/org/apache/poi/sl/draw/DrawPictureShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java b/src/java/org/apache/poi/sl/draw/DrawShape.java
similarity index 96%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java
rename to src/java/org/apache/poi/sl/draw/DrawShape.java
index c2c9b5f68..13ef4292a 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java
+++ b/src/java/org/apache/poi/sl/draw/DrawShape.java
@@ -21,7 +21,6 @@ import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
-import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.Shape;
@@ -73,7 +72,7 @@ public class DrawShape implements Drawable {
// and later on, turn it around again to compare it with its original size ...
AffineTransform txs;
- if (ps instanceof HSLFShape) {
+ if (ps.getClass().getCanonicalName().toLowerCase().contains("hslf")) {
txs = new AffineTransform(tx);
} else {
// this handling is only based on try and error ... not sure why xslf is handled differently.
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java b/src/java/org/apache/poi/sl/draw/DrawSheet.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java
rename to src/java/org/apache/poi/sl/draw/DrawSheet.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java
rename to src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java b/src/java/org/apache/poi/sl/draw/DrawSlide.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java
rename to src/java/org/apache/poi/sl/draw/DrawSlide.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTableShape.java b/src/java/org/apache/poi/sl/draw/DrawTableShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTableShape.java
rename to src/java/org/apache/poi/sl/draw/DrawTableShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextBox.java b/src/java/org/apache/poi/sl/draw/DrawTextBox.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextBox.java
rename to src/java/org/apache/poi/sl/draw/DrawTextBox.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java
rename to src/java/org/apache/poi/sl/draw/DrawTextFragment.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextParagraph.java
rename to src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java b/src/java/org/apache/poi/sl/draw/DrawTextShape.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java
rename to src/java/org/apache/poi/sl/draw/DrawTextShape.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/Drawable.java b/src/java/org/apache/poi/sl/draw/Drawable.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/Drawable.java
rename to src/java/org/apache/poi/sl/draw/Drawable.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/ImageRenderer.java b/src/java/org/apache/poi/sl/draw/ImageRenderer.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/ImageRenderer.java
rename to src/java/org/apache/poi/sl/draw/ImageRenderer.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/PathGradientPaint.java b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/PathGradientPaint.java
rename to src/java/org/apache/poi/sl/draw/PathGradientPaint.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java
similarity index 93%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java
rename to src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java
index 32ee2a03b..d7fc0ae07 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java
@@ -45,9 +45,9 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_AdjPoint2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTAdjPoint2D {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "x", required = true)
protected String x;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "y", required = true)
protected String y;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java
similarity index 96%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java
rename to src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java
index c5ef7860b..d684cccb7 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java
@@ -53,8 +53,8 @@ import javax.xml.bind.annotation.XmlType;
public class CTAdjustHandleList {
@XmlElements({
- @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class),
- @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class)
+ @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class),
+ @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class)
})
protected List ahXYOrAhPolar;
@@ -76,8 +76,8 @@ public class CTAdjustHandleList {
*
*
* Objects of the following type(s) are allowed in the list
- * {@link CTPolarAdjustHandle }
* {@link CTXYAdjustHandle }
+ * {@link CTPolarAdjustHandle }
*
*
*/
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java
similarity index 94%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java
rename to src/java/org/apache/poi/sl/draw/binding/CTAngle.java
index 2e39602da..2da2373e2 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java
@@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_Angle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTAngle {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "val", required = true)
protected int val;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColor.java b/src/java/org/apache/poi/sl/draw/binding/CTColor.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColor.java
rename to src/java/org/apache/poi/sl/draw/binding/CTColor.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java
similarity index 97%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java
rename to src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java
index fb3e2cc61..8ec68ba08 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java
@@ -52,12 +52,12 @@ import javax.xml.bind.annotation.XmlType;
public class CTColorMRU {
@XmlElements({
- @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class),
- @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class),
- @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class),
@XmlElement(name = "scrgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTScRgbColor.class),
- @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class),
- @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class)
+ @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class),
+ @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class),
+ @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class),
+ @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class),
+ @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class)
})
protected List egColorChoice;
@@ -79,12 +79,12 @@ public class CTColorMRU {
*
*
* Objects of the following type(s) are allowed in the list
- * {@link CTHslColor }
- * {@link CTSRgbColor }
- * {@link CTSchemeColor }
* {@link CTScRgbColor }
- * {@link CTPresetColor }
+ * {@link CTSRgbColor }
+ * {@link CTHslColor }
* {@link CTSystemColor }
+ * {@link CTSchemeColor }
+ * {@link CTPresetColor }
*
*
*/
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTComplementTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTComplementTransform.java
rename to src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java
similarity index 93%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java
rename to src/java/org/apache/poi/sl/draw/binding/CTConnection.java
index 4af3fac71..f5d5e1726 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java
@@ -46,9 +46,9 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_Connection", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTConnection {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "id", required = true)
protected long id;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "idx", required = true)
@XmlSchemaType(name = "unsignedInt")
protected long idx;
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java
similarity index 95%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java
rename to src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java
index 7ec62972d..eae59a0f0 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java
@@ -52,7 +52,7 @@ public class CTConnectionSite {
@XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true)
protected CTAdjPoint2D pos;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "ang", required = true)
protected String ang;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java
rename to src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java b/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java
rename to src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java
similarity index 91%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java
rename to src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java
index 94d44ece2..8787125f4 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java
@@ -46,11 +46,11 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_EmbeddedWAVAudioFile", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTEmbeddedWAVAudioFile {
- @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true)
+ @XmlAttribute(name = "embed", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true)
protected String embed;
- @XmlAttribute
+ @XmlAttribute(name = "name")
protected String name;
- @XmlAttribute
+ @XmlAttribute(name = "builtIn")
protected Boolean builtIn;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java
similarity index 94%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java
rename to src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java
index 92f41aee8..d1ed283f5 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java
@@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_FixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTFixedPercentage {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "val", required = true)
protected int val;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGammaTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGammaTransform.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java
similarity index 93%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java
index 3df22093c..5622e4c28 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java
@@ -47,10 +47,10 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlType(name = "CT_GeomGuide", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTGeomGuide {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "name", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String name;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "fmla", required = true)
protected String fmla;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuideList.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuideList.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java
similarity index 92%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java
index b1368be29..3198f0410 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java
@@ -47,13 +47,13 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "CT_GeomRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
public class CTGeomRect {
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "l", required = true)
protected String l;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "t", required = true)
protected String t;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "r", required = true)
protected String r;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "b", required = true)
protected String b;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java
similarity index 100%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java
similarity index 94%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java
rename to src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java
index 6508613b1..f06e1d8f9 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java
@@ -66,11 +66,11 @@ public class CTGroupTransform2D {
protected CTPoint2D chOff;
@XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main")
protected CTPositiveSize2D chExt;
- @XmlAttribute
+ @XmlAttribute(name = "rot")
protected Integer rot;
- @XmlAttribute
+ @XmlAttribute(name = "flipH")
protected Boolean flipH;
- @XmlAttribute
+ @XmlAttribute(name = "flipV")
protected Boolean flipV;
/**
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java
similarity index 90%
rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java
rename to src/java/org/apache/poi/sl/draw/binding/CTHslColor.java
index c5bca5aec..376d423ee 100644
--- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java
+++ b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java
@@ -57,41 +57,41 @@ import javax.xml.bind.annotation.XmlType;
public class CTHslColor {
@XmlElementRefs({
- @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class),
- @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class)
+ @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false),
+ @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false)
})
protected List> egColorTransform;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "hue", required = true)
protected int hue;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "sat", required = true)
protected int sat;
- @XmlAttribute(required = true)
+ @XmlAttribute(name = "lum", required = true)
protected int lum;
/**
@@ -112,34 +112,34 @@ public class CTHslColor {
*
*