Java tutorial
/** * Copyright (c) Codice Foundation * <p/> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p/> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. **/ package ddf.catalog.test; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.xml.HasXPath.hasXPath; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static com.jayway.restassured.RestAssured.delete; import static com.jayway.restassured.RestAssured.given; import static com.jayway.restassured.RestAssured.when; import static ddf.common.test.WaitCondition.expect; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.ws.rs.core.MediaType; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.commons.io.IOUtils; import org.codice.ddf.persistence.PersistentItem; import org.codice.ddf.persistence.PersistentStore; import org.json.simple.JSONObject; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; import org.osgi.service.cm.Configuration; import org.xml.sax.InputSource; import com.google.common.collect.Maps; import com.jayway.restassured.response.Response; import com.jayway.restassured.response.ValidatableResponse; import ddf.common.test.BeforeExam; /** * Tests the Catalog framework components. Includes helper methods at the Catalog level. */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class TestCatalog extends AbstractIntegrationTest { private static final String METACARD_X_PATH = "/metacards/metacard[@id='%s']"; public static void deleteMetacard(String id) { LOGGER.info("Deleting metacard {}", id); delete(REST_PATH.getUrl() + id).then().assertThat().statusCode(200).log().all(); } public static String ingestGeoJson(String json) { return ingest(json, "application/json"); } public static String ingest(String data, String mimeType) { LOGGER.info("Ingesting data of type {}:\n{}", mimeType, data); return given().body(data).header("Content-Type", mimeType).expect().log().all().statusCode(201).when() .post(REST_PATH.getUrl()).getHeader("id"); } @BeforeExam public void beforeExam() throws Exception { basePort = getBasePort(); getAdminConfig().setLogLevels(); getServiceManager().waitForAllBundles(); getCatalogBundle().waitForCatalogProvider(); getServiceManager().waitForHttpEndpoint(SERVICE_ROOT + "/catalog/query"); } @Test public void testMetacardTransformersFromRest() { String id = ingestGeoJson(Library.getSimpleGeoJson()); String url = REST_PATH.getUrl() + id; LOGGER.info("Getting response to {}", url); when().get(url).then().log().all().assertThat().body(hasXPath("/metacard[@id='" + id + "']")); deleteMetacard(id); } @Test public void testOpenSearchQuery() throws IOException { String id1 = ingestXmlFromResource("/metacard1.xml"); String id2 = ingestXmlFromResource("/metacard2.xml"); String id3 = ingestXmlFromResource("/metacard3.xml"); String id4 = ingestXmlFromResource("/metacard4.xml"); // Test xml-format response for an all-query ValidatableResponse response = executeOpenSearch("xml", "q=*"); response.body(hasXPath(String.format(METACARD_X_PATH, id1))) .body(hasXPath(String.format(METACARD_X_PATH, id2))) .body(hasXPath(String.format(METACARD_X_PATH, id3))) .body(hasXPath(String.format(METACARD_X_PATH, id4))); // Execute a text search against a value in an indexed field (metadata) response = executeOpenSearch("xml", "q=dunder*"); response.body(hasXPath(String.format(METACARD_X_PATH, id3))) .body(not(hasXPath(String.format(METACARD_X_PATH, id1)))) .body(not(hasXPath(String.format(METACARD_X_PATH, id2)))) .body(not(hasXPath(String.format(METACARD_X_PATH, id4)))); // Execute a text search against a value that isn't in any indexed fields response = executeOpenSearch("xml", "q=whatisthedealwithairlinefood"); response.body("metacards.metacard.size()", equalTo(0)); // Execute a geo search that should match a point card response = executeOpenSearch("xml", "lat=40.689", "lon=-74.045", "radius=250"); response.body(hasXPath(String.format(METACARD_X_PATH, id1))) .body(not(hasXPath(String.format(METACARD_X_PATH, id2)))) .body(not(hasXPath(String.format(METACARD_X_PATH, id3)))) .body(not(hasXPath(String.format(METACARD_X_PATH, id4)))); // Execute a geo search...this should match two cards, both polygons around the Space Needle response = executeOpenSearch("xml", "lat=47.62", "lon=-122.356", "radius=500"); response.body(hasXPath(String.format(METACARD_X_PATH, id2))) .body(hasXPath(String.format(METACARD_X_PATH, id4))) .body(not(hasXPath(String.format(METACARD_X_PATH, id1)))) .body(not(hasXPath(String.format(METACARD_X_PATH, id3)))); deleteMetacard(id1); deleteMetacard(id2); deleteMetacard(id3); deleteMetacard(id4); } private Response ingestCswRecord() { return given().header("Content-Type", MediaType.APPLICATION_XML).body(Library.getCswIngest()) .post(CSW_PATH.getUrl()); } private String getMetacardIdFromCswInsertResponse(Response response) throws IOException, XPathExpressionException { XPath xPath = XPathFactory.newInstance().newXPath(); String idPath = "//*[local-name()='identifier']/text()"; InputSource xml = new InputSource( IOUtils.toInputStream(response.getBody().asString(), StandardCharsets.UTF_8.name())); return xPath.compile(idPath).evaluate(xml); } private void deleteMetacard(Response response) throws IOException, XPathExpressionException { String id = getMetacardIdFromCswInsertResponse(response); deleteMetacard(id); } @Test public void testCswIngest() { Response response = ingestCswRecord(); ValidatableResponse validatableResponse = response.then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("1")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/InsertResult/BriefRecord/title", is("Aliquam fermentum purus quis arcu")), hasXPath("//TransactionResponse/InsertResult/BriefRecord/BoundingBox")); try { deleteMetacard(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); } } @Test public void testCswDeleteOneWithFilter() { ingestCswRecord(); ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswFilterDelete()).post(CSW_PATH.getUrl()).then(); response.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("1")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); } @Test public void testCswDeleteOneWithCQL() { ingestCswRecord(); ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswCqlDelete()).post(CSW_PATH.getUrl()).then(); response.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("1")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); } @Test public void testCswDeleteNone() { Response response = ingestCswRecord(); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswCqlDeleteNone()).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); try { deleteMetacard(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); } } @Test public void testCombinedCswIngestAndDelete() { // This record will be deleted with the <Delete> in the next transaction request. ingestCswRecord(); // The record being inserted in this transaction request will be deleted at the end of the // test. Response response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCombinedCswInsertAndDelete()).post(CSW_PATH.getUrl()); ValidatableResponse validatableResponse = response.then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("1")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("1")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); try { deleteMetacard(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); } } @Test public void testCswDeleteMultiple() { ingestCswRecord(); ingestCswRecord(); ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswFilterDelete()).post(CSW_PATH.getUrl()).then(); response.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("2")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); } @Test public void testCswUpdateByNewRecord() { Response response = ingestCswRecord(); String requestXml = Library.getCswUpdateByNewRecord(); String id; try { id = getMetacardIdFromCswInsertResponse(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); return; } requestXml = requestXml.replace("identifier placeholder", id); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(requestXml).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("1"))); String url = REST_PATH.getUrl() + id; when().get(url).then().log().all().assertThat().body( hasXPath("//metacard/dateTime[@name='date']/value", startsWith("2015-08-10")), hasXPath("//metacard/string[@name='title']/value", is("Updated Title")), hasXPath("//metacard/string[@name='subject']/value", is("Updated Subject")), hasXPath("(//metacard/geometry[@name='location']/value/Polygon/exterior/LinearRing/pos)[1]", is("1.0 2.0")), hasXPath("(//metacard/geometry[@name='location']/value/Polygon/exterior/LinearRing/pos)[2]", is("3.0 2.0")), hasXPath("(//metacard/geometry[@name='location']/value/Polygon/exterior/LinearRing/pos)[3]", is("3.0 4.0")), hasXPath("(//metacard/geometry[@name='location']/value/Polygon/exterior/LinearRing/pos)[4]", is("1.0 4.0")), hasXPath("(//metacard/geometry[@name='location']/value/Polygon/exterior/LinearRing/pos)[5]", is("1.0 2.0"))); deleteMetacard(id); } @Test public void testCswUpdateByNewRecordNoExistingMetacards() { ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswUpdateByNewRecord()).post(CSW_PATH.getUrl()).then(); response.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); } @Test public void testCswUpdateByNewRecordNoMetacardFound() { Response response = ingestCswRecord(); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswUpdateByNewRecord()).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); try { deleteMetacard(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); } } @Test public void testCswUpdateByFilterConstraint() { Response firstResponse = ingestCswRecord(); Response secondResponse = ingestCswRecord(); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswUpdateByFilterConstraint()).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("2"))); String firstId; String secondId; try { firstId = getMetacardIdFromCswInsertResponse(firstResponse); secondId = getMetacardIdFromCswInsertResponse(secondResponse); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); return; } String firstUrl = REST_PATH.getUrl() + firstId; when().get(firstUrl).then().log().all().assertThat() // Check that the updated attributes were changed. .body(hasXPath("//metacard/dateTime[@name='date']/value", startsWith("2015-08-25")), hasXPath("//metacard/string[@name='title']/value", is("Updated Title")), hasXPath("//metacard/string[@name='format']/value", is("")), // Check that an attribute that was not updated was not changed. hasXPath("//metacard/string[@name='subject']/value", is("Hydrography--Dictionaries"))); String secondUrl = REST_PATH.getUrl() + secondId; when().get(secondUrl).then().log().all().assertThat() // Check that the updated attributes were changed. .body(hasXPath("//metacard/dateTime[@name='date']/value", startsWith("2015-08-25")), hasXPath("//metacard/string[@name='title']/value", is("Updated Title")), hasXPath("//metacard/string[@name='format']/value", is("")), // Check that an attribute that was not updated was not changed. hasXPath("//metacard/string[@name='subject']/value", is("Hydrography--Dictionaries"))); deleteMetacard(firstId); deleteMetacard(secondId); } @Test public void testCswUpdateByFilterConstraintNoExistingMetacards() { ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswUpdateByFilterConstraint()).post(CSW_PATH.getUrl()).then(); response.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); } @Test public void testCswUpdateByFilterConstraintNoMetacardsFound() { Response response = ingestCswRecord(); String updateRequest = Library.getCswUpdateByFilterConstraint(); // Change the <Filter> property being searched for so no results will be found. updateRequest = updateRequest.replace("title", "subject"); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(updateRequest).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("0"))); try { deleteMetacard(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); } } @Test public void testCswGetRecordsWithHitsResultType() { Response response = ingestCswRecord(); String query = Library.getCswQuery("AnyText", "*"); String id; try { id = getMetacardIdFromCswInsertResponse(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); return; } //test with resultType="results" first ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(query).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("/GetRecordsResponse/SearchResults/Record")); //test with resultType="hits" query = query.replace("results", "hits"); validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML).body(query) .post(CSW_PATH.getUrl()).then(); //assert that no records have been returned validatableResponse.body(not(hasXPath("//Record"))); //testing with resultType='validate' is not //possible due to DDF-1537, this test will need //to be updated to test this once it is fixed. deleteMetacard(id); } @Test public void testCswUpdateRemoveAttributesByCqlConstraint() { Response response = ingestCswRecord(); String id; try { id = getMetacardIdFromCswInsertResponse(response); } catch (IOException | XPathExpressionException e) { fail("Could not retrieve the ingested record's ID from the response."); return; } String url = REST_PATH.getUrl() + id; when().get(url).then().log().all().assertThat() // Check that the attributes about to be removed in the update are present. .body(hasXPath("//metacard/dateTime[@name='date']"), hasXPath("//metacard/string[@name='title']"), hasXPath("//metacard/geometry[@name='location']")); ValidatableResponse validatableResponse = given().header("Content-Type", MediaType.APPLICATION_XML) .body(Library.getCswUpdateRemoveAttributesByCqlConstraint()).post(CSW_PATH.getUrl()).then(); validatableResponse.body(hasXPath("//TransactionResponse/TransactionSummary/totalDeleted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalInserted", is("0")), hasXPath("//TransactionResponse/TransactionSummary/totalUpdated", is("1"))); when().get(url).then().log().all().assertThat() // Check that the updated attributes were removed. .body(not(hasXPath("//metacard/dateTime[@name='date']")), not(hasXPath("//metacard/string[@name='title']")), not(hasXPath("//metacard/geometry[@name='location']")), // Check that an attribute that was not updated was not changed. hasXPath("//metacard/string[@name='subject']/value", is("Hydrography--Dictionaries"))); deleteMetacard(id); } @Test public void testGetRecordById() throws IOException, XPathExpressionException { final Response firstResponse = ingestCswRecord(); final Response secondResponse = ingestCswRecord(); final String firstId = getMetacardIdFromCswInsertResponse(firstResponse); final String secondId = getMetacardIdFromCswInsertResponse(secondResponse); final String requestIds = firstId + "," + secondId; // Request the records we just added. final String url = CSW_PATH.getUrl() + Library.getGetRecordByIdUrl().replace("placeholder_id", requestIds); final ValidatableResponse response = when().get(url).then().log().all(); verifyGetRecordByIdResponse(response, firstId, secondId); deleteMetacard(firstId); deleteMetacard(secondId); } @Test public void testPostGetRecordById() throws IOException, XPathExpressionException { final Response firstResponse = ingestCswRecord(); final Response secondResponse = ingestCswRecord(); final String firstId = getMetacardIdFromCswInsertResponse(firstResponse); final String secondId = getMetacardIdFromCswInsertResponse(secondResponse); final String requestXml = Library.getGetRecordByIdXml().replace("placeholder_id_1", firstId) .replace("placeholder_id_2", secondId); final ValidatableResponse response = given().header("Content-Type", MediaType.APPLICATION_XML) .body(requestXml).post(CSW_PATH.getUrl()).then(); verifyGetRecordByIdResponse(response, firstId, secondId); deleteMetacard(firstId); deleteMetacard(secondId); } private void verifyGetRecordByIdResponse(final ValidatableResponse response, final String... ids) { final String xPathGetRecordWithId = "//GetRecordByIdResponse/Record[identifier=\"%s\"]"; final String xPathValidateTitleWithId = xPathGetRecordWithId + "/title[text()=\"Aliquam fermentum purus quis arcu\"]"; final String xPathValidateBboxLowerWithId = xPathGetRecordWithId + "/BoundingBox/LowerCorner[text()=\"44.792 -6.171\"]"; final String xPathValidateBboxUpperWithId = xPathGetRecordWithId + "/BoundingBox/UpperCorner[text()=\"51.126 -2.228\"]"; final String xPathValidateId = "//GetRecordByIdResponse/Record/identifier[text()=\"%s\"]"; final String xPathCountRecords = "count(//GetRecordByIdResponse/Record)"; response.body(hasXPath(xPathCountRecords, is(String.valueOf(ids.length)))); for (String id : ids) { // Check that the IDs of the returned records are the IDs we requested. response.body(hasXPath(String.format(xPathValidateId, id))) // Check the contents of the returned records. .body(hasXPath(String.format(xPathValidateTitleWithId, id))) .body(hasXPath(String.format(xPathValidateBboxLowerWithId, id))) .body(hasXPath(String.format(xPathValidateBboxUpperWithId, id))); } } @Test public void testFilterPlugin() { try { // Ingest the metacard String id1 = ingestXmlFromResource("/metacard1.xml"); String xPath = String.format(METACARD_X_PATH, id1); // Test without filtering ValidatableResponse response = executeOpenSearch("xml", "q=*"); response.body(hasXPath(xPath)); startFeature(true, "sample-filter"); startFeature(true, "filter-plugin"); // Configure the PDP PdpProperties pdpProperties = new PdpProperties(); pdpProperties.put("matchAllMappings", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role=point-of-contact"); Configuration config = configAdmin.getConfiguration("ddf.security.pdp.realm.SimpleAuthzRealm", null); Dictionary<String, ?> configProps = new Hashtable<>(pdpProperties); config.update(configProps); waitForAllBundles(); // Test with filtering with out point-of-contact response = executeOpenSearch("xml", "q=*"); response.body(not(hasXPath(xPath))); // Test filtering with point of contact getSecurityPolicy().configureRestForBasic(); response = executeAdminOpenSearch("xml", "q=*"); response.body(hasXPath(xPath)); getSecurityPolicy().configureRestForAnonymous(); stopFeature(true, "sample-filter"); stopFeature(true, "filter-plugin"); deleteMetacard(id1); } catch (Exception e) { LOGGER.error("Couldn't start filter plugin"); } } @Test public void testIngestPlugin() throws Exception { //ingest a data set to make sure we don't have any issues initially String id1 = ingestGeoJson(Library.getSimpleGeoJson()); String xPath1 = String.format(METACARD_X_PATH, id1); //verify ingest by querying ValidatableResponse response = executeOpenSearch("xml", "q=*"); response.body(hasXPath(xPath1)); //change ingest plugin role to ingest IngestProperties ingestProperties = new IngestProperties(); ingestProperties.put("permissionStrings", new String[] { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role=ingest" }); Configuration config = configAdmin.getConfiguration("ddf.catalog.security.ingest.IngestPlugin", null); Dictionary<String, Object> configProps = new Hashtable<>(ingestProperties); config.update(configProps); waitForAllBundles(); //try ingesting again - it should fail this time given().body(Library.getSimpleGeoJson()).header("Content-Type", "application/json").expect().log().all() .statusCode(500).when().post(REST_PATH.getUrl()); //verify query for first id works response = executeOpenSearch("xml", "q=*"); response.body(hasXPath(xPath1)); //revert to original configuration configProps.put("permissionStrings", new String[] { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role=anonymous" }); config.update(configProps); waitForAllBundles(); deleteMetacard(id1); } @Test public void testContentDirectoryMonitor() throws Exception { startFeature(true, "content-core-directorymonitor"); final String TMP_PREFIX = "tcdm_"; Path tmpDir = Files.createTempDirectory(TMP_PREFIX); tmpDir.toFile().deleteOnExit(); Path tmpFile = Files.createTempFile(tmpDir, TMP_PREFIX, "_tmp.xml"); tmpFile.toFile().deleteOnExit(); Files.copy(this.getClass().getClassLoader().getResourceAsStream("metacard5.xml"), tmpFile, StandardCopyOption.REPLACE_EXISTING); Map<String, Object> cdmProperties = new HashMap<>(); cdmProperties.putAll(getMetatypeDefaults("content-core-directorymonitor", "ddf.content.core.directorymonitor.ContentDirectoryMonitor")); cdmProperties.put("monitoredDirectoryPath", tmpDir.toString() + "/"); // Must end with / cdmProperties.put("directive", "STORE_AND_PROCESS"); createManagedService("ddf.content.core.directorymonitor.ContentDirectoryMonitor", cdmProperties); long startTime = System.nanoTime(); ValidatableResponse response = null; do { response = executeOpenSearch("xml", "q=*SysAdmin*"); if (response.extract().xmlPath().getList("metacards.metacard").size() == 1) { break; } try { TimeUnit.MILLISECONDS.sleep(50); } catch (InterruptedException e) { } } while (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < TimeUnit.MINUTES.toMillis(1)); response.body("metacards.metacard.size()", equalTo(1)); } @Test public void persistObjectToWorkspace() throws Exception { persistToWorkspace(100); } @Test @Ignore // Ignored until DDF-1571 is addressed public void persistLargeObjectToWorkspace() throws Exception { persistToWorkspace(40000); } private void persistToWorkspace(int size) throws Exception { // Generate very large data block Map<String, String> map = Maps.newHashMap(); for (int i = 0; i < size; i++) { map.put("Key-" + i, "Val-" + i); } String jsonString = new JSONObject(map).toJSONString(); final PersistentStore pstore = getServiceManager().getService(PersistentStore.class); PersistentItem item = new PersistentItem(); item.addIdProperty("itest"); item.addProperty("user", "itest"); item.addProperty("workspaces_json", jsonString); try { assertThat(pstore.get(PersistentStore.WORKSPACE_TYPE), is(empty())); pstore.add(PersistentStore.WORKSPACE_TYPE, item); expect("Solr core to be spun up and item to be persisted").within(5, TimeUnit.MINUTES) .until(() -> pstore.get(PersistentStore.WORKSPACE_TYPE).size(), equalTo(1)); List<Map<String, Object>> storedWs = pstore.get(PersistentStore.WORKSPACE_TYPE, "id = 'itest'"); assertThat(storedWs, hasSize(1)); assertThat(storedWs.get(0).get("user_txt"), is("itest")); } finally { pstore.delete(PersistentStore.WORKSPACE_TYPE, "id = 'itest'"); expect("Workspace to be empty").within(5, TimeUnit.MINUTES) .until(() -> pstore.get(PersistentStore.WORKSPACE_TYPE).size(), equalTo(0)); } } private ValidatableResponse executeOpenSearch(String format, String... query) { StringBuilder buffer = new StringBuilder(OPENSEARCH_PATH.getUrl()).append("?").append("format=") .append(format); for (String term : query) { buffer.append("&").append(term); } String url = buffer.toString(); LOGGER.info("Getting response to {}", url); return when().get(url).then(); } private ValidatableResponse executeAdminOpenSearch(String format, String... query) { StringBuilder buffer = new StringBuilder(OPENSEARCH_PATH.getUrl()).append("?").append("format=") .append(format); for (String term : query) { buffer.append("&").append(term); } String url = buffer.toString(); LOGGER.info("Getting response to {}", url); return given().auth().basic("admin", "admin").when().get(url).then(); } protected String ingestXmlFromResource(String resourceName) throws IOException { StringWriter writer = new StringWriter(); IOUtils.copy(getClass().getResourceAsStream(resourceName), writer); return ingest(writer.toString(), "text/xml"); } public class PdpProperties extends HashMap<String, Object> { public static final String SYMBOLIC_NAME = "security-pdp-authzrealm"; public static final String FACTORY_PID = "ddf.security.pdp.realm.SimpleAuthzRealm"; public PdpProperties() { this.putAll(getMetatypeDefaults(SYMBOLIC_NAME, FACTORY_PID)); } } public class IngestProperties extends HashMap<String, Object> { public static final String SYMBOLIC_NAME = "catalog-security-ingestplugin"; public static final String FACTORY_PID = "ddf.catalog.security.ingest.IngestPlugin"; public IngestProperties() { this.putAll(getMetatypeDefaults(SYMBOLIC_NAME, FACTORY_PID)); } } }