Java tutorial
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.rest.catalog; import net.sf.json.JSON; import net.sf.json.JSONObject; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.custommonkey.xmlunit.XMLUnit; import org.custommonkey.xmlunit.XpathEngine; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.CatalogFacade; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.PropertyStyleHandler; import org.geoserver.catalog.SLDHandler; import org.geoserver.catalog.StyleInfo; import org.geoserver.catalog.Styles; import org.geoserver.data.test.SystemTestData; import org.geoserver.data.test.TestData; import org.geoserver.platform.GeoServerResourceLoader; import org.geoserver.platform.resource.Resource; import org.geoserver.rest.RestBaseController; import org.geotools.data.DataUtilities; import org.geotools.styling.Style; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.URL; import java.util.List; import java.util.Properties; import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo; import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.endsWith; import static org.junit.Assert.*; /** * Just ripped these tests from the existing rest test */ public class StyleControllerTest extends CatalogRESTTestSupport { @Before public void removeStyles() throws IOException { removeStyle("gs", "foo"); removeStyle(null, "foo"); } @Before public void addPondsStyle() throws IOException { getTestData().addStyle(SystemTestData.PONDS.getLocalPart(), getCatalog()); } @Before public void restoreLayers() throws IOException { revertLayer(SystemTestData.BASIC_POLYGONS); } @Test public void testGetAllAsXML() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/styles.xml"); List<StyleInfo> styles = catalog.getStyles(); assertXpathEvaluatesTo("" + styles.size(), "count(//style)", dom); } @Test public void testGetAllASJSON() throws Exception { JSON json = getAsJSON(RestBaseController.ROOT_PATH + "/styles.json"); List<StyleInfo> styles = catalog.getStyles(); assertEquals(styles.size(), ((JSONObject) json).getJSONObject("styles").getJSONArray("style").size()); } @Test public void testGetAllAsHTML() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/styles.html"); print(dom); List<StyleInfo> styles = catalog.getStylesByWorkspace(CatalogFacade.NO_WORKSPACE); NodeList links = xp.getMatchingNodes("//html:a", dom); for (int i = 0; i < styles.size(); i++) { StyleInfo s = styles.get(i); Element link = (Element) links.item(i); final String href = link.getAttribute("href"); assertTrue("Expected href to bed with " + s.getName() + ".html but was " + href, href.endsWith(s.getName() + ".html")); } } @Test public void testGetAllFromWorkspace() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/workspaces/gs/styles.xml"); assertEquals("styles", dom.getDocumentElement().getNodeName()); assertXpathEvaluatesTo("0", "count(//style)", dom); addStyleToWorkspace("foo"); dom = getAsDOM(RestBaseController.ROOT_PATH + "/workspaces/gs/styles.xml"); assertEquals("styles", dom.getDocumentElement().getNodeName()); assertXpathEvaluatesTo("1", "count(//style)", dom); assertXpathExists("//style/name[text() = 'foo']", dom); } void addStyleToWorkspace(String name) { Catalog cat = getCatalog(); StyleInfo s = cat.getFactory().createStyle(); s.setName(name); s.setFilename(name + ".sld"); s.setWorkspace(cat.getWorkspaceByName("gs")); cat.add(s); } @Test public void testGetAsXML() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/styles/Ponds.xml"); assertEquals("style", dom.getDocumentElement().getNodeName()); assertXpathEvaluatesTo("Ponds", "/style/name", dom); assertXpathEvaluatesTo("Ponds.sld", "/style/filename", dom); } @Test public void testGetAsJSON() throws Exception { JSON json = getAsJSON(RestBaseController.ROOT_PATH + "/styles/Ponds.json"); JSONObject style = ((JSONObject) json).getJSONObject("style"); assertEquals("Ponds", style.get("name")); assertEquals("Ponds.sld", style.get("filename")); } @Test public void testGetWrongStyle() throws Exception { // Parameters for the request String ws = "gs"; String style = "foooooo"; // Request path String requestPath = RestBaseController.ROOT_PATH + "/styles/" + style + ".html"; String requestPath2 = RestBaseController.ROOT_PATH + "/workspaces/" + ws + "/styles/" + style + ".html"; // Exception path String exception = "No such style: " + style; String exception2 = "No such style " + style + " in workspace " + ws; // CASE 1: No workspace set // 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()); // CASE 2: workspace set // First request should thrown an exception response = getAsServletResponse(requestPath2); assertEquals(404, response.getStatus()); assertTrue(response.getContentAsString().contains(exception2)); // Same request with ?quietOnNotFound should not throw an exception response = getAsServletResponse(requestPath2 + "?quietOnNotFound=true"); assertEquals(404, response.getStatus()); assertFalse(response.getContentAsString().contains(exception2)); // No exception thrown assertTrue(response.getContentAsString().isEmpty()); } @Test public void testGetAsSLD() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/styles/Ponds.sld"); assertEquals("StyledLayerDescriptor", dom.getDocumentElement().getNodeName()); } @Test public void testGetFromWorkspace() throws Exception { MockHttpServletResponse resp = getAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.xml"); assertEquals(404, resp.getStatus()); addStyleToWorkspace("foo"); resp = getAsServletResponse(RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.xml"); assertEquals(200, resp.getStatus()); Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.xml"); assertXpathEvaluatesTo("foo", "/style/name", dom); assertXpathEvaluatesTo("gs", "/style/workspace/name", dom); } String newSLDXML() { return "<sld:StyledLayerDescriptor xmlns:sld='http://www.opengis.net/sld'>" + "<sld:NamedLayer>" + "<sld:Name>foo</sld:Name>" + "<sld:UserStyle>" + "<sld:Name>foo</sld:Name>" + "<sld:FeatureTypeStyle>" + "<sld:Name>foo</sld:Name>" + "</sld:FeatureTypeStyle>" + "</sld:UserStyle>" + "</sld:NamedLayer>" + "</sld:StyledLayerDescriptor>"; } @Test public void testPostAsSLD() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles", xml, SLDHandler.MIMETYPE_10); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/styles/foo")); assertNotNull(catalog.getStyleByName("foo")); } @Test public void testPostExternalEntityAsSLD() throws Exception { String xml = IOUtils.toString(TestData.class.getResource("externalEntities.sld"), "UTF-8"); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles", xml, SLDHandler.MIMETYPE_10); assertEquals(500, response.getStatus()); String message = response.getContentAsString(); assertThat(message, containsString("Entity resolution disallowed")); assertThat(message, containsString("/this/file/does/not/exist")); } @Test public void testPostAsSLDToWorkspace() throws Exception { assertNull(catalog.getStyleByName("gs", "foo")); String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles", xml, SLDHandler.MIMETYPE_10); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/workspaces/gs/styles/foo")); assertNotNull(catalog.getStyleByName("gs", "foo")); GeoServerResourceLoader rl = getResourceLoader(); assertNotNull(rl.find("workspaces", "gs", "styles", "foo.sld")); } @Test public void testPostAsSLDWithName() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles?name=bar", xml, SLDHandler.MIMETYPE_10); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/styles/bar")); assertNotNull(catalog.getStyleByName("bar")); } @Test public void testStyleWithSpaceInName() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/styles?name=Default%20Styler", xml, SLDHandler.MIMETYPE_10); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertThat(response.getHeader("Location"), endsWith("/styles/Default%20Styler")); assertNotNull(catalog.getStyleByName("Default Styler")); // now delete it, using a + instead of %20, the old code supported it response = deleteAsServletResponse(RestBaseController.ROOT_PATH + "/styles/Default+Styler"); assertEquals(200, response.getStatus()); } @Test public void testPostToWorkspace() throws Exception { Catalog cat = getCatalog(); assertNull(cat.getStyleByName("gs", "foo")); String xml = "<style>" + "<name>foo</name>" + "<filename>foo.sld</filename>" + "</style>"; MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles", xml); assertEquals(201, response.getStatus()); assertNotNull(cat.getStyleByName("gs", "foo")); } @Test public void testPut() throws Exception { StyleInfo style = catalog.getStyleByName("Ponds"); assertEquals("Ponds.sld", style.getFilename()); String xml = "<style>" + "<name>Ponds</name>" + "<filename>Forests.sld</filename>" + "</style>"; MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/Ponds", xml.getBytes(), "text/xml"); assertEquals(200, response.getStatus()); style = catalog.getStyleByName("Ponds"); assertEquals("Forests.sld", style.getFilename()); } @Test public void testPutAsSLD() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/Ponds", xml, SLDHandler.MIMETYPE_10); assertEquals(200, response.getStatus()); Style s = catalog.getStyleByName("Ponds").getStyle(); ByteArrayOutputStream out = new ByteArrayOutputStream(); SLDHandler handler = new SLDHandler(); handler.encode(Styles.sld(s), SLDHandler.VERSION_10, false, out); xml = new String(out.toByteArray()); assertTrue(xml.contains("<sld:Name>foo</sld:Name>")); } @Test public void testPutAsSLDWithExtension() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/Ponds.sld", xml, SLDHandler.MIMETYPE_10); assertEquals(200, response.getStatus()); Style s = catalog.getStyleByName("Ponds").getStyle(); ByteArrayOutputStream out = new ByteArrayOutputStream(); SLDHandler handler = new SLDHandler(); handler.encode(Styles.sld(s), SLDHandler.VERSION_10, false, out); xml = new String(out.toByteArray()); assertTrue(xml.contains("<sld:Name>foo</sld:Name>")); } @Test public void testRawPutAsSLD() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/styles/Ponds?raw=true", xml, SLDHandler.MIMETYPE_10); assertEquals(200, response.getStatus()); Style s = catalog.getStyleByName("Ponds").getStyle(); ByteArrayOutputStream out = new ByteArrayOutputStream(); SLDHandler handler = new SLDHandler(); handler.encode(Styles.sld(s), SLDHandler.VERSION_10, false, out); xml = new String(out.toByteArray()); assertTrue(xml.contains("<sld:Name>foo</sld:Name>")); } @Test public void testRawPutAsInvalidSLD() throws Exception { String xml = "This is not valid SLD"; MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/styles/Ponds?raw=true", xml, SLDHandler.MIMETYPE_10); assertEquals(200, response.getStatus()); StyleInfo styleInfo = catalog.getStyleByName("Ponds"); String fileName = styleInfo.getFilename(); GeoServerResourceLoader resources = getGeoServer().getCatalog().getResourceLoader(); Resource resource = resources.get("styles/" + fileName); String content = new String(resource.getContents()); assertFalse("replaced", content.contains("<sld:Name>foo</sld:Name>")); assertTrue("replaced", content.contains("not valid")); } @Test public void testPutToWorkspace() throws Exception { testPostToWorkspace(); Catalog cat = getCatalog(); assertEquals("foo.sld", cat.getStyleByName("gs", "foo").getFilename()); String xml = "<style>" + "<filename>bar.sld</filename>" + "</style>"; MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo", xml, "application/xml"); assertEquals(200, response.getStatus()); assertEquals("bar.sld", cat.getStyleByName("gs", "foo").getFilename()); } @Test public void testPutToWorkspaceChangeWorkspace() throws Exception { testPostToWorkspace(); String xml = "<style>" + "<workspace>cite</workspace>" + "</style>"; MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo", xml, "application/xml"); assertEquals(403, response.getStatus()); } @Test public void testStyleNotFoundGloballyWhenInWorkspace() throws Exception { testPostToWorkspace(); Catalog cat = getCatalog(); assertEquals("foo.sld", cat.getStyleByName("gs", "foo").getFilename()); String xml = "<style>" + "<filename>bar.sld</filename>" + "</style>"; MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo", xml, "application/xml"); assertEquals(200, response.getStatus()); response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/gs:foo", xml, "application/xml"); assertEquals(500, response.getStatus()); } @Test public void testDelete() throws Exception { String xml = "<style>" + "<name>dummy</name>" + "<filename>dummy.sld</filename>" + "</style>"; post(RestBaseController.ROOT_PATH + "/styles", xml, "text/xml"); assertNotNull(catalog.getStyleByName("dummy")); MockHttpServletResponse response = deleteAsServletResponse(RestBaseController.ROOT_PATH + "/styles/dummy"); assertEquals(200, response.getStatus()); assertNull(catalog.getStyleByName("dummy")); } @Test public void testDeleteWithLayerReference() throws Exception { assertNotNull(catalog.getStyleByName("Ponds")); MockHttpServletResponse response = deleteAsServletResponse(RestBaseController.ROOT_PATH + "/styles/Ponds"); assertEquals(403, response.getStatus()); assertNotNull(catalog.getStyleByName("Ponds")); } @Test public void testDeleteWithLayerReferenceAndRecurse() throws Exception { assertNotNull(catalog.getStyleByName("Ponds")); MockHttpServletResponse response = deleteAsServletResponse( RestBaseController.ROOT_PATH + "/styles/Ponds?recurse=true"); assertEquals(200, response.getStatus()); assertNull(catalog.getStyleByName("Ponds")); } @Test public void testDeleteWithoutPurge() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles", xml, SLDHandler.MIMETYPE_10); assertNotNull(catalog.getStyleByName("foo")); //ensure the style not deleted on disk assertTrue(new File(getDataDirectory().findStyleDir(), "foo.sld").exists()); response = deleteAsServletResponse(RestBaseController.ROOT_PATH + "/styles/foo"); assertEquals(200, response.getStatus()); //ensure the style deleted on disk but backed up assertFalse(new File(getDataDirectory().findStyleDir(), "foo.sld").exists()); assertTrue(new File(getDataDirectory().findStyleDir(), "foo.sld.bak").exists()); } @Test public void testDeleteWithPurge() throws Exception { String xml = newSLDXML(); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles", xml, SLDHandler.MIMETYPE_10); assertNotNull(catalog.getStyleByName("foo")); //ensure the style not deleted on disk assertTrue(new File(getDataDirectory().findStyleDir(), "foo.sld").exists()); response = deleteAsServletResponse(RestBaseController.ROOT_PATH + "/styles/foo?purge=true"); assertEquals(200, response.getStatus()); //ensure the style not deleted on disk assertFalse(new File(getDataDirectory().findStyleDir(), "foo.sld").exists()); } @Test public void testDeleteFromWorkspace() throws Exception { testPostToWorkspace(); Catalog cat = getCatalog(); assertNotNull(cat.getStyleByName("gs", "foo")); MockHttpServletResponse response = deleteAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.xml"); assertEquals(200, response.getStatus()); assertNull(cat.getStyleByName("gs", "foo")); } @Test public void testDeleteFromWorkspaceWithPurge() throws Exception { testPostAsSLDToWorkspace(); Catalog cat = getCatalog(); assertNotNull(cat.getStyleByName("gs", "foo")); GeoServerResourceLoader rl = getResourceLoader(); assertNotNull(rl.find("workspaces", "gs", "styles", "foo.sld")); MockHttpServletResponse response = deleteAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo?purge=true"); assertEquals(200, response.getStatus()); assertNull(cat.getStyleByName("gs", "foo")); assertNull(rl.find("workspaces", "gs", "styles", "foo.sld")); } @Test public void testGetAllByLayer() throws Exception { Document dom = getAsDOM(RestBaseController.ROOT_PATH + "/layers/cite:BasicPolygons/styles.xml"); LayerInfo layer = catalog.getLayerByName("cite:BasicPolygons"); assertXpathEvaluatesTo(layer.getStyles().size() + "", "count(//style)", dom); } @Test public void testPostByLayer() throws Exception { LayerInfo l = catalog.getLayerByName("cite:BasicPolygons"); int nstyles = l.getStyles().size(); String xml = "<style>" + "<name>Ponds</name>" + "</style>"; MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/layers/cite:BasicPolygons/styles", xml, "text/xml"); assertEquals(201, response.getStatus()); LayerInfo l2 = catalog.getLayerByName("cite:BasicPolygons"); assertEquals(nstyles + 1, l2.getStyles().size()); assertTrue(l2.getStyles().contains(catalog.getStyleByName("Ponds"))); } @Test public void testPostByLayerWithDefault() throws Exception { getTestData().addVectorLayer(SystemTestData.BASIC_POLYGONS, getCatalog()); LayerInfo l = catalog.getLayerByName("cite:BasicPolygons"); int nstyles = l.getStyles().size(); String xml = "<style>" + "<name>Ponds</name>" + "</style>"; MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/layers/cite:BasicPolygons/styles?default=true", xml, "text/xml"); assertEquals(201, response.getStatus()); LayerInfo l2 = catalog.getLayerByName("cite:BasicPolygons"); assertEquals(nstyles + 1, l2.getStyles().size()); assertEquals(catalog.getStyleByName("Ponds"), l2.getDefaultStyle()); } @Test public void testPostByLayerExistingWithDefault() throws Exception { getTestData().addVectorLayer(SystemTestData.BASIC_POLYGONS, getCatalog()); testPostByLayer(); LayerInfo l = catalog.getLayerByName("cite:BasicPolygons"); int nstyles = l.getStyles().size(); String xml = "<style>" + "<name>Ponds</name>" + "</style>"; MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/layers/cite:BasicPolygons/styles?default=true", xml, "text/xml"); assertEquals(201, response.getStatus()); LayerInfo l2 = catalog.getLayerByName("cite:BasicPolygons"); assertEquals(nstyles, l2.getStyles().size()); assertEquals(catalog.getStyleByName("Ponds"), l2.getDefaultStyle()); } @Test @Ignore public void testPostAsPSL() throws Exception { Properties props = new Properties(); props.put("type", "point"); props.put("color", "ff0000"); StringWriter out = new StringWriter(); props.store(out, "comment!"); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles?name=foo", out.toString(), PropertyStyleHandler.MIMETYPE); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/styles/foo")); assertNotNull(catalog.getStyleByName("foo")); Resource style = getDataDirectory().style(getCatalog().getStyleByName("foo")); InputStream in = style.in(); props = new Properties(); try { props.load(in); assertEquals("point", props.getProperty("type")); } finally { in.close(); } in = style.in(); try { out = new StringWriter(); IOUtils.copy(in, out); assertFalse(out.toString().startsWith("#comment!")); } finally { in.close(); } } @Test @Ignore public void testPostAsPSLRaw() throws Exception { Properties props = new Properties(); props.put("type", "point"); props.put("color", "ff0000"); StringWriter out = new StringWriter(); props.store(out, "comment!"); MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/styles?name=foo&raw=true", out.toString(), PropertyStyleHandler.MIMETYPE); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/styles/foo")); // check style on disk to ensure the exact contents was preserved Resource style = getDataDirectory().style(getCatalog().getStyleByName("foo")); try (InputStream in = style.in()) { out = new StringWriter(); IOUtils.copy(in, out); assertTrue(out.toString().startsWith("#comment!")); } } @Test @Ignore public void testGetAsPSL() throws Exception { Properties props = new Properties(); props.load(get(RestBaseController.ROOT_PATH + "/styles/Ponds.properties")); assertEquals("polygon", props.getProperty("type")); } @Test @Ignore public void testPutAsPSL() throws Exception { testPostAsPSL(); Properties props = new Properties(); props.put("type", "line"); props.put("color", "00ff00"); StringWriter out = new StringWriter(); props.store(out, "comment!"); MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/foo", out.toString(), PropertyStyleHandler.MIMETYPE); assertEquals(200, response.getStatus()); Resource style = getDataDirectory().style(getCatalog().getStyleByName("foo")); InputStream in = style.in(); try { props = new Properties(); props.load(in); assertEquals("line", props.getProperty("type")); } finally { in.close(); } in = style.in(); try { out = new StringWriter(); IOUtils.copy(in, out); assertFalse(out.toString().startsWith("#comment!")); } finally { in.close(); } } @Test @Ignore public void testPutAsPSLRaw() throws Exception { testPostAsPSL(); Properties props = new Properties(); props.put("type", "line"); props.put("color", "00ff00"); StringWriter out = new StringWriter(); props.store(out, "comment!"); MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/styles/foo?raw=true", out.toString(), PropertyStyleHandler.MIMETYPE); assertEquals(200, response.getStatus()); Resource style = getDataDirectory().style(getCatalog().getStyleByName("foo")); InputStream in = style.in(); try { props = new Properties(); props.load(in); assertEquals("line", props.getProperty("type")); } finally { in.close(); } in = style.in(); try { out = new StringWriter(); IOUtils.copy(in, out); assertTrue(out.toString().startsWith("#comment!")); } finally { in.close(); } } @Test public void testPostAsSE() throws Exception { String xml = "<StyledLayerDescriptor xmlns=\"http://www.opengis.net/sld\" " + " xmlns:se=\"http://www.opengis.net/se\" version=\"1.1.0\"> " + " <NamedLayer> " + " <UserStyle> " + " <se:Name>UserSelection</se:Name> " + " <se:FeatureTypeStyle> " + " <se:Rule> " + " <se:PolygonSymbolizer> " + " <se:Fill> " + " <se:SvgParameter name=\"fill\">#FF0000</se:SvgParameter> " + " </se:Fill> " + " </se:PolygonSymbolizer> " + " </se:Rule> " + " </se:FeatureTypeStyle> " + " </UserStyle> " + " </NamedLayer> " + "</StyledLayerDescriptor>"; MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles?name=foo", xml, SLDHandler.MIMETYPE_11); assertEquals(201, response.getStatus()); assertNotNull(response.getHeader("Location")); assertTrue(response.getHeader("Location").endsWith("/styles/foo")); StyleInfo style = catalog.getStyleByName("foo"); assertNotNull(style); assertEquals("sld", style.getFormat()); assertEquals(SLDHandler.VERSION_11, style.getFormatVersion()); } @Test public void testPostToWorkspaceSLDPackage() throws Exception { Catalog cat = getCatalog(); assertNull(cat.getStyleByName("gs", "foo")); URL zip = getClass().getResource("test-data/foo.zip"); byte[] bytes = FileUtils.readFileToByteArray(DataUtilities.urlToFile(zip)); MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles", bytes, "application/zip"); assertEquals(201, response.getStatus()); assertNotNull(cat.getStyleByName("gs", "foo")); Document d = getAsDOM(RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.sld"); assertEquals("StyledLayerDescriptor", d.getDocumentElement().getNodeName()); XpathEngine engine = XMLUnit.newXpathEngine(); NodeList list = engine.getMatchingNodes( "//sld:StyledLayerDescriptor/sld:NamedLayer/sld:UserStyle/sld:FeatureTypeStyle/sld:Rule/sld:PointSymbolizer/sld:Graphic/sld:ExternalGraphic/sld:OnlineResource", d); assertEquals(1, list.getLength()); Element onlineResource = (Element) list.item(0); assertEquals("gear.png", onlineResource.getAttribute("xlink:href")); assertNotNull(getCatalog().getResourceLoader().find("workspaces/gs/styles/gear.png")); assertNotNull(getCatalog().getResourceLoader().find("workspaces/gs/styles/foo.sld")); } @Test public void testPostWithExternalEntities() throws Exception { URL zip = getClass().getResource("test-data/externalEntities.zip"); byte[] bytes = FileUtils.readFileToByteArray(DataUtilities.urlToFile(zip)); MockHttpServletResponse response = postAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles", bytes, "application/zip"); // expecting a failure with explanation assertEquals(400, response.getStatus()); final String content = response.getContentAsString(); assertThat(content, containsString("Entity resolution disallowed")); assertThat(content, containsString("/this/file/does/not/exist")); } @Test public void testPutToWorkspaceSLDPackage() throws Exception { testPostAsSLDToWorkspace(); Catalog cat = getCatalog(); assertNotNull(cat.getStyleByName("gs", "foo")); URL zip = getClass().getResource("test-data/foo.zip"); byte[] bytes = FileUtils.readFileToByteArray(DataUtilities.urlToFile(zip)); MockHttpServletResponse response = putAsServletResponse( RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo", bytes, "application/zip"); assertEquals(200, response.getStatus()); assertNotNull(cat.getStyleByName("gs", "foo")); Document d = getAsDOM(RestBaseController.ROOT_PATH + "/workspaces/gs/styles/foo.sld"); assertEquals("StyledLayerDescriptor", d.getDocumentElement().getNodeName()); XpathEngine engine = XMLUnit.newXpathEngine(); NodeList list = engine.getMatchingNodes( "//sld:StyledLayerDescriptor/sld:NamedLayer/sld:UserStyle/sld:FeatureTypeStyle/sld:Rule/sld:PointSymbolizer/sld:Graphic/sld:ExternalGraphic/sld:OnlineResource", d); assertEquals(1, list.getLength()); Element onlineResource = (Element) list.item(0); assertEquals("gear.png", onlineResource.getAttribute("xlink:href")); assertNotNull(getCatalog().getResourceLoader().find("workspaces/gs/styles/gear.png")); assertNotNull(getCatalog().getResourceLoader().find("workspaces/gs/styles/foo.sld")); } @Test public void testPostSLDPackage() throws Exception { Catalog cat = getCatalog(); assertNull(cat.getStyleByName("foo")); URL zip = getClass().getResource("test-data/foo.zip"); byte[] bytes = FileUtils.readFileToByteArray(DataUtilities.urlToFile(zip)); MockHttpServletResponse response = postAsServletResponse(RestBaseController.ROOT_PATH + "/styles", bytes, "application/zip"); assertEquals(201, response.getStatus()); assertNotNull(cat.getStyleByName("foo")); Document d = getAsDOM(RestBaseController.ROOT_PATH + "/styles/foo.sld"); assertEquals("StyledLayerDescriptor", d.getDocumentElement().getNodeName()); XpathEngine engine = XMLUnit.newXpathEngine(); NodeList list = engine.getMatchingNodes( "//sld:StyledLayerDescriptor/sld:NamedLayer/sld:UserStyle/sld:FeatureTypeStyle/sld:Rule/sld:PointSymbolizer/sld:Graphic/sld:ExternalGraphic/sld:OnlineResource", d); assertEquals(1, list.getLength()); Element onlineResource = (Element) list.item(0); assertEquals("gear.png", onlineResource.getAttribute("xlink:href")); assertNotNull(getCatalog().getResourceLoader().find("styles/gear.png")); assertNotNull(getCatalog().getResourceLoader().find("styles/foo.sld")); } @Test public void testPutSLDPackage() throws Exception { testPostAsSLD(); Catalog cat = getCatalog(); assertNotNull(cat.getStyleByName("foo")); URL zip = getClass().getResource("test-data/foo.zip"); byte[] bytes = FileUtils.readFileToByteArray(DataUtilities.urlToFile(zip)); //@TODO i had to change this from foo.zip to just foo. see the long comments below MockHttpServletResponse response = putAsServletResponse(RestBaseController.ROOT_PATH + "/styles/foo", bytes, "application/zip"); assertEquals(200, response.getStatus()); assertNotNull(cat.getStyleByName("foo")); Document d = getAsDOM(RestBaseController.ROOT_PATH + "/styles/foo.sld"); assertEquals("StyledLayerDescriptor", d.getDocumentElement().getNodeName()); XpathEngine engine = XMLUnit.newXpathEngine(); NodeList list = engine.getMatchingNodes( "//sld:StyledLayerDescriptor/sld:NamedLayer/sld:UserStyle/sld:FeatureTypeStyle/sld:Rule/sld:PointSymbolizer/sld:Graphic/sld:ExternalGraphic/sld:OnlineResource", d); assertEquals(1, list.getLength()); Element onlineResource = (Element) list.item(0); assertEquals("gear.png", onlineResource.getAttribute("xlink:href")); assertNotNull(getCatalog().getResourceLoader().find("styles/gear.png")); assertNotNull(getCatalog().getResourceLoader().find("styles/foo.sld")); } /** * TODO I had to put this here BECAUSE: * * - The testPutSLDPackage test uses a *.zip URL * - BUT, put style does not support ZIP responses * - Spring interprets the .zip extension on the path as being a request for a zip response * - This fails, because there is no actual handler for a zip response on a style endpoint * - Unfortunately Spring only considers one of the Accept header or the path * - So the handler is never found * * this leaves us with a few options * * 1) Configure spring to prefer the accept header over the path. This would: * * - Force future clients who depended on put/posting to zip endpoints to make sure their * Accept header is correct. * - Maybe more importantly it could potentially break other end points that depend on preferring * the path extension. * * 2) Continue letting Spring prefer the path (which is really the right behavior for a REST api) * * - Future clients would not be able to use an endpoint like .zip * - But this is more REST-y * * 3) Write our own content negotiation strategy that allows for both. * * - This is a pain in the ass. * - Potentially difficult to recreate all default behavior + behavior needed to fix this test * case * * @param path * @param body * @param contentType * @return * @throws Exception */ protected MockHttpServletResponse putAsServletResponse(String path, byte[] body, String contentType, String accepts) throws Exception { MockHttpServletRequest request = createRequest(path); request.setMethod("PUT"); request.setContentType(contentType); request.setContent(body); request.addHeader("Accept", accepts); request.addHeader("Content-type", contentType); return dispatch(request); } }