com.boundlessgeo.geoserver.AppIntegrationTest.java Source code

Java tutorial

Introduction

Here is the source code for com.boundlessgeo.geoserver.AppIntegrationTest.java

Source

/* (c) 2014-2015 Boundless, http://boundlessgeo.com
 * This code is licensed under the GPL 2.0 license.
 */
package com.boundlessgeo.geoserver;

import com.boundlessgeo.geoserver.api.controllers.IO;
import com.boundlessgeo.geoserver.api.controllers.IconController;
import com.boundlessgeo.geoserver.api.controllers.ImportController;
import com.boundlessgeo.geoserver.api.controllers.StoreController;
import com.boundlessgeo.geoserver.api.controllers.WorkspaceController;
import com.boundlessgeo.geoserver.catalog.UploadDeleteCatalogListener;
import com.boundlessgeo.geoserver.json.JSONArr;
import com.boundlessgeo.geoserver.json.JSONObj;
import com.boundlessgeo.geoserver.util.NameUtil;
import com.boundlessgeo.geoserver.util.RecentObjectCache;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.io.IOUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourcePool;
import org.geoserver.catalog.SLDHandler;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.SettingsInfo;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.importer.Importer;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.resource.Resource;
import org.geoserver.rest.util.RESTUtils;
import org.geoserver.test.GeoServerSystemTestSupport;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.ysld.YsldHandler;
import org.geotools.data.DataAccess;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.NameImpl;
import org.geotools.referencing.CRS;
import org.geotools.util.NullProgressListener;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.Feature;
import org.opengis.feature.Property;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;

import javax.mail.internet.InternetHeaders;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.servlet.http.HttpServletRequest;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

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.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;

public class AppIntegrationTest extends GeoServerSystemTestSupport {

    @Override
    protected void setUpTestData(SystemTestData testData) throws Exception {
        super.setUpTestData(testData);
        testData.setUpWcs10RasterLayers();
    }

    @Before
    public void removeMaps() {
        removeLayerGroup("sf", "map1");
        removeLayerGroup("sf", "map2");

        removeLayerGroup("cgf", "map1");
        removeLayerGroup("cgf", "map2");
    }

    @Before
    public void removeLayers() {
        removeLayer("gs", "foo");
        removeLayer("sf", "foo");
        removeLayer("cdf", "foo");

        removeLayer("gs", "point");
        removeLayer("gs", "point space");
        removeLayer("gs", "point_space");

        removeLayer("cgf", "renamedLayer");
        removeLayer("cgf", "Points-map");
        removeLayer("cgf", "Lines-map");
    }

    @Before
    public void removeFiles() {
        removeStore("gs", "point");
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point/point.shp").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point/point.prj").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point/point.shx").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point/point.dbf").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.shp").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.prj").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.shx").delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.dbf").delete();

        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point_space/point space.shp")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point_space/point space.prj")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point_space/point space.shx")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "data/gs/point_space/point space.dbf")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point_space/point space.shp")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point_space/point space.prj")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point_space/point space.shx")
                .delete();
        new File(getCatalog().getResourceLoader().getBaseDirectory(), "uploads/gs/point_space/point space.dbf")
                .delete();
    }

    @Test
    public void testPageLayers() throws Exception {
        JSONObject obj = (JSONObject) getAsJSON(("/app/api/layers/sf"));
        JSONArray arr = obj.getJSONArray("layers");
        assertEquals(3, arr.size());

        obj = (JSONObject) getAsJSON(("/app/api/layers/sf?page=1&count=1"));
        arr = obj.getJSONArray("layers");
        assertEquals(1, arr.size());
    }

    @Test
    public void testPageMaps() throws Exception {
        Catalog cat = getCatalog();
        CatalogBuilder catBuilder = new CatalogBuilder(cat);

        LayerInfo pgf = cat.getLayerByName("sf:PrimitiveGeoFeature");

        LayerGroupInfo map = cat.getFactory().createLayerGroup();
        map.setWorkspace(cat.getWorkspaceByName("sf"));
        map.setName("map1");
        map.getLayers().add(pgf);
        map.getStyles().add(null);
        catBuilder.calculateLayerGroupBounds(map);
        cat.add(map);

        map = cat.getFactory().createLayerGroup();
        map.setWorkspace(cat.getWorkspaceByName("sf"));
        map.setName("map2");
        map.getLayers().add(pgf);
        map.getStyles().add(null);
        catBuilder.calculateLayerGroupBounds(map);
        cat.add(map);

        JSONObject obj = (JSONObject) getAsJSON(("/app/api/maps/sf"));
        assertEquals(2, obj.getInt("total"));
        assertEquals(0, obj.getInt("page"));
        assertEquals(2, obj.getInt("count"));

        JSONArray arr = obj.getJSONArray("maps");
        assertEquals(2, arr.size());

        obj = (JSONObject) getAsJSON(("/app/api/maps/sf?page=1&count=1"));
        assertEquals(2, obj.getInt("total"));
        assertEquals(1, obj.getInt("page"));
        assertEquals(1, obj.getInt("count"));
        arr = obj.getJSONArray("maps");
        assertEquals(1, arr.size());
    }

    @Test
    public void testPageStores() throws Exception {
        JSONObject obj = (JSONObject) getAsJSON(("/app/api/stores/sf"));
        JSONArray arr = obj.getJSONArray("stores");
        assertEquals(1, arr.size());

        obj = (JSONObject) getAsJSON(("/app/api/stores/sf?page=1&count=1"));
        arr = obj.getJSONArray("stores");
        assertEquals(0, arr.size());
    }

    @Test
    public void testListAttributes() throws Exception {
        Catalog cat = getCatalog();

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("get");

        StoreController ctrl = new StoreController(getGeoServer());
        JSONObj obj = ctrl.attributes("sf", "sf", "PrimitiveGeoFeature", 10, request);
        JSONArr attributes = obj.object("schema").array("attributes");
        JSONArr values = obj.array("values");

        //Page through actual features and ensure values match what is returned
        StoreInfo store = cat.getStoreByName("sf", "sf", StoreInfo.class);
        DataAccess data = ((DataStoreInfo) store).getDataStore(new NullProgressListener());
        FeatureSource source = data.getFeatureSource(new NameImpl("PrimitiveGeoFeature"));

        Query query = new Query(Query.ALL);
        query.setMaxFeatures(10);
        FeatureIterator features = source.getFeatures(query).features();
        int featureIndex = 0;
        while (features.hasNext()) {
            Feature feature = features.next();
            JSONArr featureJSON = (JSONArr) values.at(featureIndex);
            Property[] properties = feature.getProperties().toArray(new Property[feature.getProperties().size()]);

            for (int i = 0; i < attributes.size(); i++) {

                //Verify the schema matches the feature
                JSONObj attribute = attributes.object(i);
                assertEquals(attribute.get("type"),
                        properties[i].getDescriptor().getType().getBinding().getSimpleName());
                assertEquals(attribute.get("name"), properties[i].getDescriptor().getName().getLocalPart());

                //Verify the value matches the feature
                assertEquals(featureJSON.str(i),
                        properties[i].getValue() == null ? null : properties[i].getValue().toString());
            }
            featureIndex++;
        }
    }

    @Test
    public void testImportShapefileAsZip() throws Exception {
        Catalog catalog = getCatalog();
        //Test default root of "data"
        RESTUtils.loadMapFromGlobal().remove("root");
        assertNull(catalog.getLayerByName("gs:point"));

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("post");

        createMultiPartFormContent(request, "form-data; name=\"upload\"; filename=\"point.zip\"", "application/zip",
                IOUtils.toByteArray(getClass().getResourceAsStream("point.shp.zip")));

        JSONObj result = ctrl.importFile("gs", request);
        Long id = Long.parseLong(result.str("id"));

        //Wait for the import to complete
        result = pollImport(ctrl, "gs", id, "pending", request);
        assertNotNull(result);
        result = ctrl.update("gs", id, getUpdateTasks(result), request);
        result = pollImport(ctrl, "gs", id, "complete", request);
        assertNotNull(result);

        assertEquals(1, result.array("tasks").size());
        JSONObj obj = result.array("tasks").object(0);

        assertEquals("gs", obj.object("layer").str("workspace"));
        assertEquals("point", obj.object("layer").str("name"));

        LayerInfo l = catalog.getLayerByName("gs:point");
        StoreInfo s = catalog.getStoreByName("gs", "point", StoreInfo.class);
        assertNotNull(l);
        assertNotNull(s);
        //Wait for the taskListener to move the imported file
        Thread.sleep(500);
        assertTrue(new File(catalog.getResourceLoader().getBaseDirectory(), "data/gs/point/point.shp").exists());
        assertTrue(new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                .get("url").toString()).getFile()).exists());
        assertEquals(new File(catalog.getResourceLoader().getBaseDirectory(), "data/gs/point").getAbsoluteFile(),
                new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                        .get("url").toString()).getFile()).getAbsoluteFile());

        // ensure style in workspace
        StyleInfo style = l.getDefaultStyle();
        assertNotNull(style.getWorkspace());

        //Try to reimport the same store - should succeed
        createMultiPartFormContent(request, "form-data; name=\"upload\"; filename=\"point.zip\"", "application/zip",
                IOUtils.toByteArray(getClass().getResourceAsStream("point.shp.zip")));
        obj = ctrl.importFile("gs", request);

        assertNotNull(obj.get("id"));

    }

    @Test
    public void testImportShapefiles() throws Exception {
        Catalog catalog = getCatalog();
        catalog.addListener(new UploadDeleteCatalogListener(catalog));
        //Test REST global root
        GeoServerInfo gsInfo = GeoServerExtensions.bean(GeoServer.class).getGlobal();
        SettingsInfo info = gsInfo.getSettings();
        info.getMetadata().put("root",
                catalog.getResourceLoader().findOrCreateDirectory("uploads").getAbsolutePath());
        getGeoServer().save(gsInfo);
        assertNull(catalog.getLayerByName("gs:point"));

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);
        StoreController storeCtrl = new StoreController(getGeoServer());

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("post");

        //Import as separate files
        MimeMultipart body = initMultiPartFormContent(request);

        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point.dbf\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point.dbf")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point.prj\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point.prj")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point.shp\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point.shp")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point.shx\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point.shx")));

        createMultiPartFormContent(body, request);

        JSONObj result = ctrl.importFile("gs", request);
        Long id = Long.parseLong(result.str("id"));

        //Wait for the import to complete
        result = pollImport(ctrl, "gs", id, "pending", request);
        assertNotNull(result);
        result = ctrl.update("gs", id, getUpdateTasks(result), request);
        result = pollImport(ctrl, "gs", id, "complete", request);
        assertNotNull(result);

        assertEquals(1, result.array("tasks").size());
        JSONObj obj = result.array("tasks").object(0);

        assertEquals("gs", obj.object("layer").str("workspace"));
        assertEquals("point", obj.object("layer").str("name"));

        LayerInfo l = catalog.getLayerByName("gs:point");
        StoreInfo s = catalog.getStoreByName("gs", "point", StoreInfo.class);
        assertNotNull(l);
        assertNotNull(s);
        //Wait for the taskListener to move the imported file
        Thread.sleep(500);
        assertTrue(new File(catalog.getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.shp").exists());
        assertTrue(new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                .get("url").toString()).getFile()).exists());
        assertEquals(new File(catalog.getResourceLoader().getBaseDirectory(), "uploads/gs/point").getAbsoluteFile(),
                new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                        .get("url").toString()).getFile()).getAbsoluteFile());

        // ensure style in workspace
        StyleInfo style = l.getDefaultStyle();
        assertNotNull(style.getWorkspace());

        //Delete the store and re-upload:
        MockHttpServletRequest deleteRequest = new MockHttpServletRequest();
        deleteRequest.setContextPath("/geoserver");
        deleteRequest.setRequestURI("/geoserver/hello");
        deleteRequest.setMethod("delete");
        storeCtrl.delete("gs", "point", true, deleteRequest);
        assertFalse(
                new File(catalog.getResourceLoader().getBaseDirectory(), "uploads/gs/point/point.shp").exists());
        result = ctrl.importFile("gs", request);
        id = Long.parseLong(result.str("id"));
        //Wait for the import to complete
        result = pollImport(ctrl, "gs", id, "pending", request);
        assertNotNull(result);
        result = ctrl.update("gs", id, getUpdateTasks(result), request);
        result = pollImport(ctrl, "gs", id, "complete", request);
        assertNotNull(result);
        assertEquals(1, result.array("tasks").size());
        assertEquals("COMPLETE", result.array("tasks").object(0).get("status"));
    }

    @Test
    public void testImportShapefilesWithSpaceInName() throws Exception {
        Catalog catalog = getCatalog();
        //Test REST global root
        GeoServerInfo gsInfo = GeoServerExtensions.bean(GeoServer.class).getGlobal();
        SettingsInfo info = gsInfo.getSettings();
        info.getMetadata().put("root",
                catalog.getResourceLoader().findOrCreateDirectory("uploads").getAbsolutePath());
        getGeoServer().save(gsInfo);
        assertNull(catalog.getLayerByName("gs:point_space"));

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);
        StoreController storeCtrl = new StoreController(getGeoServer());

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("post");

        //Import as separate files
        MimeMultipart body = initMultiPartFormContent(request);

        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point space.dbf\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point space.dbf")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point space.prj\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point space.prj")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point space.shp\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point space.shp")));
        appendMultiPartFormContent(body, "form-data; name=\"upload\"; filename=\"point space.shx\"",
                "application/octet-stream", IOUtils.toByteArray(getClass().getResourceAsStream("point space.shx")));

        createMultiPartFormContent(body, request);

        JSONObj result = ctrl.importFile("gs", request);
        Long id = Long.parseLong(result.str("id"));

        //Wait for the import to complete
        result = pollImport(ctrl, "gs", id, "pending", request);
        assertNotNull(result);
        result = ctrl.update("gs", id, getUpdateTasks(result), request);
        result = pollImport(ctrl, "gs", id, "complete", request);
        assertNotNull(result);
        //Apparently the catalog is time-sensitive now...
        Thread.sleep(100);
        LayerInfo l = catalog.getLayerByName("gs:point_20space");
        StoreInfo s = catalog.getStoreByName("gs", "point_space", StoreInfo.class);
        assertNotNull(l);
        assertNotNull(s);
        //Wait for the taskListener to move the imported file
        Thread.sleep(500);
        assertTrue(
                new File(catalog.getResourceLoader().getBaseDirectory(), "uploads/gs/point_space/point space.shp")
                        .exists());
        assertTrue(new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                .get("url").toString()).getFile()).exists());
        assertEquals(
                new File(catalog.getResourceLoader().getBaseDirectory(), "uploads/gs/point_space")
                        .getAbsoluteFile(),
                new File(new URL(ResourcePool.getParams(s.getConnectionParameters(), catalog.getResourceLoader())
                        .get("url").toString()).getFile()).getAbsoluteFile());

        StyleInfo style = l.getDefaultStyle();
        assertEquals("point_space", l.getDefaultStyle().getName());
        assertEquals("point_20space", l.getResource().getName());
    }

    @Test
    public void testImportDb() throws Exception {
        Catalog catalog = getCatalog();
        assertNull(catalog.getLayerByName("gs:point"));

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);

        try (H2TestData data = new H2TestData()) {

            MockHttpServletRequest request = new MockHttpServletRequest();
            request.setContextPath("/geoserver");
            request.setRequestURI("/geoserver/hello");
            request.setMethod("post");

            JSONObj result = data.createConnectionParameters();
            result = ctrl.importDb("gs", result, request);

            Long id = Long.parseLong(result.str("id"));
            result = pollImport(ctrl, "gs", id, "pending", request);
            assertNotNull(result);
            assertTrue(result.integer("tasksTotal") > 0);
            List<String> names = Arrays.asList(new String[] { "ft1", "ft2", "ft3" });
            JSONArr tasks = new JSONArr();
            for (JSONObj o : result.array("tasks").objects()) {
                if (names.contains(o.get("name")) && o.get("status").equals("READY")) {
                    tasks.add(new JSONObj().put("task", o.get("task").toString()));
                    assertEquals("table", o.get("type"));
                }
            }
            JSONObj response = new JSONObj();
            response.put("tasks", tasks);

            result = ctrl.update("gs", id, response, request);
            result = pollImport(ctrl, "gs", id, "complete", request);
            assertNotNull(result);

            int complete = 0;
            int ready = 0;
            int no_crs = 0;
            int failed = 0;
            tasks = new JSONArr();

            for (JSONObj o : result.array("tasks").objects()) {
                if (o.get("status").equals("READY")) {
                    ready++;
                }
                if (o.get("status").equals("NO_CRS")) {
                    no_crs++;
                    String srs = "EPSG:4326";
                    tasks.add(new JSONObj().put("task", o.get("task").toString()).put("proj",
                            IO.proj(new JSONObj(), CRS.decode(srs), srs)));
                }
                if (o.get("status").equals("COMPLETE")) {
                    complete++;
                }
                if (o.get("status").equals("ERROR") || o.get("status").equals("NO_BOUNDS")) {
                    failed++;
                }
            }
            assertEquals(0, ready);
            assertEquals(1, complete);
            assertEquals(2, no_crs);
            assertEquals(0, failed);

            response = new JSONObj();
            response.put("tasks", tasks);

            result = ctrl.update("gs", id, response, request);
            //Wait for the import to complete
            result = pollImport(ctrl, "gs", id, "complete", request);
            assertNotNull(result);

            for (JSONObj o : result.array("tasks").objects()) {
                assertEquals("COMPLETE", o.get("status"));
            }

            //Try to reimport the same store - should fail and return existing store
            result = data.createConnectionParameters();
            result = ctrl.importDb("gs", result, request);

            assertNotNull(result.get("store"));
            assertNull(result.get("id"));
        }
    }

    @Test
    public void testImportGeoJSONintoDb() throws IOException, Exception {
        Catalog catalog = getCatalog();
        StoreInfo targetStore = catalog.getStoreByName("sf", "sf", StoreInfo.class);
        assertNotNull(targetStore);

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("post");

        createMultiPartFormContent(request, "form-data; name=\"upload\"; filename=\"point.json\"",
                "application/json", IOUtils.toByteArray(getClass().getResourceAsStream("point.json")));

        JSONObj result = ctrl.importFile("sf", "sf", request);
        Long id = Long.parseLong(result.str("id"));

        //Wait for the import to complete
        result = pollImport(ctrl, "gs", id, "pending", request);
        assertNotNull(result);
        result = ctrl.update("gs", id, getUpdateTasks(result), request);
        result = pollImport(ctrl, "gs", id, "complete", request);
        assertNotNull(result);

        assertEquals(1, result.array("tasks").size());
        JSONObj obj = result.array("tasks").object(0);
        assertEquals("COMPLETE", obj.get("status"));

        assertEquals("sf", obj.object("layer").str("workspace"));
        assertEquals("point", obj.object("layer").str("name"));

        LayerInfo l = catalog.getLayerByName("sf:point");
        assertNotNull(l);
        FeatureTypeInfo f = (FeatureTypeInfo) l.getResource();
        assertEquals(targetStore, f.getStore());

        // ensure style in workspace
        StyleInfo s = l.getDefaultStyle();
        assertNotNull(s.getWorkspace());
    }

    private JSONObj getUpdateTasks(JSONObj result) {
        JSONArr tasks = new JSONArr();
        for (JSONObj o : result.array("tasks").objects()) {
            if (o.get("status").equals("READY")) {
                tasks.add(new JSONObj().put("task", o.get("task").toString()));
            }
        }
        JSONObj response = new JSONObj();
        return response.put("tasks", tasks);
    }

    private JSONObj pollImport(ImportController ctrl, String ws, Long id, String state,
            HttpServletRequest request) {
        int attempts = 100;
        int interval = 10;

        for (int i = 0; i < attempts; i++) {
            try {
                Thread.sleep(interval);
                JSONObj obj = ctrl.get(ws, id, request);
                if (obj.get("state") != null && obj.get("state").equals(state)) {
                    return obj;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    @Test
    public void testImporterBeans() {
        //This will throw an exception if multiple beans are visible to geoserver
        GeoServerExtensions.bean(Importer.class, applicationContext);
    }

    @Test
    public void testImportInfo() throws IOException {
        Catalog catalog = getCatalog();
        StoreInfo targetStore = catalog.getStoreByName("sf", "sf", StoreInfo.class);
        assertNotNull(targetStore);

        ImportController ctrl = new ImportController(getGeoServer(), applicationContext);

        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/hello");
        request.setMethod("post");

        JSONObj obj = ctrl.info("sf");

        assertEquals("sf", obj.str("workspace"));
        assertNotNull(obj.get("spaceAvailable"));
        assertEquals(obj.get("spaceAvailable"), obj.get("tmpSpace"));
    }

    @Test
    public void testIconsUploadDelete() throws Exception {
        Catalog catalog = getCatalog();
        IconController ctrl = new IconController(getGeoServer());

        // test upload
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/api/icons/cite");
        request.setMethod("post");

        createMultiPartFormContent(request, "form-data; name=\"icon\"; filename=\"STYLE.PROPERTIES\"",
                "text/x-java-properties", "square=LINESTRING((0 0,0 1,1 1,1 0,0 0))".getBytes());

        JSONArr arr = ctrl.create("cite", request);
        assertEquals(1, arr.size());

        Resource r = catalog.getResourceLoader().get("workspaces/cite/styles/STYLE.PROPERTIES");
        assertEquals("created", Resource.Type.RESOURCE, r.getType());

        // test delete
        MockHttpServletRequestBuilder delete = delete("/api/icons/cite/icon.png");
        ctrl.delete("cite", "STYLE.PROPERTIES");

        r = catalog.getResourceLoader().get("workspaces/cite/styles/STYLE.PROPERTIES");
        assertEquals("deleted", Resource.Type.UNDEFINED, r.getType());

        //Global style directory

        // test upload
        request = new MockHttpServletRequest();
        request.setContextPath("/geoserver");
        request.setRequestURI("/geoserver/api/icons");
        request.setMethod("post");

        createMultiPartFormContent(request, "form-data; name=\"icon\"; filename=\"STYLE.PROPERTIES\"",
                "text/x-java-properties", "square=LINESTRING((0 0,0 1,1 1,1 0,0 0))".getBytes());

        arr = ctrl.create(request);
        assertEquals(1, arr.size());

        r = catalog.getResourceLoader().get("styles/STYLE.PROPERTIES");
        assertEquals("created", Resource.Type.RESOURCE, r.getType());

        // test delete
        delete = delete("/api/icons/icon.png");
        ctrl.delete("STYLE.PROPERTIES");

        r = catalog.getResourceLoader().get("styles/STYLE.PROPERTIES");
        assertEquals("deleted", Resource.Type.UNDEFINED, r.getType());
    }

    @Test
    public void testWorkspaceExport() throws Exception {
        MockHttpServletResponse response = doWorkspaceExport("sf");

        assertEquals("application/zip", response.getContentType());
        assertEquals("attachment; filename=\"sf.zip\"", response.getHeader("Content-Disposition"));

        Path tmp = Files.createTempDirectory(Paths.get("target"), "export");
        org.geoserver.data.util.IOUtils.decompress(new ByteArrayInputStream(response.getContentAsByteArray()),
                tmp.toFile());

        assertTrue(tmp.resolve("bundle.json").toFile().exists());
    }

    @Test
    public void testWorkspaceImport() throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest();
        createMultiPartFormContent(request, "form-data; name=\"file\"; filename=\"sf.zip\"", "application/zip",
                doWorkspaceExport("sf").getContentAsByteArray());

        Catalog cat = getCatalog();
        assertNull(cat.getLayerByName("gs:PrimitiveGeoFeature"));

        MockHttpServletResponse response = new MockHttpServletResponse();
        WorkspaceController ctrl = new WorkspaceController(getGeoServer(), new RecentObjectCache());
        ctrl.inport("gs", request, response);

        assertNotNull(cat.getLayerByName("gs:PrimitiveGeoFeature"));
    }

    MockHttpServletResponse doWorkspaceExport(String wsName) throws Exception {
        WorkspaceController ctrl = new WorkspaceController(getGeoServer(), new RecentObjectCache());

        MockHttpServletResponse response = new MockHttpServletResponse();
        ctrl.export(wsName, response);

        return response;
    }

    void createMultiPartFormContent(MockHttpServletRequest request, String contentDisposition, String contentType,
            byte[] content) throws Exception {
        MimeMultipart body = new MimeMultipart();
        request.setContentType(body.getContentType());
        InternetHeaders headers = new InternetHeaders();
        headers.setHeader("Content-Disposition", contentDisposition);
        headers.setHeader("Content-Type", contentType);
        body.addBodyPart(new MimeBodyPart(headers, content));

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        body.writeTo(bout);
        request.setContent(bout.toByteArray());
    }

    void createMultiPartFormContent(MimeMultipart body, MockHttpServletRequest request) throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        body.writeTo(bout);
        request.setContent(bout.toByteArray());
    }

    MimeMultipart initMultiPartFormContent(MockHttpServletRequest request) throws Exception {
        MimeMultipart body = new MimeMultipart();
        request.setContentType(body.getContentType());

        return body;
    }

    MimeMultipart appendMultiPartFormContent(MimeMultipart body, String contentDisposition, String contentType,
            byte[] content) throws Exception {
        InternetHeaders headers = new InternetHeaders();
        headers.setHeader("Content-Disposition", contentDisposition);
        headers.setHeader("Content-Type", contentType);
        body.addBodyPart(new MimeBodyPart(headers, content));

        return body;
    }

    @Test
    public void testCopyMapWithLayers() throws Exception {
        Catalog catalog = getCatalog();
        CatalogBuilder catalogBuilder = new CatalogBuilder(catalog);

        LayerInfo points = catalog.getLayerByName("cgf:Points");
        LayerInfo lines = catalog.getLayerByName("cgf:Lines");

        LayerGroupInfo map = catalog.getFactory().createLayerGroup();
        map.setWorkspace(catalog.getWorkspaceByName("cgf"));
        map.setName("map1");
        map.getLayers().add(lines);
        map.getLayers().add(points);
        map.getStyles().add(null);
        map.getStyles().add(null);
        catalogBuilder.calculateLayerGroupBounds(map);
        catalog.add(map);

        assertNotNull(catalog.getLayerGroupByName("cgf:map1"));
        assertNotNull(catalog.getLayerByName("cgf:Points"));
        assertNotNull(catalog.getLayerByName("cgf:Lines"));
        assertNull(catalog.getLayerGroupByName("cgf:map2"));
        assertNull(catalog.getLayerByName("cgf:renamedLayer"));
        assertNull(catalog.getLayerByName("cgf:Lines-map"));

        JSONObj obj = new JSONObj();
        obj.put("name", "map2");
        obj.put("copylayers", true);
        obj.putArray("layers").addObject().put("name", "renamedLayer").putObject("layer").put("name", "Points")
                .put("workspace", "cgf");

        MockHttpServletResponse resp = putAsServletResponse("/app/api/maps/cgf/map1/copy", obj.toString(),
                MediaType.APPLICATION_JSON_VALUE);
        assertEquals(200, resp.getStatus());

        assertNotNull(catalog.getLayerGroupByName("cgf:map2"));
        assertNotNull(catalog.getLayerByName("cgf:renamedLayer"));
        assertNotNull(catalog.getLayerByName("cgf:Lines-map"));
    }

    @Test
    public void testCreateLayerFromCopy() throws Exception {
        Catalog catalog = getCatalog();
        assertNull(catalog.getLayerByName("sf:foo"));

        JSONObj obj = new JSONObj();
        obj.put("name", "foo");
        obj.putObject("layer").put("name", "PrimitiveGeoFeature").put("workspace", "sf");

        MockHttpServletResponse resp = postAsServletResponse("/app/api/layers/sf", obj.toString(),
                MediaType.APPLICATION_JSON_VALUE);
        assertEquals(201, resp.getStatus());

        assertNotNull(catalog.getLayerByName("sf:foo"));
    }

    @Test
    public void testCreateLayerFromResource() throws Exception {
        Catalog catalog = getCatalog();
        assertNull(catalog.getLayerByName("sf:foo"));

        JSONObj obj = new JSONObj();
        obj.put("name", "foo");
        obj.putObject("resource").put("name", "PrimitiveGeoFeature").put("store", "sf").put("workspace", "sf");

        MockHttpServletResponse resp = postAsServletResponse("/app/api/layers/sf", obj.toString(),
                MediaType.APPLICATION_JSON_VALUE);
        assertEquals(201, resp.getStatus());

        assertNotNull(catalog.getLayerByName("sf:foo"));
    }

    @Test
    public void testCreateLayerFromRasterResource() throws Exception {
        Catalog catalog = getCatalog();
        assertNull(catalog.getLayerByName("cdf:foo"));
        assertNotNull(catalog.getLayerByName("cdf:usa"));

        JSONObj obj = new JSONObj();
        obj.put("name", "foo");
        obj.putObject("resource").put("name", "usa").put("store", "usa").put("workspace", "cdf");

        MockHttpServletResponse resp = postAsServletResponse("/app/api/layers/cdf", obj.toString(),
                MediaType.APPLICATION_JSON_VALUE);
        assertEquals(201, resp.getStatus());

        assertNotNull(catalog.getLayerByName("cdf:foo"));

    }

    @Test
    public void testPutStyleExistingSLD() throws Exception {
        Catalog catalog = getCatalog();
        LayerInfo layer = catalog.getLayerByName("sf:PrimitiveGeoFeature");
        assertNotNull(layer.getDefaultStyle());
        assertEquals(SLDHandler.FORMAT, layer.getDefaultStyle().getFormat());

        String sldName = layer.getDefaultStyle().getName();

        MockHttpServletResponse resp = putAsServletResponse("/app/api/layers/sf/PrimitiveGeoFeature/style",
                "title: ysld", YsldHandler.MIMETYPE);
        assertEquals(200, resp.getStatus());

        layer = catalog.getLayerByName("sf:PrimitiveGeoFeature");
        assertNotNull(layer.getDefaultStyle());
        assertEquals(2, layer.getStyles().size());
        assertEquals(sldName + "_YSLD", layer.getDefaultStyle().getName());
        assertEquals(YsldHandler.FORMAT, layer.getDefaultStyle().getFormat());
    }

    /* (SUITE-1072) Full WMS URL is not compatible with GeoServerSystemTestSupport
     * Removing test case until a viable workaround can be found
    @Test
    public void testThumbnail() throws Exception {
    ThumbnailController ctrl = applicationContext.getBean(ThumbnailController.class);
    LayerController layerCtrl = applicationContext.getBean(LayerController.class);
    AppConfiguration config = applicationContext.getBean(AppConfiguration.class);
        
    //Precision on file.lastModified for the current architecture
    int filePrecision = 1000;
    if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
        //Still keep a small delay, just in case
        filePrecision = 10;
    }
        
    //Setup map
    Catalog catalog = getCatalog();
    CatalogBuilder catBuilder = new CatalogBuilder(catalog);
        
    LayerInfo layer = catalog.getLayerByName("sf:PrimitiveGeoFeature");
        
    StyleGenerator styleGenerator = new StyleGenerator(catalog);
    StyleInfo style = styleGenerator.createStyle((FeatureTypeInfo)layer.getResource());
        
    catalog.add(style);
    layer.setDefaultStyle(style);
    catalog.save(layer);
        
    LayerGroupInfo map = catalog.getFactory().createLayerGroup();
    map.setWorkspace(catalog.getWorkspaceByName("sf"));
    map.setName("map");
    map.getLayers().add(layer);
    map.getStyles().add(style);
    catBuilder.calculateLayerGroupBounds(map);
    catalog.add(map);
        
    assertNotNull(map);
        
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setContextPath("/geoserver");
    request.setRequestURI("/geoserver/hello");
    request.setMethod("get");
        
    //Test initial get
    assertFalse(config.cacheFile(ThumbnailController.thumbnailFilename(layer)).exists());
    assertFalse(config.cacheFile(ThumbnailController.thumbnailFilename(map)).exists());
    HttpEntity<byte[]> response = ctrl.getMap("sf", "map", false, request);
    BufferedImage image = ImageIO.read(new ByteArrayInputStream(response.getBody()));
        
    File imageFile = config.cacheFile(ThumbnailController.thumbnailFilename(map));
    assertTrue(imageFile.exists());
        
    long lastModified = imageFile.lastModified();
        
    //Test cached get
    response = ctrl.getMap("sf", "map", true, request);
    imageFile = config.cacheFile(ThumbnailController.thumbnailFilename(map));
    assertTrue(imageFile.exists());
    assertEquals(lastModified, imageFile.lastModified());
        
    //Test invalidate
    ctrl.clearThumbnail(map);
    assertFalse(config.cacheFile(ThumbnailController.thumbnailFilename(map)).exists());
    //file.lastModified is only accurate to the second
    Thread.sleep(filePrecision);
        
    response = ctrl.getMap("sf", "map", true, request);
        
    imageFile = config.cacheFile(ThumbnailController.thumbnailFilename(map));
    assertTrue(imageFile.exists());
    long lm2 = imageFile.lastModified();
    assertTrue(lastModified < lm2);
    lastModified = imageFile.lastModified();
        
    //Test layer get
    response = ctrl.getLayer("sf", "PrimitiveGeoFeature", true, request);
    BufferedImage image2 = ImageIO.read(new ByteArrayInputStream(response.getBody()));
        
    //Compare high/low res
    assertEquals(image.getWidth()*2, image2.getWidth());
    assertEquals(image.getHeight()*2, image2.getHeight());
        
        
    imageFile = config.cacheFile(ThumbnailController.thumbnailFilename(layer));
    assertTrue(imageFile.exists());
        
    //Test layer invalidating map
    request = new MockHttpServletRequest();
    request.setContextPath("/geoserver");
    request.setRequestURI("/geoserver/hello");
    request.setMethod("put");
        
    layerCtrl.put("sf", "PrimitiveGeoFeature", new JSONObj().put("title", layer.getTitle()), request);
        
    //Update proxy
    assertFalse(config.cacheFile(ThumbnailController.thumbnailFilename(layer)).exists());
    assertFalse(config.cacheFile(ThumbnailController.thumbnailFilename(map)).exists());
    }
    */

    @Test
    public void testNameUtil() throws Exception {
        Catalog catalog = getCatalog();
        CatalogBuilder catalogBuilder = new CatalogBuilder(catalog);

        LayerInfo points = catalog.getLayerByName("cgf:Points");
        StyleInfo pointStyle = points.getDefaultStyle();

        LayerGroupInfo pointMap = catalog.getFactory().createLayerGroup();
        pointMap.setWorkspace(catalog.getWorkspaceByName("cgf"));
        pointMap.setName("Points");
        pointMap.getLayers().add(points);
        pointMap.getStyles().add(null);
        catalogBuilder.calculateLayerGroupBounds(pointMap);
        catalog.add(pointMap);

        assertNotNull(catalog.getLayerGroupByName(pointMap.prefixedName()));
        assertNotNull(catalog.getLayerByName(points.prefixedName()));
        assertNotNull(catalog.getStyleByName(pointStyle.prefixedName()));

        //Test unique against existing catalog entries
        assertEquals(points.getName() + "0", NameUtil.unique(points.getName(), points.getClass(), catalog));
        assertEquals(pointMap.getName() + "0", NameUtil.unique(pointMap.getName(), pointMap.getClass(), catalog));
        assertEquals(pointStyle.getName() + "0",
                NameUtil.unique(pointStyle.getName(), pointStyle.getClass(), catalog));

        //Test unique with no existing entries
        assertEquals("unique", NameUtil.unique("unique", points.getClass(), catalog));
        assertEquals("unique", NameUtil.unique("unique", pointMap.getClass(), catalog));
        assertEquals("unique", NameUtil.unique("unique", pointStyle.getClass(), catalog));

    }

    @Test
    public void testGetRenderingTransforms() throws Exception {
        JSON json = getAsJSON(("/app/api/serverInfo/renderingTransforms"));
        if (json instanceof JSONObject) {
            //getAsJson returned an exception message
            fail(json.toString());
        }
        JSONArray arr = (JSONArray) json;
        //Make sure we get something from each factory
        boolean hasHeatmap = false;
        boolean hasBuffer = false;
        boolean hasContour = false;

        for (Object o : arr.toArray()) {
            String name = ((JSONObject) o).getString("name");
            if ("vec:Heatmap".equals(name)) {
                hasHeatmap = true;
            }
            if ("geo:buffer".equals(name)) {
                hasBuffer = true;
            }
            if ("ras:Contour".equals(name)) {
                hasContour = true;
            }
        }
        assertTrue(hasHeatmap);
        assertTrue(hasBuffer);
        assertTrue(hasContour);
    }
}