diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java index d827dd2..2a709b7 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -30,11 +30,12 @@ import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; import it.geosolutions.geoserver.rest.encoder.GSBackupEncoder; import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; import it.geosolutions.geoserver.rest.encoder.GSNamespaceEncoder; -import it.geosolutions.geoserver.rest.encoder.GSPostGISDatastoreEncoder; import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder; import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy; import it.geosolutions.geoserver.rest.encoder.GSWorkspaceEncoder; import it.geosolutions.geoserver.rest.encoder.coverage.GSCoverageEncoder; +import it.geosolutions.geoserver.rest.encoder.datastore.GSAbstractDatastoreEncoder; +import it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder; import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder; import java.io.File; @@ -655,20 +656,20 @@ public class GeoServerRESTPublisher { } /** - * The file, url, and external endpoints are used to specify the method that - * is used to upload the file. - * - * The file method is used to directly upload a file from a local source. + * The {@code file}, {@code url}, and {@code external} endpoints are used to specify + * the method that is used to upload the file. + * * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it * */ @@ -677,7 +678,7 @@ public class GeoServerRESTPublisher { } // ========================================================================== - // === DATASTORE + // === DATASTORES // ========================================================================== /** @@ -702,11 +703,52 @@ public class GeoServerRESTPublisher { String result = HTTPUtils.postXml(sUrl, xml, gsuser, gspass); return result != null; } + + /** + * Create a datastore (any datastore extending GSAbstractDatastoreEncoder). + * + * @param workspace + * Name of the workspace to contain the datastore. This will also + * be the prefix of any layer names contained in the datastore. + * @param datastore + * the set of parameters to be set to the datastore (including + * connection parameters). + * @return true if the datastore has been successfully + * created, false otherwise + */ + public boolean createDatastore(String workspace, + GSAbstractDatastoreEncoder datastore) { + String sUrl = restURL + "/rest/workspaces/" + workspace + + "/datastores/"; + String xml = datastore.toString(); + String result = HTTPUtils.postXml(sUrl, xml, gsuser, gspass); + return result != null; + } + + /** + * Update a datastore (any datastore extending GSAbstractDatastoreEncoder). + * + * @param workspace + * Name of the workspace that contains the datastore. + * @param datastore + * the set of parameters to be set to the datastore (including + * connection parameters). + * @return true if the datastore has been successfully + * updated, false otherwise + */ + public boolean updateDatastore(String workspace, + GSAbstractDatastoreEncoder datastore) { + String sUrl = restURL + "/rest/workspaces/" + workspace + + "/datastores/" + datastore.getName(); + String xml = datastore.toString(); + String result = HTTPUtils.putXml(sUrl, xml, gsuser, gspass); + return result != null; + } // ========================================================================== // === SHAPEFILES // ========================================================================== - + /** * Publish a zipped shapefile.
* The defaultCRS will be set to EPSG:4326. @@ -896,6 +938,57 @@ public class GeoServerRESTPublisher { return publishShp(workspace, storename, params, layername, UploadMethod.file, zipFile.toURI(), srs, ProjectionPolicy.NONE,null); } + + + /** + * Publish a collection of shapefiles. + * + * It will automatically create the store and publish each shapefile as a layer. + * + * @param workspace the name of the workspace to use + * @param storeName the name of the store to create + * @param resource the shapefile collection. It can be: + * @return {@code true} if publication successful. + * @throws FileNotFoundException if the specified zip file does not exist. + */ + public boolean publishShpCollection(String workspace, String storeName, URI resource) + throws FileNotFoundException { + + // Deduce upload method & mime type from resource syntax. + UploadMethod method = null; + String mime = null; + if (resource.getScheme().equals("file") || resource.isAbsolute() == false) { + File f = new File(resource); + if (f.exists() && f.isFile() && f.toString().endsWith(".zip")) { + method = UploadMethod.file; + mime = "application/zip"; + } else if (f.isDirectory()) { + method = UploadMethod.external; + mime = "text/plain"; + } + } else { + try { + if(resource.toURL() != null) { + method = UploadMethod.url; + mime = "text/plain"; + } + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Resource is not recognized as a zip file, or a directory, or a valid URL", e); + } + } + + // Create store, upload data, and publish layers + return createStore( + workspace, DataStoreType.datastores, + storeName, method, + DataStoreExtension.shp, // TODO if GEOS-5113 is accepted, change to DataStoreExtension.shpdir + mime, resource, + ParameterConfigure.ALL, + new NameValuePair[0]); + } /** * @param workspace @@ -1159,7 +1252,7 @@ public class GeoServerRESTPublisher { * */ public enum DataStoreExtension { - shp, properties, h2, spatialite + shp, /*shpdir,*/ properties, h2, spatialite // TODO uncomment if GEOS-5113 is accepted } /** diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java index 22c24f0..52904d7 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java @@ -26,7 +26,11 @@ package it.geosolutions.geoserver.rest.decoder; import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; + +import java.util.HashMap; import java.util.List; +import java.util.Map; + import org.jdom.Element; /** @@ -108,15 +112,44 @@ public class RESTDataStore { public String getName() { return dsElem.getChildText("name"); } + + public String getStoreType() { + return dsElem.getChildText("type"); + } + + public String getDescription() { + return dsElem.getChildText("description"); + } + public boolean isEnabled() { + return Boolean.parseBoolean(dsElem.getChildText("enabled")); + } + public String getWorkspaceName() { return dsElem.getChild("workspace").getChildText("name"); } - - protected String getConnectionParameter(String paramName) { + + public Map getConnectionParameters() { Element elConnparm = dsElem.getChild("connectionParameters"); if (elConnparm != null) { - for (Element entry : (List) elConnparm.getChildren("entry")) { + @SuppressWarnings("unchecked") + List elements = (List)elConnparm.getChildren("entry"); + Map params = new HashMap(elements.size()); + for (Element element : elements) { + String key = element.getAttributeValue("key"); + String value = element.getTextTrim(); + params.put(key, value); + } + return params; + } + return null; + } + + @SuppressWarnings("unchecked") + protected String getConnectionParameter(String paramName) { + Element elConnparm = dsElem.getChild("connectionParameters"); + if (elConnparm != null) { + for (Element entry : (List) elConnparm.getChildren("entry")) { String key = entry.getAttributeValue("key"); if (paramName.equals(key)) { return entry.getTextTrim(); @@ -126,7 +159,7 @@ public class RESTDataStore { return null; } - + public DBType getType() { return DBType.get(getConnectionParameter("dbtype")); } diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSAbstractDatastoreEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSAbstractDatastoreEncoder.java new file mode 100644 index 0000000..f957810 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSAbstractDatastoreEncoder.java @@ -0,0 +1,146 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2012 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.encoder.datastore; + +import java.util.Map; + +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.encoder.utils.ElementUtils; +import it.geosolutions.geoserver.rest.encoder.utils.NestedElementEncoder; +import it.geosolutions.geoserver.rest.encoder.utils.PropertyXMLEncoder; + +/** + * Generic Datastore encoder. + * + * Provides getters and setters for parameters common to all Datastores, + * an internal placeholder for specific connection parameters, and + * a constructor to read parameters from a {@link RESTDataStore}. + * + * @author Oscar Fonts + */ +public abstract class GSAbstractDatastoreEncoder extends PropertyXMLEncoder { + + final static String ROOT = "dataStore"; + + NestedElementEncoder connectionParameters = new NestedElementEncoder("connectionParameters"); + + GSAbstractDatastoreEncoder(String storeName) { + super(ROOT); + // Add mandatory parameter + ensureValidName(storeName); + setName(storeName); + + // Add connection parameters + addContent(connectionParameters.getRoot()); + } + + /** + * Create a {@value #TYPE} datastore encoder from a store read from server. + * + * @param store The existing store. + * @throws IllegalArgumentException if store type or mandatory parameters are not valid + */ + GSAbstractDatastoreEncoder(RESTDataStore store) { + this(store.getName()); + + // Match datastore type + ensureValidType(store.getStoreType()); + setType(store.getStoreType()); + + // Copy store parameters + setDescription(store.getDescription()); + setEnabled(store.isEnabled()); + + // Copy connection parameters - bulk + Map params = store.getConnectionParameters(); + for(String key : params.keySet()) { + connectionParameters.set(key, params.get(key)); + } + } + + void setType(String type) { + set("type", type); + } + + public String getType() { + return ElementUtils.contains(getRoot(), "type").getTextTrim(); + } + + public void setName(String name) { + ensureValidName(name); + set("name", name); + } + + public String getName() { + return ElementUtils.contains(getRoot(), "name").getTextTrim(); + } + + public void setDescription(String description) { + set("description", description); + } + + public String getDescription() { + return ElementUtils.contains(getRoot(), "description").getTextTrim(); + } + + public void setEnabled(boolean enabled) { + set("enabled", Boolean.toString(enabled)); + } + + public boolean getEnabled() { + return Boolean.parseBoolean(ElementUtils.contains(getRoot(), "enabled").getTextTrim()); + } + + /** + * Check name validity. + * + * @param name the name + * @throws IllegalArgumentException if name is null or empty + */ + void ensureValidName(String name) { + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + "Store name cannot be null or empty"); + } + } + + /** + * Check type validity. + * + * @param type the type. + * @throws IllegalArgumentException if type is not {@value #TYPE} + */ + void ensureValidType(String type) { + if (!type.equals(getValidType())) { + throw new IllegalArgumentException( + "The store type '"+ type +"' is not valid"); + } + } + + /** + * The type of the implementing datastore. + */ + abstract String getValidType(); +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSDirectoryOfShapefilesDatastoreEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSDirectoryOfShapefilesDatastoreEncoder.java new file mode 100644 index 0000000..eae422e --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSDirectoryOfShapefilesDatastoreEncoder.java @@ -0,0 +1,68 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2012 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.encoder.datastore; + +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; + +import java.net.URL; + +/** + * Encoder for a {@value #TYPE} datastore. + * + * @author Oscar Fonts + */ +public class GSDirectoryOfShapefilesDatastoreEncoder extends GSShapefileDatastoreEncoder { + + static final String TYPE = "Directory of spatial files (shapefiles)"; + + /** + * Create a {@value #TYPE} datastore with default connection parameters, + * given a store name and a url (the store location). + * + * @param name New datastore name + * @param url The shapefile location in the server, relative to $GEOSERVER_DATA_DIR. + */ + public GSDirectoryOfShapefilesDatastoreEncoder(String name, URL url) { + super(name, url); + setType(TYPE); + } + + /** + * Create a {@value #TYPE} datastore encoder from an existing store read from server. + * + * @param store The existing store. + * @throws IllegalArgumentException if store type or mandatory parameters are not valid + */ + public GSDirectoryOfShapefilesDatastoreEncoder(RESTDataStore store) { + super(store); + } + + /** + * @return {@value #TYPE} + */ + String getValidType() { + return TYPE; + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSPostGISDatastoreEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSPostGISDatastoreEncoder.java similarity index 99% rename from src/main/java/it/geosolutions/geoserver/rest/encoder/GSPostGISDatastoreEncoder.java rename to src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSPostGISDatastoreEncoder.java index 1db6613..0323fb3 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSPostGISDatastoreEncoder.java +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSPostGISDatastoreEncoder.java @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -package it.geosolutions.geoserver.rest.encoder; +package it.geosolutions.geoserver.rest.encoder.datastore; import it.geosolutions.geoserver.rest.encoder.utils.NestedElementEncoder; import it.geosolutions.geoserver.rest.encoder.utils.PropertyXMLEncoder; diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSShapefileDatastoreEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSShapefileDatastoreEncoder.java new file mode 100644 index 0000000..3a9d949 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/datastore/GSShapefileDatastoreEncoder.java @@ -0,0 +1,163 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2012 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.encoder.datastore; + +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; + +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.encoder.utils.ElementUtils; + +/** + * Encoder for a {@value #TYPE} datastore. + * + * @author Oscar Fonts + */ +public class GSShapefileDatastoreEncoder extends GSAbstractDatastoreEncoder { + + static final String TYPE = "Shapefile"; + + final static boolean DEFAULT_ENABLED = true; + final static String DEFAULT_CHARSET = "ISO-8859-1"; + final static boolean DEFAULT_CREATE_SPATIAL_INDEX = true; + final static boolean DEFAULT_MEMORY_MAPPED_BUFFER = false; + final static boolean DEFAULT_CACHE_AND_REUSE_MEMORY_MAPS = true; + + /** + * Create a {@value #TYPE} datastore with default connection parameters, + * given a store name and a url (the store location). + * + * The following default connection parameters are set: + *
    + *
  • enabled: {@value #DEFAULT_ENABLED} + *
  • charset: {@value #DEFAULT_CHARSET} + *
  • create spatial index: {@value #DEFAULT_CREATE_SPATIAL_INDEX} + *
  • memory mapped buffer: {@value #DEFAULT_MEMORY_MAPPED_BUFFER} + *
  • cache and reuse memory maps: {@value #DEFAULT_CACHE_AND_REUSE_MEMORY_MAPS} + *
+ * + * @param name New datastore name + * @param url The shapefile location in the server, relative to $GEOSERVER_DATA_DIR. + */ + public GSShapefileDatastoreEncoder(String name, URL url) { + // Set fixed values + super(name); + setType(TYPE); + + // Set mandatory parameter + ensureValidURL(url); + setUrl(url); + + // Set default values + setEnabled(DEFAULT_ENABLED); + setCharset(Charset.forName(DEFAULT_CHARSET)); + setCreateSpatialIndex(DEFAULT_CREATE_SPATIAL_INDEX); + setMemoryMappedBuffer(DEFAULT_MEMORY_MAPPED_BUFFER); + setCacheAndReuseMemoryMaps(DEFAULT_CACHE_AND_REUSE_MEMORY_MAPS); + } + + /** + * Create a {@value #TYPE} datastore encoder from an existing store read from server. + * + * @param store The existing store. + * @throws IllegalArgumentException if store type or mandatory parameters are not valid + */ + public GSShapefileDatastoreEncoder(RESTDataStore store) { + super(store); + + // Check mandatory parameter validity + try { + ensureValidURL(new URL(store.getConnectionParameters().get("url"))); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Shapefile store URL is malformed", e); + } + } + + public void setUrl(URL url) { + ensureValidURL(url); + connectionParameters.set("url", url.toString()); + } + + public URL getUrl() { + try { + return new URL(ElementUtils.contains(connectionParameters.getRoot(), "description").getTextTrim()); + } catch (MalformedURLException e) { + return null; + } + } + + public void setCharset(Charset charset) { + connectionParameters.set("charset", charset.name()); + } + + public Charset getCharset() { + return Charset.forName(ElementUtils.contains(connectionParameters.getRoot(), "charset").getTextTrim()); + } + + public void setCreateSpatialIndex(boolean createSpatialIndex) { + connectionParameters.set("create spatial index", Boolean.toString(createSpatialIndex)); + } + + public boolean getCreateSpatialIndex() { + return Boolean.parseBoolean(ElementUtils.contains(connectionParameters.getRoot(), "create spatial index").getTextTrim()); + } + + public void setMemoryMappedBuffer(boolean memoryMappedBuffer) { + connectionParameters.set("memory mapped buffer", Boolean.toString(memoryMappedBuffer)); + } + + public boolean getMemoryMappedBuffer() { + return Boolean.parseBoolean(ElementUtils.contains(connectionParameters.getRoot(), "memory mapped buffer").getTextTrim()); + } + + public void setCacheAndReuseMemoryMaps(boolean cacheAndReuseMemoryMaps) { + connectionParameters.set("cache and reuse memory maps", Boolean.toString(cacheAndReuseMemoryMaps)); + } + + public boolean getCacheAndReuseMemoryMaps() { + return Boolean.parseBoolean(ElementUtils.contains(connectionParameters.getRoot(), "cache and reuse memory maps").getTextTrim()); + } + + /** + * Check url validity. + * + * @param url the url + * @throws IllegalArgumentException if url is null or empty + */ + private static void ensureValidURL(URL url) { + if (url == null || url.toString().isEmpty()) { + throw new IllegalArgumentException( + "Shapefile store URL cannot be null or empty"); + } + } + + /** + * @return {@value #TYPE} + */ + String getValidType() { + return TYPE; + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/utils/NestedElementEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/utils/NestedElementEncoder.java index aaf97d8..a72dee4 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/encoder/utils/NestedElementEncoder.java +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/utils/NestedElementEncoder.java @@ -155,7 +155,7 @@ public class NestedElementEncoder extends XmlElement { // if some previous similar object is found final Element search; if ((search = ElementUtils.contains(getRoot(), new NestedElementFilter( - getRoot(), key, value))) != null) { + getRoot(), key, null))) != null) { // remove it ElementUtils.remove(getRoot(), search); } diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTCreateReadUpdateDatastoreTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTCreateReadUpdateDatastoreTest.java new file mode 100644 index 0000000..d56a885 --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTCreateReadUpdateDatastoreTest.java @@ -0,0 +1,131 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2012 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 org.junit.Test; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Map; + +import it.geosolutions.geoserver.rest.GeoServerRESTPublisher; +import it.geosolutions.geoserver.rest.GeoserverRESTTest; +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.encoder.datastore.GSAbstractDatastoreEncoder; +import it.geosolutions.geoserver.rest.encoder.datastore.GSShapefileDatastoreEncoder; +import it.geosolutions.geoserver.rest.encoder.datastore.GSDirectoryOfShapefilesDatastoreEncoder; + +/** + * Test datastore handling (create, read and update): + * + *
  • Tests all the constructors and setters from + * {@link GSDirectoryOfShapefilesDatastoreEncoder} and parent classes + * ({@link GSShapefileDatastoreEncoder}, {@link GSAbstractDatastoreEncoder}). + * + *
  • Tests constructors and getters from {@link RESTDataStore} (reader). + * + *
  • Tests {@link GeoServerRESTPublisher#createDatastore} and + * {@link GeoServerRESTPublisher#updateDatastore} methods.
+ * + *

The sequence is: + *

    + *
  1. Create a DirectoryOfShapefilesDatastoreEncoder, with default parameters. + *
  2. Publish via createDatastore. + *
  3. Read the datastore from server. + *
  4. Test all parameter values. + *
  5. Create a new Encoder from it. + *
  6. Change all datastore parameter to non-default ones. + *
  7. Update via updateDatastore. + *
  8. Read again. + *
  9. Test all new values. + *
+ * + * @author Oscar Fonts + */ +public class GeoserverRESTCreateReadUpdateDatastoreTest extends GeoserverRESTTest { + + private static final String WS_NAME = DEFAULT_WS; + private static final String DS_NAME = "testCreateDatastore"; + private static final String DS_DESCRIPTION = "A description"; + private static URL LOCATION_1; + private static URL LOCATION_2; + + public GeoserverRESTCreateReadUpdateDatastoreTest(String testName) throws Exception { + super(testName); + LOCATION_1 = new URL("file:data/1"); + LOCATION_2 = new URL("file:data/2"); + } + + @Test + public void test() throws Exception { + assertTrue(enabled()); + + // Delete all resources except styles + deleteAllWorkspacesRecursively(); + + // Create workspace + assertTrue(publisher.createWorkspace(WS_NAME)); + + // Create a directory of spatial files with default parameters + GSDirectoryOfShapefilesDatastoreEncoder create = new GSDirectoryOfShapefilesDatastoreEncoder(DS_NAME, LOCATION_1); + assertTrue(publisher.createDatastore(WS_NAME, create)); + + // Read the store from server; check all parameter values + RESTDataStore read = reader.getDatastore(WS_NAME, DS_NAME); + assertEquals(read.getName(), DS_NAME); + assertEquals(read.getWorkspaceName(), WS_NAME); + assertEquals(read.isEnabled(), true); + + Map connParams = read.getConnectionParameters(); + assertEquals(connParams.get("url"), LOCATION_1.toString()); + assertEquals(connParams.get("charset"), "ISO-8859-1"); + assertEquals(connParams.get("create spatial index"), "true"); + assertEquals(connParams.get("memory mapped buffer"), "false"); + assertEquals(connParams.get("cache and reuse memory maps"), "true"); + + // Change all parameter to non-default values + GSDirectoryOfShapefilesDatastoreEncoder update = new GSDirectoryOfShapefilesDatastoreEncoder(read); + update.setDescription(DS_DESCRIPTION); + update.setEnabled(false); + update.setUrl(LOCATION_2); + update.setCharset(Charset.forName("UTF-8")); + update.setCreateSpatialIndex(false); + update.setMemoryMappedBuffer(true); + update.setCacheAndReuseMemoryMaps(false); + + //update the store + assertTrue(publisher.updateDatastore(WS_NAME, update)); + + // Read again, check that all parameters have changed + read = reader.getDatastore(WS_NAME, DS_NAME); + assertEquals(read.getWorkspaceName(), WS_NAME); + assertEquals(read.isEnabled(), false); + connParams = read.getConnectionParameters(); + assertEquals(connParams.get("url"), LOCATION_2.toString()); + assertEquals(connParams.get("charset"), "UTF-8"); + assertEquals(connParams.get("create spatial index"), "false"); + assertEquals(connParams.get("memory mapped buffer"), "true"); + assertEquals(connParams.get("cache and reuse memory maps"), "false"); + } +} diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPostgisDatastoreTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPostgisDatastoreTest.java index 2d76af5..2bceb7b 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPostgisDatastoreTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPostgisDatastoreTest.java @@ -28,7 +28,7 @@ package it.geosolutions.geoserver.rest.publisher; import it.geosolutions.geoserver.rest.GeoserverRESTTest; import it.geosolutions.geoserver.rest.decoder.RESTDataStore; -import it.geosolutions.geoserver.rest.encoder.GSPostGISDatastoreEncoder; +import it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPublishShpCollectionTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPublishShpCollectionTest.java new file mode 100644 index 0000000..c5bd0a2 --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTPublishShpCollectionTest.java @@ -0,0 +1,84 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2012 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 org.junit.Test; +import java.net.URI; +import java.util.List; +import org.springframework.core.io.ClassPathResource; + +import it.geosolutions.geoserver.rest.GeoserverRESTTest; + +/** + * @author Oscar Fonts + */ +public class GeoserverRESTPublishShpCollectionTest extends GeoserverRESTTest { + + final String workspace = DEFAULT_WS; + final String storeName = "testshpcollection"; + + public GeoserverRESTPublishShpCollectionTest(String testName) { + super(testName); + } + + @Test + public void testLocalZip() throws Exception { + assertTrue(enabled()); + + URI location = new ClassPathResource("testdata/multipleshp.zip").getFile().toURI(); + test(location); + } + + @Test + public void testExternalDir() throws Exception { + assertTrue(enabled()); + + URI location = new ClassPathResource("testdata/multipleshapefiles").getFile().toURI(); + test(location); + } + + void test(URI location) throws Exception { + + // Delete all resources except styles + deleteAllWorkspacesRecursively(); + + // Create workspace + assertTrue(publisher.createWorkspace(workspace)); + + // Publish shp collection + assertTrue(publisher.publishShpCollection(workspace, storeName, location)); + + // Test store type */ + /* TODO uncomment if GEOS-5113 is accepted + String storeType = reader.getDatastore(workspace, storeName).getStoreType(); + assertEquals(storeType, "Directory of spatial files (shapefiles)"); + */ + + // Test published layer names + List layers = reader.getLayers().getNames(); + assertTrue(layers.contains("cities")); + assertTrue(layers.contains("boundaries")); + } +} diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTShapeTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTShapeTest.java index 8859d92..3f3ebfa 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTShapeTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTShapeTest.java @@ -166,11 +166,12 @@ public class GeoserverRESTShapeTest extends GeoserverRESTTest { String ns = "geosolutions"; String storeName = "resttestshp"; String layerName = "cities"; + final String styleName = "restteststyle"; File zipFile = new ClassPathResource("testdata/resttestshp.zip").getFile(); publisher.removeDatastore(DEFAULT_WS, storeName,true); + publisher.removeStyle(styleName); - final String styleName = "restteststyle"; File sldFile = new ClassPathResource("testdata/restteststyle.sld").getFile(); // insert style diff --git a/src/test/resources/testdata/multipleshapefiles/boundaries.dbf b/src/test/resources/testdata/multipleshapefiles/boundaries.dbf new file mode 100644 index 0000000..b245a5e Binary files /dev/null and b/src/test/resources/testdata/multipleshapefiles/boundaries.dbf differ diff --git a/src/test/resources/testdata/multipleshapefiles/boundaries.prj b/src/test/resources/testdata/multipleshapefiles/boundaries.prj new file mode 100644 index 0000000..7a70628 --- /dev/null +++ b/src/test/resources/testdata/multipleshapefiles/boundaries.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] diff --git a/src/test/resources/testdata/multipleshapefiles/boundaries.shp b/src/test/resources/testdata/multipleshapefiles/boundaries.shp new file mode 100644 index 0000000..85957fa Binary files /dev/null and b/src/test/resources/testdata/multipleshapefiles/boundaries.shp differ diff --git a/src/test/resources/testdata/multipleshapefiles/cities.dbf b/src/test/resources/testdata/multipleshapefiles/cities.dbf new file mode 100644 index 0000000..6b53516 Binary files /dev/null and b/src/test/resources/testdata/multipleshapefiles/cities.dbf differ diff --git a/src/test/resources/testdata/multipleshapefiles/cities.prj b/src/test/resources/testdata/multipleshapefiles/cities.prj new file mode 100644 index 0000000..c0c0792 Binary files /dev/null and b/src/test/resources/testdata/multipleshapefiles/cities.prj differ diff --git a/src/test/resources/testdata/multipleshapefiles/cities.shp b/src/test/resources/testdata/multipleshapefiles/cities.shp new file mode 100644 index 0000000..54fd672 Binary files /dev/null and b/src/test/resources/testdata/multipleshapefiles/cities.shp differ diff --git a/src/test/resources/testdata/multipleshp.zip b/src/test/resources/testdata/multipleshp.zip new file mode 100644 index 0000000..6a58512 Binary files /dev/null and b/src/test/resources/testdata/multipleshp.zip differ diff --git a/src/test/resources/testdata/shapefile/cities.shx b/src/test/resources/testdata/shapefile/cities.shx deleted file mode 100644 index 6817e44..0000000 Binary files a/src/test/resources/testdata/shapefile/cities.shx and /dev/null differ