Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrContentHandler.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrContentHandler.java (revision 2370) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrContentHandler.java (working copy) @@ -480,7 +480,14 @@ class JcrContentHandler extends DefaultHandler { properties.put(name, values); } if (propertyType == PropertyType.BINARY) { - ByteArrayInputStream is = new ByteArrayInputStream(Base64.decode(value, Base64.URL_SAFE)); + byte[] binary = null; + try { + binary = Base64.decode(value.getBytes("UTF-8")); + } catch (IOException e) { + // try re-reading, in case this was an export from a prior ModeShape version that used URL_SAFE ... + binary = Base64.decode(value, Base64.URL_SAFE); + } + ByteArrayInputStream is = new ByteArrayInputStream(binary); values.add(valueFor(is)); } else { if (decoder != null) value = decoder.decode(value); Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSystemViewExporter.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSystemViewExporter.java (revision 2370) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSystemViewExporter.java (working copy) @@ -262,7 +262,7 @@ class JcrSystemViewExporter extends AbstractJcrExporter { Binary binary = value.getBinary(); try { - InputStream stream = new Base64.InputStream(binary.getStream(), Base64.ENCODE | Base64.URL_SAFE); + InputStream stream = new Base64.InputStream(binary.getStream(), Base64.ENCODE); while (-1 != (len = stream.read(bytes))) { contentHandler.characters(new String(bytes, 0, len).toCharArray(), 0, len); } @@ -304,7 +304,7 @@ class JcrSystemViewExporter extends AbstractJcrExporter { startElement(contentHandler, JcrSvLexicon.VALUE, valueAtts); try { - chars = Base64.encodeBytes(value.getBytes(), Base64.URL_SAFE).toCharArray(); + chars = Base64.encodeBytes(value.getBytes("UTF-8")).toCharArray(); } catch (IOException ioe) { throw new RepositoryException(ioe); } Index: modeshape-jcr/src/test/java/org/modeshape/jcr/JcrImportExportTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/JcrImportExportTest.java (revision 2370) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/JcrImportExportTest.java (working copy) @@ -26,6 +26,7 @@ package org.modeshape.jcr; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -424,6 +425,67 @@ public class JcrImportExportTest { assertNode("/page1"); } + @Test + public void shouldImportFileExportedFromJackrabbitContainingBinaryData() throws Exception { + // Load the Magnolia CND file ... + CndNodeTypeReader cndReader = new CndNodeTypeReader(session); + cndReader.read("magnolia.cnd"); + session.getWorkspace().getNodeTypeManager().registerNodeTypes(cndReader.getNodeTypeDefinitions(), false); + assertThat(session.getWorkspace().getNodeTypeManager().getNodeType("mgnl:content"), is(notNullValue())); + + // Now import the file ... + String filename = "io/system-export-with-binary-data-and-uuids.xml"; + assertImport(filename, "/a", ImportBehavior.THROW); // no matching UUIDs expected + } + + @Test + public void shouldDecodeBase64() throws Exception { + String base64Str = "R0lGODlhEAAQAMZpAGxZMW1bNW9bMm9cNnJdNXJdNnNfN3tnPX5oQIBqQYJrO4FrQoVtQIZuQohxQopyRopzQYtzRo10Qo51SI12SJB3SZN5Q5N5RpV7TJZ8TJd9SJh+TpyAT52CUJ+FUaOGU6OHUaSIUqGKUqaJVaiKVaGMV6mLVqWOXqyOVayOWLCSWa2VWrSVW7aXXbSbXbqaXrqaX7uaX7ubXsCfYrigcMKgY8OhY8SiZMWjZMWjZcelZsimZsqnZ8unZ8uoaMypaM2pac6qacOtbc+ratCsatKta8uwbdGvctOvbtSvbNWwbciyhdaxbdm2dda7ddq5gd26fN28gNe/ed6+htvCeuHAhd3EfOLCidrDmd7GfuLEj9/HfubKlufLmOjLmOnMmOnNmujNne3UpuzUqe3Vp+7VqO/VqO/Wqe7YsP///////////////////////////////////////////////////////////////////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAH8ALAAAAAAQABAAAAeJgH+Cg4SFhoeIiYqLhSciiR40S1hoY0JZVE5GK4MOZWdmZGJhJVumW1aDFGBfXl1cWiRSp1sufxYXV1VQUVNPMSAYDwgHEINNTEpJSEcwKR0VCwWERURDQUA9LSYcEwkDhD8+PDs6OCwjGxEIAYQyOTc2NTMqHxkNBgCFChIaKC8hGBBgJIARo0AAOw=="; + boolean print = false; + + // Try apache ... + byte[] apacheBytes = org.apache.util.Base64.decode(base64Str.getBytes("UTF-8")); + if (print) { + System.out.println("Apache: " + toString(apacheBytes)); + System.out.println(" length: " + apacheBytes.length); + } + + // Try jboss ... + byte[] jbossBytes = org.jboss.util.Base64.decode(base64Str); + if (print) { + System.out.println("JBoss: " + toString(jbossBytes)); + System.out.println(" length: " + jbossBytes.length); + } + + // Try jackrabbit ... + ByteArrayOutputStream jrOutput = new ByteArrayOutputStream(); + org.apache.jackrabbit.test.api.Base64.decode(base64Str, jrOutput); + byte[] jrBytes = jrOutput.toByteArray(); + if (print) { + System.out.println("Jackrabbit: " + toString(jrBytes)); + System.out.println(" length: " + jrBytes.length); + } + + // Try modeshape ... + byte[] msBytes = org.modeshape.common.util.Base64.decode(base64Str); + if (print) { + System.out.println("ModeShape: " + toString(msBytes)); + System.out.println(" length: " + msBytes.length); + } + + // assertThat(apacheBytes, is(jbossBytes)); // apache pads 3 0s at the end + assertThat(jrBytes, is(jbossBytes)); + assertThat(msBytes, is(jbossBytes)); + + } + + String toString( byte[] bytes ) { + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) + sb.append(b); + return sb.toString(); + } + // ---------------------------------------------------------------------------------------------------------------- // Import System View WITH 'jcr:root' node and WITH uuids // ----------------------------------------------------------------------------------------------------------------