diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java index 39f4407..8722e38 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -1,7 +1,7 @@ /* * GeoServer-Manager - Simple Manager Library for GeoServer * - * Copyright (C) 2007,2015 GeoSolutions S.A.S. + * Copyright (C) 2007,2015,2016 GeoSolutions S.A.S. * http://www.geo-solutions.it * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -65,6 +65,7 @@ import org.slf4j.LoggerFactory; * * @author ETj (etj at geo-solutions.it) * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it + * @author Lennart Karsten - lennart.k@thinking-aloud.eu */ public class GeoServerRESTPublisher { @@ -761,7 +762,9 @@ public class GeoServerRESTPublisher { /** ImageMosaic */ IMAGEMOSAIC, /** Geo referenced image (JPEG,PNG,TIF) */ - WORLDIMAGE; + WORLDIMAGE, + /** Esri ArcGrid */ + ARCGRID; /** * Returns a lowercase representation of the parameter value, suitable to construct the rest call. @@ -1519,6 +1522,215 @@ public class GeoServerRESTPublisher { .toString()) } : (NameValuePair[]) null); } + // ========================================================================== + // === ARCGRID + // ========================================================================== + + /** + * Upload and publish a ArcGrid image. + * + * @param workspace Workspace to use + * @param storeName The store name to be used or created. + * @param arcgrid The ArcGrid file. + * @return true if success. + * @throws FileNotFoundException if ArcGrid file does not exist. + */ + public boolean publishArcGrid(String workspace, String storeName, File arcgrid) + throws FileNotFoundException { + return publishCoverage(workspace, storeName, CoverageStoreExtension.ARCGRID, + "image/arcgrid", arcgrid, ParameterConfigure.FIRST, (NameValuePair[]) null); + } + + /** + * Upload and publish a ArcGrid image. + * + * @param workspace Workspace to use + * @param storeName Name of the coveragestore (if null the file name will be used) + * @param coverageName the name of the coverage (if null the file name will be used) + * @param arcgrid file to upload + * @return true if the operation completed successfully. + * @throws FileNotFoundException if file does not exists + * @throws IllegalArgumentException if workspace or arcgrid are null + */ + public boolean publishArcGrid(final String workspace, final String storeName, + final String coverageName, final File arcgrid) throws FileNotFoundException, + IllegalArgumentException { + if (workspace == null || arcgrid == null) + throw new IllegalArgumentException("Unable to proceed, some arguments are null"); + + return publishCoverage( + workspace, + (storeName != null) ? storeName : FilenameUtils.getBaseName(arcgrid + .getAbsolutePath()), CoverageStoreExtension.ARCGRID, "image/arcgrid", + arcgrid, ParameterConfigure.FIRST, + (coverageName != null) ? new NameValuePair[] { new NameValuePair("coverageName", + coverageName) } : (NameValuePair[]) null); + } + + /** + * Same as {@link #publishArcGrid(String, String, String, File, String, ProjectionPolicy, String, double[])} but without the last parameter + * (bbox). Kept here for backwards compatibility. + * + * @deprecated use the former method with bbox set to null. + */ + public boolean publishArcGrid(String workspace, String storeName, String resourceName, + File arcgrid, String srs, ProjectionPolicy policy, String defaultStyle) + throws FileNotFoundException, IllegalArgumentException { + return publishArcGrid(workspace, storeName, resourceName, arcgrid, srs, policy, + defaultStyle, null); + } + + /** + * Upload and publish a ArcGrid image. + * + * @param workspace Workspace to use + * @param storeName Name of the coveragestore (if null the file name will be used) + * @param coverageName the name of the coverage (if null the file name will be used) + * @param arcgrid file to upload + * @param srs the native CRS + * @param policy projection policy. See {@link ProjectionPolicy}. + * @param defaultStyle the default style to apply. + * @param bbox An array of 4 doubles indicating envelope in EPSG:4326. Order is [Xmin, Ymin, Xmax, Ymax]. + * @return true if the operation completed successfully. + * @throws FileNotFoundException if file does not exists + * @throws IllegalArgumentException if workspace or arcgrid are null + * + */ + public boolean publishArcGrid(String workspace, String storeName, String coverageName, + File arcgrid, String srs, ProjectionPolicy policy, String defaultStyle, double[] bbox) + throws FileNotFoundException, IllegalArgumentException { + if (workspace == null || storeName == null || arcgrid == null || coverageName == null + || srs == null || policy == null || defaultStyle == null) + throw new IllegalArgumentException("Unable to run: null parameter"); + + if (!createCoverageStore( + workspace, + (storeName != null) ? storeName : FilenameUtils.getBaseName(arcgrid + .getAbsolutePath()), UploadMethod.FILE, CoverageStoreExtension.ARCGRID, + "image/arcgrid", arcgrid.toURI(), ParameterConfigure.NONE, (NameValuePair[]) null)) { + LOGGER.error("Unable to create coverage store for coverage: " + arcgrid); + return false; + } + + // config coverage props (srs) + final GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.setName(coverageName); + coverageEncoder.setTitle(coverageName); + coverageEncoder.setSRS(srs); + coverageEncoder.setNativeFormat("ArcGrid"); + coverageEncoder.addSupportedFormats("ARCGRID"); + coverageEncoder.addKeyword("arcGrid"); + coverageEncoder.addKeyword("WCS"); + coverageEncoder.setNativeCRS(srs); + coverageEncoder.setProjectionPolicy(policy); + coverageEncoder.setRequestSRS(srs); + coverageEncoder.setResponseSRS(srs); + if (bbox != null && bbox.length == 4) { + coverageEncoder.setLatLonBoundingBox(bbox[0], bbox[1], bbox[2], bbox[3], DEFAULT_CRS); + } + + if (!createCoverage(workspace, storeName, coverageEncoder)) { + LOGGER.error("Unable to create a coverage store for coverage: " + arcgrid); + return false; + } + + // config layer props (style, ...) + final GSLayerEncoder layerEncoder = configureDefaultStyle(defaultStyle); + + return configureLayer(workspace, coverageName, layerEncoder); + } + + /** + * Publish a ArcGrid already in a filesystem readable by GeoServer. + * + * @param workspace an existing workspace + * @param storeName the coverageStore to be created + * @param arcgrid the arcGrid to be published + * @param srs the native CRS + * @param policy projection policy. See {@link ProjectionPolicy}. + * @param defaultStyle the default style to apply. + * + * @return true if the operation completed successfully. + * @throws FileNotFoundException if file does not exists + * @throws IllegalArgumentException if any of the mandatory parameters are null. + */ + public boolean publishExternalArcGrid(String workspace, String storeName, File arcgrid, + String coverageName, String srs, ProjectionPolicy policy, String defaultStyle) + throws FileNotFoundException, IllegalArgumentException { + if (workspace == null || storeName == null || arcgrid == null || coverageName == null + || srs == null || policy == null || defaultStyle == null) + throw new IllegalArgumentException("Unable to run: null parameter"); + + // config coverage props (srs) + final GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.setName(coverageName); + coverageEncoder.setTitle(coverageName); + coverageEncoder.setSRS(srs); + coverageEncoder.setProjectionPolicy(policy); + + // config layer props (style, ...) + final GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.setDefaultStyle(defaultStyle); + + return publishExternalArcGrid(workspace, storeName, arcgrid, coverageEncoder, layerEncoder) != null ? true + : false; + } + + /** + * Publish a ArcGrid already in a filesystem readable by GeoServer. + * + * @param workspace an existing workspace + * @param storeName the coverageStore to be created + * @param arcgrid the arcGrid to be published + * @param coverageEncoder coverage details. See {@link GSCoverageEncoder}. + * @param layerEncoder layer details, See {@link GSLayerEncoder}. + * + * @return true if the operation completed successfully. + * @throws FileNotFoundException if file does not exists + * @throws IllegalArgumentException if any of the mandatory parameters are null. + */ + public RESTCoverageStore publishExternalArcGrid(final String workspace, final String storeName, + final File arcgrid, final GSCoverageEncoder coverageEncoder, + final GSLayerEncoder layerEncoder) throws IllegalArgumentException, + FileNotFoundException { + + if (workspace == null || arcgrid == null || storeName == null || layerEncoder == null + || coverageEncoder == null) + throw new IllegalArgumentException("Unable to run: null parameter"); + + final String coverageName = coverageEncoder.getName(); + if (coverageName.isEmpty()) { + throw new IllegalArgumentException("Unable to run: empty coverage store name"); + } + + // create store + final boolean store = publishExternalCoverage(workspace, storeName, + CoverageStoreExtension.ARCGRID, "text/plain", arcgrid, ParameterConfigure.NONE, + ParameterUpdate.OVERWRITE); + if (!store) { + return null; + } + + // create Coverage Store + if (!createCoverage(workspace, storeName, coverageEncoder)) { + if (LOGGER.isErrorEnabled()) + LOGGER.error("Unable to create a coverage for the store:" + coverageName); + return null; + } + + // create Layer + if (configureLayer(workspace, coverageName, layerEncoder)) { + GeoServerRESTReader reader; + try { + reader = new GeoServerRESTReader(this.restURL, this.gsuser, this.gspass); + return reader.getCoverageStore(workspace, storeName); + } catch (MalformedURLException e) { + LOGGER.error(e.getMessage(), e); + } + } + return null; + } + // ========================================================================== // === GEOTIFF // ========================================================================== diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTArcGridTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTArcGridTest.java new file mode 100644 index 0000000..b068b4a --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTArcGridTest.java @@ -0,0 +1,180 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2016 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.publisher; + +import it.geosolutions.geoserver.rest.GeoServerRESTPublisher.StoreType; +import it.geosolutions.geoserver.rest.GeoserverRESTTest; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.decoder.RESTLayer; +import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import static org.junit.Assert.*; + +/** + * Testcase for publishing layers on geoserver. + * We need a running GeoServer to properly run the tests. + * If such geoserver instance cannot be contacted, tests will be skipped. + * + * @author Lennart Karsten - lennart.k@thinking-aloud.eu + * inspired by: Carlo Cancellieri - carlo.cancellieri@geo-solutions.it + */ +public class GeoserverRESTArcGridTest extends GeoserverRESTTest { + + private final static Logger LOGGER = LoggerFactory.getLogger(GeoserverRESTArcGridTest.class); + + private String storeName = "testRESTStoreArcGrid"; + private String layerName = "resttestdem"; + + @Test + public void testExternalArcGrid() throws FileNotFoundException, IOException { + if (!enabled()) return; + deleteAll(); + + File arcgrid = new ClassPathResource("testdata/resttestdem.asc").getFile(); + + assertTrue(reader.getWorkspaces().isEmpty()); + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + + // known state? + assertFalse("Cleanup failed", existsLayer(layerName)); + + // Test exists + assertFalse(reader.existsLayer(DEFAULT_WS, layerName)); + + // test insert + boolean pc = publisher.publishExternalArcGrid(DEFAULT_WS, storeName, arcgrid, layerName,"EPSG:4326",ProjectionPolicy.FORCE_DECLARED,"raster"); + assertTrue("publish() failed", pc); + assertTrue(existsLayer(layerName)); + assertFalse(reader.existsLayer(DEFAULT_WS, layerName)); + LOGGER.info("Published "+pc); + RESTCoverageStore reloadedCS = reader.getCoverageStore(DEFAULT_WS, storeName); + + assertEquals(storeName, reloadedCS.getName()); + assertEquals(DEFAULT_WS, reloadedCS.getWorkspaceName()); + + //test delete + assertTrue("Unpublish() failed", publisher.unpublishCoverage(DEFAULT_WS, storeName, layerName)); + assertTrue("Unpublish() failed", publisher.removeCoverageStore(DEFAULT_WS, storeName)); + assertFalse("Bad unpublish()", publisher.unpublishCoverage(DEFAULT_WS, storeName, layerName)); + assertFalse(existsLayer(layerName)); + } + + @Test + public void testArcGrid() throws FileNotFoundException, IOException { + if (!enabled()) return; + deleteAll(); + + File arcgrid = new ClassPathResource("testdata/resttestdem.asc").getFile(); + + assertTrue(reader.getWorkspaces().isEmpty()); + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + // known state? + assertFalse("Cleanup failed", existsLayer(layerName)); + + // test insert + boolean pub = publisher.publishArcGrid(DEFAULT_WS, storeName, arcgrid); + + assertNotNull("publish() failed", pub); + // Test exists + assertTrue(reader.existsCoveragestore(DEFAULT_WS, storeName)); + assertTrue(reader.existsCoverage(DEFAULT_WS, storeName, storeName)); + + pub = publisher.publishArcGrid(DEFAULT_WS, storeName+"another", "layername", arcgrid); + + assertTrue("publish() failed", pub); + + double[] bbox = {-103.85, 44.38, -103.62, 44.50}; + pub = publisher.publishArcGrid(DEFAULT_WS, storeName+"another_complex", storeName+"another_complex", arcgrid, "EPSG:4326", ProjectionPolicy.REPROJECT_TO_DECLARED, "raster", bbox); + + assertTrue("publish() failed", pub); + + //delete + assertTrue("Unpublish() failed", publisher.removeCoverageStore(DEFAULT_WS, storeName,true)); + // Test not exists + assertFalse(reader.existsCoveragestore(DEFAULT_WS, storeName)); + } + + @Test + public void testArcGridWithStyleInWorkspace() throws IOException { + if (!enabled()) return; + deleteAll(); + + File arcgrid = new ClassPathResource("testdata/resttestdem.asc").getFile(); + + assertTrue(reader.getWorkspaces().isEmpty()); + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + File sldFile = new ClassPathResource("testdata/raster.sld").getFile(); + + + // insert style + assertTrue(publisher.publishStyleInWorkspace(DEFAULT_WS, sldFile, "mystyle")); + assertTrue(reader.existsStyle(DEFAULT_WS, "mystyle")); + + // known state? + assertFalse("Cleanup failed", existsLayer(layerName)); + + // test insert + boolean pub = publisher.publishArcGrid(DEFAULT_WS, storeName, storeName, + arcgrid, "EPSG:4326", ProjectionPolicy.FORCE_DECLARED, DEFAULT_WS + ":" + "mystyle", null); + + assertNotNull("publish() failed", pub); + // Test exists + assertTrue(reader.existsCoveragestore(DEFAULT_WS, storeName)); + assertTrue(reader.existsCoverage(DEFAULT_WS, storeName, storeName)); + RESTLayer layer = reader.getLayer(DEFAULT_WS, storeName); + assertEquals("mystyle", layer.getDefaultStyle()); + assertEquals(DEFAULT_WS, layer.getDefaultStyleWorkspace()); + } + + @Test + public void testReloadCoverageStore() throws FileNotFoundException, IOException { + if (!enabled()) return; + deleteAll(); + + File arcgrid = new ClassPathResource("testdata/resttestdem.asc").getFile(); + + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + // test insert + boolean pub = publisher.publishArcGrid(DEFAULT_WS, storeName, arcgrid); + + assertNotNull("publish() failed", pub); + + // test reload + assertTrue(publisher.reloadStore(DEFAULT_WS, storeName, StoreType.COVERAGESTORES)); + } +} diff --git a/src/test/resources/testdata/resttestdem.asc b/src/test/resources/testdata/resttestdem.asc new file mode 100644 index 0000000..939f54a --- /dev/null +++ b/src/test/resources/testdata/resttestdem.asc @@ -0,0 +1,12 @@ +ncols 4 +nrows 6 +xllcorner 0.0 +yllcorner 0.0 +cellsize 50.0 +NODATA_value -9999 +-9999 -9999 5 2 +-9999 20 100 36 +3 8 35 10 +32 42 50 6 +88 75 27 9 +13 5 1 -9999