diff --git a/src/main/java/org/fcrepo/importexport/exporter/Exporter.java b/src/main/java/org/fcrepo/importexport/exporter/Exporter.java index 584f82dd..a0bf9302 100644 --- a/src/main/java/org/fcrepo/importexport/exporter/Exporter.java +++ b/src/main/java/org/fcrepo/importexport/exporter/Exporter.java @@ -51,6 +51,7 @@ import java.io.OutputStream; import java.io.Reader; import java.net.URI; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -388,7 +389,7 @@ private void exportBinary(final URI uri, final List describedby, final bool throws FcrepoOperationFailedException, IOException { if (!config.isIncludeBinaries()) { - logger.info("Skipping {}", uri); + logger.debug("Skipping: {} -> binaries are not included in this export configuration", uri); return; } @@ -402,11 +403,16 @@ private void exportBinary(final URI uri, final List describedby, final bool final File file = external ? fileForExternalResources(uri, null, null, config.getBaseDirectory()) : fileForBinary(uri, null, null, config.getBaseDirectory()); - logger.info("Exporting binary: {}", uri); - writeResponse(uri, response.getBody(), describedby, file); - writeHeadersFile(response, getHeadersFile(file)); - exportLogger.info("export {} to {}", uri, file.getAbsolutePath()); - successCount.incrementAndGet(); + //only retrieve content of external resources when retrieve external flag is enabled + //otherwise write a zero length file. + try (final InputStream is = external && !config.retrieveExternal() ? + IOUtils.toInputStream("", Charset.defaultCharset()) : response.getBody()) { + logger.info("Exporting binary: {}", uri); + writeResponse(uri, is, describedby, file); + writeHeadersFile(response, getHeadersFile(file)); + exportLogger.info("export {} to {}", uri, file.getAbsolutePath()); + successCount.incrementAndGet(); + } } diff --git a/src/test/java/org/fcrepo/importexport/exporter/ExporterTest.java b/src/test/java/org/fcrepo/importexport/exporter/ExporterTest.java index cc2f6c0b..680c0969 100644 --- a/src/test/java/org/fcrepo/importexport/exporter/ExporterTest.java +++ b/src/test/java/org/fcrepo/importexport/exporter/ExporterTest.java @@ -178,6 +178,7 @@ public void testExportBag() throws Exception { bagArgs.setMode("export"); bagArgs.setBaseDirectory(basedir); bagArgs.setIncludeBinaries(true); + bagArgs.setRetrieveExternal(true); bagArgs.setPredicates(predicates); bagArgs.setRdfLanguage("application/ld+json"); bagArgs.setResource(resource3); @@ -297,6 +298,7 @@ public void testExportBeyondTheRepositoryBag() throws IOException { config.setMode("export"); config.setBaseDirectory(exportDirectory); config.setIncludeBinaries(true); + config.setRetrieveExternal(true); config.setPredicates(predicates); config.setRdfLanguage("application/ld+json"); config.setResource(resource3); diff --git a/src/test/java/org/fcrepo/importexport/integration/ExporterIT.java b/src/test/java/org/fcrepo/importexport/integration/ExporterIT.java index 1a7910ca..c1bef9f4 100644 --- a/src/test/java/org/fcrepo/importexport/integration/ExporterIT.java +++ b/src/test/java/org/fcrepo/importexport/integration/ExporterIT.java @@ -52,6 +52,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.slf4j.LoggerFactory.getLogger; /** @@ -176,6 +177,76 @@ public void testExportRetrieveExternal() throws Exception { assertEquals("content", readFileToString(externalFile, "UTF-8")); } + @Test + public void testExportRetrieveExternalDisabledWithRedirect() throws Exception { + // Create an external content resource pointing at another repository resource + final URI binaryURI = URI.create(serverAddress + UUID.randomUUID()); + createBody(binaryURI, "content", "text/plain"); + final Map headers = new HashMap<>(); + headers.put("Link", "<" + binaryURI.toString() + ">;" + + " rel=\"http://fedora.info/definitions/fcrepo#ExternalContent\"; " + + " handling=\"redirect\"; " + + " type=\"text/plain\""); + + createBody(url, new ByteArrayInputStream("".getBytes()), "text/plain", headers); + + // Run an export process + final Config config = new Config(); + config.setMode("export"); + config.setBaseDirectory(TARGET_DIR); + config.setResource(url); + config.setIncludeBinaries(true); + config.setRetrieveExternal(false); + config.setUsername(USERNAME); + config.setPassword(PASSWORD); + + final Exporter exporter = new Exporter(config, clientBuilder); + exporter.run(); + + // Verify + final File externalFile = new File(TARGET_DIR, url.getPath() + EXTERNAL_RESOURCE_EXTENSION); + assertTrue(externalFile.exists()); + assertEquals("File length should be 0", 0, externalFile.length()); + } + + @Test + public void testExportRetrieveExternalDisabledWithProxy() throws Exception { + // Create an external content resource pointing at a local file resource + final File file = File.createTempFile("test",".txt"); + file.deleteOnExit(); + final String fileStr = "file://" + file.toPath().toAbsolutePath().toString(); + logger().debug("External File Resource = {}", fileStr); + final Map headers = new HashMap<>(); + headers.put("Link", "<" + fileStr + ">;" + + "rel=\"http://fedora.info/definitions/fcrepo#ExternalContent\"; " + + "handling=\"proxy\"; type=\"text/plain\""); + final FcrepoResponse proxiedResourceResponse = createBody(url, new ByteArrayInputStream("".getBytes()), + "text/plain", headers); + assertEquals(SC_CREATED, proxiedResourceResponse.getStatusCode()); + // Run an export process + final Config config = new Config(); + config.setMode("export"); + config.setBaseDirectory(TARGET_DIR); + config.setResource(url); + config.setIncludeBinaries(true); + config.setRetrieveExternal(false); + config.setUsername(USERNAME); + config.setPassword(PASSWORD); + + final Exporter exporter = new Exporter(config, clientBuilder); + try { + exporter.run(); + } catch(Exception ex) { + logger().error(ex.getMessage(), ex); + fail("Exporter failed unexpectedly: " + ex.getMessage()); + } + + // Verify + final File externalFile = new File(TARGET_DIR, url.getPath() + EXTERNAL_RESOURCE_EXTENSION); + assertTrue("External file should exist: " + externalFile.getAbsoluteFile(), externalFile.exists()); + assertEquals("File length should be 0", 0, externalFile.length()); + } + @Test public void testExportCustomPredicate() throws Exception { final String[] predicates = new String[]{ "http://example.org/custom" }; diff --git a/src/test/java/org/fcrepo/importexport/integration/RoundtripIT.java b/src/test/java/org/fcrepo/importexport/integration/RoundtripIT.java index 90d3f9c1..a248fc04 100644 --- a/src/test/java/org/fcrepo/importexport/integration/RoundtripIT.java +++ b/src/test/java/org/fcrepo/importexport/integration/RoundtripIT.java @@ -136,7 +136,7 @@ public void testRoundtripWithIgnoreVersions() throws Exception { final FcrepoResponse memento = post(timemapURI); assertEquals(SC_CREATED, memento.getStatusCode()); final URI mementoURI = memento.getLocation(); - roundtrip(uri, new ArrayList(), true, true, false); + roundtrip(uri, new ArrayList(), true, true, false, false); //timemap will be there because it is created automatically assertEquals(SC_OK, get(timemapURI).getStatusCode()); //the memento however should not have been imported. @@ -390,7 +390,7 @@ public void testRoundtripExcludedBinaries() throws Exception { assertTrue(exists(res1)); assertTrue(exists(file1)); - final Config config = roundtrip(res1, Collections.singletonList(file1), true, false, true); + final Config config = roundtrip(res1, Collections.singletonList(file1), true, false, true, false); // verify that files exist and contain expected content final File exportDir = config.getBaseDirectory(); @@ -498,7 +498,7 @@ public void testRoundtripExternalProxy() throws Exception { final String contentLength = get(file1).getHeaderValue("Content-Length"); assertEquals("Unexpected Content-Length value", contentLength, binaryFileLength + ""); - final Config config = roundtrip(URI.create(baseURI), true); + final Config config = roundtrip(URI.create(baseURI), true,true); // verify that files exist and contain expected content final File exportDir = config.getBaseDirectory(); @@ -648,12 +648,19 @@ private Literal longLiteral(final String longString) { return createTypedLiteral(longString, XSDlong); } - private Config roundtrip(final URI uri, final boolean reset) throws FcrepoOperationFailedException { - return roundtrip(uri, new ArrayList(), true, true, true); + private Config roundtrip(final URI uri, final boolean reset) + throws FcrepoOperationFailedException { + return roundtrip(uri, new ArrayList(), true, true, true, false); + } + + private Config roundtrip(final URI uri, final boolean reset, final boolean retrieveExternal) + throws FcrepoOperationFailedException { + return roundtrip(uri, new ArrayList(), true, true, true, retrieveExternal); } private Config roundtrip(final URI uri, final List relatedResources, - final boolean reset, final boolean includeBinary, final boolean includeVersions) + final boolean reset, final boolean includeBinary, final boolean includeVersions, + final boolean retrieveExternal) throws FcrepoOperationFailedException { // export resources final Config config = new Config(); @@ -662,6 +669,7 @@ private Config roundtrip(final URI uri, final List relatedResources, config.setIncludeBinaries(includeBinary); config.setIncludeMembership(true); config.setResource(uri); + config.setRetrieveExternal(retrieveExternal); config.setPredicates(new String[]{ CONTAINS.toString() }); config.setRdfExtension(DEFAULT_RDF_EXT); config.setRdfLanguage(DEFAULT_RDF_LANG);