/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.rest.catalog;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.rest.RestBaseController;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class CoverageStoreControllerTest extends CatalogRESTTestSupport {
@Override
protected void setUpTestData(SystemTestData testData) throws Exception {
testData.setUpDefaultRasterLayers();
}
@Before
public void addBlueMarbleCoverage() throws Exception {
getTestData().addDefaultRasterLayer(SystemTestData.TASMANIA_BM, getCatalog());
}
@Test
public void testGetAllOnMissingWorkspace() throws Exception {
MockHttpServletResponse response = getAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/abcde/coveragestores.xml");
assertEquals(404, response.getStatus());
assertThat(response.getContentAsString(), containsString("abcde"));
}
@Test
public void testGetAllAsXML() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores.xml");
assertEquals( catalog.getStoresByWorkspace( "wcs", CoverageStoreInfo.class ).size(),
dom.getElementsByTagName( "coverageStore").getLength() );
}
@Test
public void testGetAllAsJSON() throws Exception {
JSON json = getAsJSON( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores.json");
assertTrue( json instanceof JSONObject );
Object coveragestores = ((JSONObject)json).getJSONObject("coverageStores").get("coverageStore");
assertNotNull( coveragestores );
if( coveragestores instanceof JSONArray ) {
assertEquals( catalog.getCoverageStoresByWorkspace("wcs").size() , ((JSONArray)coveragestores).size() );
}
else {
assertEquals( 1, catalog.getCoverageStoresByWorkspace("wcs").size() );
}
}
@Test
public void testGetAllAsHTML() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores.html");
List<CoverageStoreInfo> coveragestores = catalog.getCoverageStoresByWorkspace("wcs");
NodeList links = xp.getMatchingNodes("//html:a", dom );
assertEquals( coveragestores.size(), links.getLength() );
for ( int i = 0; i < coveragestores.size(); i++ ){
CoverageStoreInfo cs = coveragestores.get( i );
Element link = (Element) links.item( i );
assertTrue( link.getAttribute("href").endsWith( cs.getName() + ".html") );
}
}
@Test
public void testPutAllUnauthorized() throws Exception {
assertEquals( 405, putAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores").getStatus() );
}
@Test
public void testDeleteAllUnauthorized() throws Exception {
assertEquals( 405, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores").getStatus() );
}
@Test
public void testGetAsXML() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.xml");
// print(dom);
assertEquals( "coverageStore", dom.getDocumentElement().getNodeName() );
assertEquals( "BlueMarble", xp.evaluate( "/coverageStore/name", dom) );
assertEquals( "wcs", xp.evaluate( "/coverageStore/workspace/name", dom) );
assertEquals( "http://localhost:8080/geoserver" + RestBaseController.ROOT_PATH + "/workspaces/wcs.xml",
xp.evaluate( "/coverageStore/workspace/atom:link/@href", dom));
assertEquals( "http://localhost:8080/geoserver" + RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble/coverages.xml",
xp.evaluate( "/coverageStore/coverages/atom:link/@href", dom));
}
@Test
public void testGetAsHTML() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.html");
CoverageStoreInfo cs = catalog.getCoverageStoreByName( "wcs", "BlueMarble" );
List<CoverageInfo> coverages = catalog.getCoveragesByCoverageStore( cs );
NodeList links = xp.getMatchingNodes("//html:a", dom );
assertEquals( coverages.size(), links.getLength() );
for ( int i = 0; i < coverages.size(); i++ ){
CoverageInfo cov = coverages.get( i );
Element link = (Element) links.item( i );
assertTrue( link.getAttribute("href").endsWith("coverages/" + cov.getName() + ".html") );
}
}
@Test
public void testGetWrongCoverageStore() throws Exception {
// Parameters for the request
String ws = "wcs";
String cs = "BlueMarblesssss";
// Request path
String requestPath = RestBaseController.ROOT_PATH + "/workspaces/" + ws + "/coveragestores/" + cs + ".html";
// Exception path
String exception = "No such coverage store: " + ws + "," + cs;
// First request should thrown an exception
MockHttpServletResponse response = getAsServletResponse(requestPath);
assertEquals(404, response.getStatus());
assertTrue(response.getContentAsString().contains(
exception));
// Same request with ?quietOnNotFound should not throw an exception
response = getAsServletResponse(requestPath + "?quietOnNotFound=true");
assertEquals(404, response.getStatus());
assertFalse(response.getContentAsString().contains(
exception));
// No exception thrown
assertTrue(response.getContentAsString().isEmpty());
}
File setupNewCoverageStore() throws Exception {
File dir = new File( "./target/usa" );
dir.mkdir();
dir.deleteOnExit();
File f = new File( dir, "usa.prj");
f.deleteOnExit();
FileOutputStream fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/usa.prj"), fout );
fout.flush();
fout.close();
f = new File( dir, "usa.meta");
f.deleteOnExit();
fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/usa.meta"), fout );
fout.flush();
fout.close();
f = new File( dir, "usa.png");
f.deleteOnExit();
fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/usa.png"), fout );
fout.flush();
fout.close();
return f;
}
@Test
public void testPostAsXML() throws Exception {
removeStore("wcs", "newCoverageStore");
File f = setupNewCoverageStore();
String xml =
"<coverageStore>" +
"<name>newCoverageStore</name>" +
"<type>WorldImage</type>" +
"<url>file://" + f.getAbsolutePath() + "</url>" +
"<workspace>wcs</workspace>" +
"</coverageStore>";
MockHttpServletResponse response =
postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores", xml, "text/xml" );
assertEquals( 201, response.getStatus() );
assertNotNull( response.getHeader( "Location") );
assertTrue( response.getHeader("Location").endsWith( "/workspaces/wcs/coveragestores/newCoverageStore" ) );
CoverageStoreInfo newCoverageStore = catalog.getCoverageStoreByName( "newCoverageStore" );
assertNotNull( newCoverageStore );
assertNotNull(newCoverageStore.getFormat());
}
@Test
public void testRoundTripCoverageStoreXML() throws Exception {
CoverageInfo before = catalog.getCoverageByName(getLayerId(MockData.TASMANIA_BM));
// get and re-write, does not go boom
String xml = getAsString( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.xml");
MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "text/xml");
assertEquals(200, response.getStatus());
// check nothing actually changed
CoverageInfo after = catalog.getCoverageByName(getLayerId(MockData.TASMANIA_BM));
assertEquals(before, after);
}
@Test
public void testGetAsJSON() throws Exception {
JSON json = getAsJSON( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.json" );
// print(json);
JSONObject coverageStore = ((JSONObject)json).getJSONObject("coverageStore");
assertNotNull(coverageStore);
assertEquals( "BlueMarble", coverageStore.get( "name") );
assertEquals( "wcs", coverageStore.getJSONObject( "workspace").get( "name" ));
assertNotNull( coverageStore.get( "type") );
assertNotNull( coverageStore.get( "url") );
assertEquals("http://localhost:8080/geoserver" + RestBaseController.ROOT_PATH + "/workspaces/wcs.json",
coverageStore.getJSONObject("workspace").get("href"));
assertEquals("http://localhost:8080/geoserver" + RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble/coverages.json",
coverageStore.get("coverages"));
}
@Test
public void testPostAsJSON() throws Exception {
removeStore("wcs", "newCoverageStore");
File f = setupNewCoverageStore();
String json =
"{'coverageStore':{" +
"'name':'newCoverageStore'," +
"'type': 'WorldImage'," +
"'url':'" + f.getAbsolutePath().replace('\\','/') + "'," +
"'workspace':'wcs'," +
"}" +
"}";
MockHttpServletResponse response =
postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores", json, "text/json" );
assertEquals( 201, response.getStatus() );
assertNotNull( response.getHeader( "Location") );
assertTrue( response.getHeader("Location").endsWith( "/workspaces/wcs/coveragestores/newCoverageStore" ) );
CoverageStoreInfo newCoverageStore = catalog.getCoverageStoreByName( "newCoverageStore" );
assertNotNull( newCoverageStore );
assertNotNull( newCoverageStore.getFormat() );
}
@Test
public void testRoundTripCoverageStoreJSON() throws Exception {
CoverageInfo before = catalog.getCoverageByName(getLayerId(MockData.TASMANIA_BM));
// get and re-write, does not go boom
String xml = getAsString( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.json");
MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "application/json");
assertEquals(200, response.getStatus());
// check nothing actually changed
CoverageInfo after = catalog.getCoverageByName(getLayerId(MockData.TASMANIA_BM));
assertEquals(before, after);
}
@Test
public void testPostToResource() throws Exception {
String xml =
"<coverageStore>" +
"<name>BlueMarble</name>" +
"<enabled>false</enabled>" +
"</coverageStore>";
MockHttpServletResponse response =
postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "text/xml");
assertEquals( 405, response.getStatus() );
}
@Test
public void testPut() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.xml");
assertXpathEvaluatesTo("true", "/coverageStore/enabled", dom );
String xml =
"<coverageStore>" +
"<name>BlueMarble</name>" +
"<enabled>false</enabled>" +
"</coverageStore>";
MockHttpServletResponse response =
putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "text/xml");
assertEquals( 200, response.getStatus() );
dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.xml");
assertXpathEvaluatesTo("false", "/coverageStore/enabled", dom );
assertFalse( catalog.getCoverageStoreByName( "wcs", "BlueMarble").isEnabled() );
}
@Test
public void testPutNonDestructive() throws Exception {
CoverageStoreInfo cs = catalog.getCoverageStoreByName( "wcs", "BlueMarble");
assertTrue(cs.isEnabled());
String xml =
"<coverageStore>" +
"<name>BlueMarble</name>" +
"</coverageStore>";
MockHttpServletResponse response =
putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "text/xml");
assertEquals( 200, response.getStatus() );
cs = catalog.getCoverageStoreByName( "wcs", "BlueMarble");
assertTrue(cs.isEnabled());
}
@Test
@Ignore
public void testPutEmptyAndHarvest() throws Exception {
File dir = new File( "./target/empty" );
dir.mkdir();
dir.deleteOnExit();
// Creating the coverageStore
File f = new File( dir, "empty.zip");
f.deleteOnExit();
FileOutputStream fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/empty.zip"), fout );
fout.flush();
fout.close();
final int length = (int) f.length();
byte[] zipData = new byte[length];
try(FileInputStream fis = new FileInputStream(f)){
fis.read(zipData);
}
MockHttpServletResponse response =
putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/empty/file.imagemosaic?configure=none", zipData, "application/zip");
// Store is created
assertEquals( 201, response.getStatus() );
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/empty.xml");
assertXpathEvaluatesTo("true", "/coverageStore/enabled", dom );
// Harvesting
f = new File( dir, "NCOM_wattemp_020_20081031T0000000_12.tiff");
f.deleteOnExit();
fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/NCOM_wattemp_020_20081031T0000000_12.tiff"), fout );
fout.flush();
fout.close();
final String path = "file://"+ f.getCanonicalPath();
response = postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/empty/external.imagemosaic", path, "text/plain");
assertEquals(202, response.getStatus() );
// Getting the list of available coverages
dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/empty/coverages.xml?list=all");
assertXpathEvaluatesTo("index", "/list/coverageName", dom );
assertEquals( 200, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/empty?recurse=true&purge=all").getStatus());
}
private void purgeRequest(final String purge, final int expectedFiles) throws Exception {
File dir = new File( "./target/mosaicfordelete" );
dir.mkdir();
dir.deleteOnExit();
// Creating the coverageStore
File f = new File( dir, "mosaic.zip");
f.deleteOnExit();
FileOutputStream fout = new FileOutputStream( f );
IOUtils.copy( getClass().getResourceAsStream("test-data/mosaic.zip"), fout );
fout.flush();
fout.close();
final int length = (int) f.length();
byte[] zipData = new byte[length];
try(FileInputStream fis = new FileInputStream(f)){
fis.read(zipData);
}
MockHttpServletResponse response =
putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/mosaicfordelete/file.imagemosaic", zipData, "application/zip");
// Store is created
assertEquals( 201, response.getStatus() );
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/mosaicfordelete.xml");
assertXpathEvaluatesTo("true", "/coverageStore/enabled", dom );
GeoServerResourceLoader loader = GeoServerExtensions.bean(GeoServerResourceLoader.class);
final File storeDir = loader.url("data/wcs/mosaicfordelete");
File[] content = storeDir.listFiles();
assertThat(content.length, anyOf(equalTo(10), equalTo(11)));
assertEquals( 200, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/mosaicfordelete?recurse=true&purge="
+purge).getStatus());
content = storeDir.listFiles();
//purge all: no files remaining; purge metadata: only 1 Granule remaining; purge none: all files (11) remaining
assertEquals(expectedFiles, content.length);
assertNull( catalog.getCoverageStoreByName("wcs", "mosaicfordelete"));
}
@Test
public void testDeletePurgeMetadataAfterConfigure() throws Exception {
purgeRequest("metadata", 1);
}
@Test
public void testDeletePurgeAllAfterConfigure() throws Exception {
purgeRequest("all", 0);
}
@Test
public void testPut2() throws Exception {
Document dom = getAsDOM( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble.xml");
assertXpathEvaluatesTo("GeoTIFF", "/coverageStore/type", dom );
String xml =
"<coverageStore>" +
"<name>BlueMarble</name>" +
"<type>WorldImage</type>" +
"</coverageStore>";
MockHttpServletResponse response =
putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble", xml, "text/xml");
assertEquals( 200, response.getStatus() );
CoverageStoreInfo cs = catalog.getCoverageStoreByName( "wcs", "BlueMarble" );
assertEquals( "WorldImage", cs.getType() );
}
@Test
public void testPutNonExistant() throws Exception {
String xml =
"<coverageStore>" +
"<name>changed</name>" +
"</coverageStore>";
MockHttpServletResponse response =
putAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/nonExistant", xml, "text/xml" );
assertEquals( 404, response.getStatus() );
}
@Test
public void testDeleteNonExistant() throws Exception {
assertEquals( 404, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/nonExistant").getStatus() );
}
@Test
public void testDelete() throws Exception {
CoverageStoreInfo cs = catalog.getCoverageStoreByName("wcs","BlueMarble");
List<CoverageInfo> coverages = catalog.getCoveragesByCoverageStore(cs);
for ( CoverageInfo c : coverages ) {
for ( LayerInfo l : catalog.getLayers(c) ) {
catalog.remove(l);
}
catalog.remove( c );
}
assertEquals( 200, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble").getStatus());
assertNull( catalog.getCoverageStoreByName("wcs", "BlueMarble"));
}
@Test
public void testDeleteNonEmpty() throws Exception {
assertEquals( 401, deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble").getStatus());
}
@Test
public void testDeleteRecursive() throws Exception {
assertNotNull(catalog.getCoverageStoreByName("wcs", "BlueMarble"));
MockHttpServletResponse response =
deleteAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/wcs/coveragestores/BlueMarble?recurse=true");
assertEquals(200, response.getStatus());
assertNull(catalog.getCoverageStoreByName("wcs", "BlueMarble"));
for (CoverageInfo c : catalog.getCoverages()) {
if (c.getStore().getName().equals("BlueMarble")) {
fail();
}
}
}
}