return result;
}
- private class PropertyComparator
+ public static class PropertyComparator
implements Comparator
{
public int compare(Object o1, Object o2)
{
+ String VBA_PROJECT = "_VBA_PROJECT";
String name1 = (( Property ) o1).getName();
String name2 = (( Property ) o2).getName();
- int result = name1.length() - name2.length();
+ int result = name1.length() - name2.length();
if (result == 0)
{
- result = name1.compareTo(name2);
+ // _VBA_PROJECT, it seems, will always come last
+ if (name1.compareTo(VBA_PROJECT) == 0)
+ result = 1;
+ else if (name2.compareTo(VBA_PROJECT) == 0)
+ result = -1;
+ else
+ {
+ if (name1.startsWith("__") && name2.startsWith("__"))
+ {
+ // Betweeen __SRP_0 and __SRP_1 just sort as normal
+ result = name1.compareToIgnoreCase(name2);
+ }
+ else if (name1.startsWith("__"))
+ {
+ // If only name1 is __XXX then this will be placed after name2
+ result = 1;
+ }
+ else if (name2.startsWith("__"))
+ {
+ // If only name2 is __XXX then this will be placed after name1
+ result = -1;
+ }
+ else
+ // result = name1.compareTo(name2);
+ // The default case is to sort names ignoring case
+ result = name1.compareToIgnoreCase(name2);
+ }
}
return result;
}
--- /dev/null
+\r
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.poifs.filesystem;\r
+\r
+import junit.framework.TestCase;\r
+import junit.framework.ComparisonFailure;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+import org.apache.poi.poifs.property.DirectoryProperty;\r
+import org.apache.poi.poifs.property.Property;\r
+\r
+/**\r
+ * Verify the order of entries <code>DirectoryProperty</code> .\r
+ * <p>\r
+ * In particular it is important to serialize ROOT._VBA_PROJECT_CUR.VBA node.\r
+ * See bug 39234 in bugzilla. Thanks to Bill Seddon for providing the solution.\r
+ * </p>\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestPropertySorter extends TestCase {\r
+\r
+ //the correct order of entries in the test file\r
+ protected static final String[] _entries = {\r
+ "dir", "JML", "UTIL", "Loader", "Sheet1", "Sheet2", "Sheet3",\r
+ "__SRP_0", "__SRP_1", "__SRP_2", "__SRP_3", "__SRP_4", "__SRP_5",\r
+ "ThisWorkbook", "_VBA_PROJECT",\r
+ };\r
+\r
+ protected File testFile;\r
+\r
+ public void setUp(){\r
+ String home = System.getProperty("HSSF.testdata.path");\r
+ testFile = new File(home + "/39234.xls");\r
+ }\r
+\r
+ /**\r
+ * Test sorting of properties in <code>DirectoryProperty</code>\r
+ */\r
+ public void testSortProperties() throws IOException {\r
+ InputStream is = new FileInputStream(testFile);\r
+ POIFSFileSystem fs = new POIFSFileSystem(is);\r
+ is.close();\r
+ Property[] props = getVBAProperties(fs);\r
+\r
+ assertEquals(_entries.length, props.length);\r
+\r
+ // (1). See that there is a problem with the old case-sensitive property comparartor\r
+ Arrays.sort(props, new CaseSensitivePropertyComparator());\r
+ try {\r
+ for (int i = 0; i < props.length; i++) {\r
+ assertEquals(_entries[i], props[i].getName());\r
+ }\r
+ fail("case-sensitive property comparator returns properties in wrong order");\r
+ } catch (ComparisonFailure e){\r
+ ; // as expected\r
+ }\r
+\r
+ // (2) Verify that the fixed proeprty comparator works right\r
+ Arrays.sort(props, new DirectoryProperty.PropertyComparator());\r
+ for (int i = 0; i < props.length; i++) {\r
+ assertEquals(_entries[i], props[i].getName());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Serialize file system and verify that the order of properties is the same as in the original file.\r
+ */\r
+ public void testSerialization() throws IOException {\r
+ InputStream is = new FileInputStream(testFile);\r
+ POIFSFileSystem fs = new POIFSFileSystem(is);\r
+ is.close();\r
+\r
+ ByteArrayOutputStream out = new ByteArrayOutputStream();\r
+ fs.writeFilesystem(out);\r
+ out.close();\r
+ is = new ByteArrayInputStream(out.toByteArray());\r
+ fs = new POIFSFileSystem(is);\r
+ is.close();\r
+ Property[] props = getVBAProperties(fs);\r
+ Arrays.sort(props, new DirectoryProperty.PropertyComparator());\r
+\r
+ assertEquals(_entries.length, props.length);\r
+ for (int i = 0; i < props.length; i++) {\r
+ assertEquals(_entries[i], props[i].getName());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return array of properties read from ROOT._VBA_PROJECT_CUR.VBA node\r
+ */\r
+ protected Property[] getVBAProperties(POIFSFileSystem fs) throws IOException {\r
+ String _VBA_PROJECT_CUR = "_VBA_PROJECT_CUR";\r
+ String VBA = "VBA";\r
+\r
+ DirectoryEntry root = fs.getRoot();\r
+ DirectoryEntry vba_project = (DirectoryEntry)root.getEntry(_VBA_PROJECT_CUR);\r
+\r
+ DirectoryNode vba = (DirectoryNode)vba_project.getEntry(VBA);\r
+ DirectoryProperty p = (DirectoryProperty)vba.getProperty();\r
+\r
+ ArrayList lst = new ArrayList();\r
+ for (Iterator it = p.getChildren(); it.hasNext();){\r
+ Property ch = (Property)it.next();\r
+ lst.add(ch);\r
+ }\r
+ return (Property [])lst.toArray(new Property[ 0 ]);\r
+ }\r
+\r
+ /**\r
+ * Old version of case-sensitive PropertyComparator to demonstrate the problem\r
+ */\r
+ private class CaseSensitivePropertyComparator implements Comparator\r
+ {\r
+\r
+ public boolean equals(Object o)\r
+ {\r
+ return this == o;\r
+ }\r
+\r
+ public int compare(Object o1, Object o2)\r
+ {\r
+ String name1 = (( Property ) o1).getName();\r
+ String name2 = (( Property ) o2).getName();\r
+ int result = name1.length() - name2.length();\r
+\r
+ if (result == 0)\r
+ {\r
+ result = name1.compareTo(name2);\r
+ }\r
+ return result;\r
+ }\r
+ }\r
+\r
+}\r