diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java index 374bc8b..adbeedd 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -1,2848 +1,2861 @@ -/* - * GeoServer-Manager - Simple Manager Library for GeoServer - * - * Copyright (C) 2007,2013 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; - -import it.geosolutions.geoserver.rest.decoder.RESTCoverage; -import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; -import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList; -import it.geosolutions.geoserver.rest.decoder.RESTStyleList; -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.GSLayerGroupEncoder; -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.feature.GSFeatureTypeEncoder; -import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredGridCoverageReaderManager; -import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredGridCoverageReaderManager.ConfigureCoveragesOption; -import it.geosolutions.geoserver.rest.manager.GeoServerRESTStyleManager; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLEncoder; -import java.util.zip.ZipFile; - -import org.apache.commons.httpclient.NameValuePair; -import org.apache.commons.io.FilenameUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Connect to a GeoServer instance to publish or modify its contents via REST API. - *
- * There are no modifiable instance fields, so all the calls are thread-safe. - * - * @author ETj (etj at geo-solutions.it) - * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it - */ -public class GeoServerRESTPublisher { - - public static final String DEFAULT_CRS = "EPSG:4326"; - - /** The logger for this class */ - private static final Logger LOGGER = LoggerFactory.getLogger(GeoServerRESTPublisher.class); - - /** - * GeoServer instance base URL. E.g.: http://localhost:8080/geoserver. - */ - private final String restURL; - - /** - * GeoServer instance privileged username, with read & write permission on REST API - */ - private final String gsuser; - - /** - * GeoServer instance password for privileged username with r&w permission on REST API - */ - private final String gspass; - - - private final GeoServerRESTStyleManager styleManager; - /** - * Creates a GeoServerRESTPublisher to connect against a GeoServer instance with the given URL and user credentials. - * - * @param restURL the base GeoServer URL (e.g.: http://localhost:8080/geoserver) - * @param username auth credential - * @param password auth credential - */ - public GeoServerRESTPublisher(String restURL, String username, String password) { - this.restURL = HTTPUtils.decurtSlash(restURL); - this.gsuser = username; - this.gspass = password; - - URL url = null; - try { - url = new URL(restURL); - } catch (MalformedURLException ex) { - LOGGER.error("Bad URL: Calls to GeoServer are going to fail" , ex); - } - styleManager = new GeoServerRESTStyleManager(url, username, password); - } - - // ========================================================================== - // === BACKUP and RESTORE - // ========================================================================== - - /** - * Issues a GeoServer BACKUP. - *
- * Won't include data, cached tiles, or logs. Use {@link #backup(String, boolean, boolean, boolean)} to control these parameters. - * - * @param backupDir the target Backup Dir String. - * - * @return id of the backup. - * @throws IllegalArgumentException if the backupDir is null or empty - */ - public String backup(final String backupDir) throws IllegalArgumentException { - /* - * This is the equivalent call with cUrl: - * - * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data - * "<task><path>${BACKUP_DATADIR}</path></task>" \ ${restURL}/rest/bkprst/backup} - */ - return backup(backupDir, false, false, false); - } - - /** - * Issues a GeoServer BACKUP. - * - * @param backupDir the target Backup Dir String. - * @param includedata whether or not include the data dir Boolean. - * @param includegwc whether or not include the geowebcache dir Boolean. - * @param includelog whether or not include the log dir Boolean. - * - * @return id of the backup. - * @throws IllegalArgumentException if the backupDir is null or empty. - */ - public String backup(final String backupDir, final boolean includedata, - final boolean includegwc, final boolean includelog) throws IllegalArgumentException { - /* - * This is the equivalent call with cUrl: - * - * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data - * "<task><path>${BACKUP_DATADIR}</path><includedata>${includedata}</includedata><includegwc>${includegwc}</includegwc><includelog>${includelog}</includelog></task>" - * \ ${restURL}/rest/bkprst/backup} - */ - if ((backupDir == null) || backupDir.isEmpty()) { - throw new IllegalArgumentException("The backup_dir must not be null or empty"); - } - - StringBuilder bkpUrl = new StringBuilder(restURL); - bkpUrl.append("/rest/bkprst/backup"); - - final GSBackupEncoder bkpenc = new GSBackupEncoder(backupDir); - bkpenc.setIncludeData(includedata); - bkpenc.setIncludeGwc(includegwc); - bkpenc.setIncludeLog(includelog); - final String result = HTTPUtils.post(bkpUrl.toString(), bkpenc.toString(), "text/xml", - gsuser, gspass); - - return result; - } - - /** - * Issues a GeoServer RESTORE. - * - * @param backupDir the source backup dir. - * - * @return id of the backup. - * @throws IllegalArgumentException if the backupDir is null or empty - */ - public String restore(final String backupDir) throws IllegalArgumentException { - /* - * This is the equivalent call with cUrl: - * - * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data - * "<task><path>${BACKUP_DATADIR}</path></task>" \ ${restURL}/rest/bkprst/restore} - */ - if ((backupDir == null) || backupDir.isEmpty()) { - throw new IllegalArgumentException("The backup_dir must not be null or empty"); - } - - StringBuilder bkpUrl = new StringBuilder(restURL); - bkpUrl.append("/rest/bkprst/restore"); - - final GSBackupEncoder bkpenc = new GSBackupEncoder(backupDir); - - final String result = HTTPUtils.post(bkpUrl.toString(), bkpenc.toString(), "text/xml", - gsuser, gspass); - - return result; - } - - // ========================================================================== - // === WORKSPACES - // ========================================================================== - - /** - * Create a new Workspace. - *
- * GeoServer will automatically create an associated Namespace with the URI being "http://{workspaceName}". To specify a custom Namespace URI, use
- * {@link #createWorkspace(String, URI)}.
- *
- * @param workspace The name of the new workspace.
- *
- * @return true if the workspace was created.
- */
- public boolean createWorkspace(final String workspace) {
- /*
- * This is the equivalent call with cUrl:
- *
- * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ -d "
- * Note that this method is equivalent to {@link #createNamespace}. - * - * @param name Name for the new workspace, which will be also its associated namespace prefix. - * @param uri Namespace URI. Cannot be empty. - * @return true if the Workspace and its associated namespace were successfully created. - */ - public boolean createWorkspace(final String name, final URI uri) { - // This is really an alias to createNamespace, as GeoServer - // will automatically create the associated workspace as well. - return createNamespace(name, uri); - } - - // ========================================================================== - // === NAMESPACES - // ========================================================================== - - /** - * Create a new Namespace. GeoServer will automatically create the corresponding Workspace. - * - * Prefix and URI are mandatory and cannot be empty. If a Namespace with the given prefix already exists, it won't be created. - * - * @param prefix The name of the new Namespace. - * @param uri The URI of the new Namespace. - * - * @return true if the Namespace was successfully created. - * @see GeoServer Documentation - */ - public boolean createNamespace(final String prefix, final URI uri) { - final String sUrl = restURL + "/rest/namespaces"; - final GSNamespaceEncoder nsenc = new GSNamespaceEncoder(prefix, uri); - final String nsxml = nsenc.toString(); - final String result = HTTPUtils.postXml(sUrl, nsxml, gsuser, gspass); - return result != null; - } - - /** - * Update a Namespace URI. - * - * Prefix and URI are mandatory and cannot be empty. A Namespace with the given prefix should exist. - * - * @param prefix The prefix of an existing Namespace. - * @param uri The new URI. - * - * @return true if the Namespace was successfully updated. - */ - public boolean updateNamespace(final String prefix, final URI uri) { - final String sUrl = restURL + "/rest/namespaces/" + encode(prefix); - final GSNamespaceEncoder nsenc = new GSNamespaceEncoder(prefix, uri); - final String nsxml = nsenc.toString(); - final String result = HTTPUtils.put(sUrl, nsxml, "application/xml", gsuser, gspass); - return result != null; - } - - /** - * Remove a given Namespace. It will remove the associated Workspace as well. - * - * @param prefix The Namespace prefix - * @param recurse The recurse parameter is used to recursively delete all resources contained in the workspace associated with this Namespace. - * This includes data stores, coverage stores, feature types, etc... Allowable values for this parameter are true or false. - * The default (safer) value is false. - * - * @return true if the Namespace was successfully removed. - */ - public boolean removeNamespace(final String prefix, boolean recurse) { - // Hack: We are instead calling removeWorkspace, as DELETE on - // a namespace will leave associated workspace in an inconsistent - // state. See https://jira.codehaus.org/browse/GEOS-5075 - // TODO switch to namespace when GEOS-5075 is solved - return removeWorkspace(prefix, recurse); - } - - // ========================================================================== - // === STYLES - // ========================================================================== - - /** - * Store and publish a Style. - * - * @param sldBody the full SLD document as a String. - * - * @return true if the operation completed successfully. - */ - public boolean publishStyle(String sldBody) { - return styleManager.publishStyle(sldBody); - } - - /** - * Store and publish a Style, assigning it a name. - * - * @param sldBody the full SLD document as a String. - * @param name the Style name. - * - * @return true if the operation completed successfully. - * @throws IllegalArgumentException if the style body is null or empty. - */ - public boolean publishStyle(final String sldBody, final String name) - throws IllegalArgumentException { - return styleManager.publishStyle(sldBody, name); - } - - /** - * Store and publish a Style. - * - * @param sldFile the File containing the SLD document. - * - * @return true if the operation completed successfully. - */ - public boolean publishStyle(File sldFile) { - return styleManager.publishStyle(sldFile); - } - - /** - * Store and publish a Style, assigning it a name. - * - * @param sldFile the File containing the SLD document. - * @param name the Style name. - * - * @return true if the operation completed successfully. - */ - public boolean publishStyle(File sldFile, String name) { - return styleManager.publishStyle(sldFile, name); - } - - /** - * Update a Style. - * - * @param sldBody the new SLD document as a String. - * @param name the Style name to update. - * - * @return true if the operation completed successfully. - * @throws IllegalArgumentException if the style body or name are null or empty. - */ - public boolean updateStyle(final String sldBody, final String name) - throws IllegalArgumentException { - return styleManager.updateStyle(sldBody, name); - } - - /** - * Update a Style. - * - * @param sldFile the File containing the SLD document. - * @param name the Style name. - * - * @return true if the operation completed successfully. - * @throws IllegalArgumentException if the sldFile file or name are null or name is empty. - */ - public boolean updateStyle(final File sldFile, final String name) - throws IllegalArgumentException { - - return styleManager.updateStyle(sldFile, name); - } - - /** - * Remove a Style. - *
- * The Style will be unpublished, and (optionally) the SLD file will be removed. - * - * @param styleName the name of the Style to remove. - * @param purge remove the related SLD file from disk. - * - * @return true if the operation completed successfully. - * @throws IllegalArgumentException if styleName is null or empty. - */ - public boolean removeStyle(String styleName, final boolean purge) - throws IllegalArgumentException { - - return styleManager.removeStyle(styleName, purge); - } - - /** - * Remove a Style. - *
- * The Style will be unpublished and the related SLD file will be removed. - * - * @param styleName the name of the Style to remove. - * - * @return true if the operation completed successfully. - */ - public boolean removeStyle(String styleName) { - return styleManager.removeStyle(styleName); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager# - */ - public boolean publishStyleInWorkspace(String workspace, String sldBody) { - return styleManager.publishStyleInWorkspace(workspace, sldBody); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager# - */ - public boolean publishStyleInWorkspace(String workspace, String sldBody, String name) throws IllegalArgumentException { - return styleManager.publishStyleInWorkspace(workspace, sldBody, name); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#publishStyleInWorkspace(java.lang.String, java.io.File) - */ - public boolean publishStyleInWorkspace(String workspace, File sldFile) { - return styleManager.publishStyleInWorkspace(workspace, sldFile); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#publishStyleInWorkspace(java.lang.String, java.io.File, java.lang.String) - */ - public boolean publishStyleInWorkspace(String workspace, File sldFile, String name) { - return styleManager.publishStyleInWorkspace(workspace, sldFile, name); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#updateStyleInWorkspace(java.lang.String, java.lang.String, java.lang.String) - */ - public boolean updateStyleInWorkspace(String workspace, String sldBody, String name) throws IllegalArgumentException { - return styleManager.updateStyleInWorkspace(workspace, sldBody, name); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#updateStyleInWorkspace(java.lang.String, java.io.File, java.lang.String) - */ - public boolean updateStyleInWorkspace(String workspace, File sldFile, String name) throws IllegalArgumentException { - return styleManager.updateStyleInWorkspace(workspace, sldFile, name); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#removeStyleInWorkspace(java.lang.String, java.lang.String, boolean) - */ - public boolean removeStyleInWorkspace(String workspace, String styleName, boolean purge) throws IllegalArgumentException { - return styleManager.removeStyleInWorkspace(workspace, styleName, purge); - } - - /** - * @since GeoServer 2.2 - * @see GeoServerRESTStyleManager#removeStyleInWorkspace(java.lang.String, java.lang.String) - */ - public boolean removeStyleInWorkspace(String workspace, String styleName) { - return styleManager.removeStyleInWorkspace(workspace, styleName); - } - - - // ========================================================================== - // === DATASTORE PUBLISHING - // ========================================================================== - - /** - * - * @author cancellieri - * @deprecated use {@link StoreType} - */ - public enum DataStoreType { - /** - * Raster based data sources. - */ - COVERAGESTORES, - /** - * Vector based data sources. Can be a file in the case of a Shapefile, a database connection in the case of PostGIS, or a server in the case - * of a remote Web Feature Service. - */ - DATASTORES; - - /** - * @deprecated use {@link StoreType#getTypeNameWithFormat(StoreType, Format)} - * @param type - * @return - */ - public static String getTypeName(StoreType type) { - return StoreType.getTypeNameWithFormat(type, Format.XML); - } - - /** - * @deprecated use {@link StoreType#toString()} - */ - @Override - public String toString() { - return this.name().toLowerCase(); - } - } - - /** - * DataStoreType definitions. - *
- * The SRS will be set to EPSG:4326.
- *
- * @see {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, ProjectionPolicy, String)}
- *
- * @param workspace The workspace name.
- * @param storename The store name.
- * @param layername The layer name.
- * @param zipFile The zipped file to publish.
- *
- * @return {@code true} if the operation completed successfully.
- * @throws FileNotFoundException , IllegalArgumentException
- */
- public boolean publishShp(String workspace, String storename, String datasetname, File zipFile)
- throws FileNotFoundException, IllegalArgumentException {
- return publishShp(workspace, storename, new NameValuePair[0], datasetname,
- UploadMethod.FILE, zipFile.toURI(), DEFAULT_CRS, null);
- }
-
- /**
- * Publish a shapefile.
- *
- * @param workspace the name of the workspace to use
- * @param storename the name of the store to create
- * @param storeParams parameters to append to the url (can be null).
- * Accepted parameters are:
- *
- * 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: - *
- * In a POST or PUT operation the format specifies 1) the representatin of the content being sent to the server, and 2) the representation of the - * response to be sent back. The former is specified with the Content-type header. To send a representation in XML, the content type "text/xml" or - * "application/xml" would be used. The latter is specified with the Accepts header as specified in the above paragraph describing a GET - * operation. - *
- * The following table defines the Content-type values for each format: - *
- * First, the associated layer is removed, then the Coverage configuration itself. - *
- * CHECKME Maybe the coveragestore has to be removed as well. - * - * @return true if the operation completed successfully. - */ - public boolean unpublishCoverage(String workspace, String storename, String layerName) { - try { - final String fqLayerName; - - // this null check is here only for backward compatibility. - // workspace - // shall be mandatory. - if (workspace == null) { - - fqLayerName = layerName; - - if (LOGGER.isWarnEnabled()) { - LOGGER.warn("Null workspace while configuring layer : " + layerName - + " -- This behavior is deprecated."); - } - } else { - fqLayerName = workspace + ":" + layerName; - } - // delete related layer - URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + fqLayerName); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Going to delete " + "/rest/layers/" + fqLayerName); - } - boolean layerDeleted = HTTPUtils - .delete(deleteLayerUrl.toExternalForm(), gsuser, gspass); - if (!layerDeleted) { - LOGGER.warn("Could not delete layer '" + fqLayerName + "'"); - return false; - } - // delete the coverage - URL deleteCovUrl = new URL(restURL + "/rest/workspaces/" + workspace - + "/coveragestores/" + storename + "/coverages/" + layerName); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Going to delete " + "/rest/workspaces/" + workspace - + "/coveragestores/" + storename + "/coverages/" + layerName); - } - boolean covDeleted = HTTPUtils.delete(deleteCovUrl.toExternalForm(), gsuser, gspass); - if (!covDeleted) { - LOGGER.warn("Could not delete coverage " + workspace + ":" + storename + "/" - + layerName + ", but layer was deleted."); - } else { - LOGGER.info("Coverage successfully deleted " + workspace + ":" + storename + "/" - + layerName); - } - return covDeleted; - - // the covstore is still there: should we delete it? - - } catch (MalformedURLException ex) { - if (LOGGER.isErrorEnabled()) - LOGGER.error(ex.getLocalizedMessage(), ex); - return false; - } - } - - /** - * Removes the featuretype and the associated layer. - *
- * You may also want to {@link #removeDatastore(String, String) remove the datastore}.
- *
- * @return true if the operation completed successfully.
- */
- public boolean unpublishFeatureType(String workspace, String storename, String layerName) {
- try {
-
- final String fqLayerName;
- // this null check is here only for backward compatibility.
- // workspace
- // shall be mandatory.
- if (workspace == null) {
-
- fqLayerName = layerName;
-
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("Null workspace while configuring layer : " + layerName
- + " -- This behavior is deprecated.");
- }
- } else {
- fqLayerName = workspace + ":" + layerName;
- }
- // delete related layer
- URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + fqLayerName);
- boolean layerDeleted = HTTPUtils
- .delete(deleteLayerUrl.toExternalForm(), gsuser, gspass);
- if (!layerDeleted) {
- LOGGER.warn("Could not delete layer '" + fqLayerName + "'");
- return false;
- }
- // delete the coverage
- URL deleteFtUrl = new URL(restURL + "/rest/workspaces/" + workspace + "/datastores/"
- + storename + "/featuretypes/" + layerName);
- boolean ftDeleted = HTTPUtils.delete(deleteFtUrl.toExternalForm(), gsuser, gspass);
- if (!ftDeleted) {
- LOGGER.warn("Could not delete featuretype " + workspace + ":" + storename + "/"
- + layerName + ", but layer was deleted.");
- } else {
- LOGGER.info("FeatureType successfully deleted " + workspace + ":" + storename + "/"
- + layerName);
- }
-
- return ftDeleted;
-
- // the store is still there: should we delete it?
-
- } catch (MalformedURLException ex) {
- if (LOGGER.isErrorEnabled())
- LOGGER.error(ex.getLocalizedMessage(), ex);
- return false;
- }
- }
-
- /**
- * Remove recursively a given Datastore in a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param storename The name of the Datastore to remove.
- * @return true if the datastore was successfully removed.
- *
- * @deprecated will be removed in next release use {@link GeoServerRESTPublisher#removeDatastore(String, String, boolean)}
- */
- public boolean removeDatastore(String workspace, String storename) {
- try {
- return removeDatastore(workspace, storename, true);
- } catch (IllegalArgumentException e) {
- if (LOGGER.isErrorEnabled())
- LOGGER.error("Arguments may not be null or empty!", e);
- }
- return false;
- }
-
- /**
- * Remove a given Datastore in a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param storename The name of the Datastore to remove.
- * @param recurse if remove should be performed recursively
- * @throws IllegalArgumentException if workspace or storename are null or empty
- * @return true if the datastore was successfully removed.
- */
- public boolean removeDatastore(String workspace, String storename, final boolean recurse)
- throws IllegalArgumentException {
- return removeStore(workspace, storename, StoreType.DATASTORES, recurse);
- }
-
- /**
- * Remove recursively a given CoverageStore in a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param storename The name of the CoverageStore to remove.
- * @return true if the CoverageStore was successfully removed.
- * @deprecated use {@link #removeCoverageStore(String, String, boolean)}
- */
- public boolean removeCoverageStore(String workspace, String storename) {
- return removeCoverageStore(workspace, storename, true);
- }
-
- /**
- * Remove a given CoverageStore in a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param storename The name of the CoverageStore to remove.
- * @param recurse if remove should be performed recursively
- * @return true if the CoverageStore was successfully removed.
- */
- public boolean removeCoverageStore(final String workspace, final String storename,
- final boolean recurse) throws IllegalArgumentException {
- return removeStore(workspace, storename, StoreType.COVERAGESTORES, recurse);
- }
-
- /**
- * Remove a given Datastore in a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param storename The name of the Datastore to remove.
- * @param the {@link StoreType} type
- * @param recurse if remove should be performed recursively
- * @throws IllegalArgumentException if workspace or storename are null or empty
- * @return true if the store was successfully removed.
- */
- private boolean removeStore(String workspace, String storename, StoreType type,
- final boolean recurse) throws IllegalArgumentException {
- try {
- if (workspace == null || storename == null)
- throw new IllegalArgumentException("Arguments may not be null!");
- if (workspace.isEmpty() || storename.isEmpty())
- throw new IllegalArgumentException("Arguments may not be empty!");
-
- final StringBuilder url = new StringBuilder(restURL);
- url.append("/rest/workspaces/").append(workspace).append("/").append(type).append("/")
- .append(storename);
- if (recurse)
- url.append("?recurse=true");
- final URL deleteStore = new URL(url.toString());
-
- boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass);
- if (!deleted) {
- LOGGER.warn("Could not delete store " + workspace + ":" + storename);
- } else {
- LOGGER.info("Store successfully deleted " + workspace + ":" + storename);
- }
-
- return deleted;
- } catch (MalformedURLException ex) {
- if (LOGGER.isErrorEnabled())
- LOGGER.error(ex.getLocalizedMessage(), ex);
- return false;
- }
- }
-
- /**
- * Remove the workspace given Workspace using default parameters
- *
- * @see {@link GeoServerRESTPublisher#removeWorkspace(String, boolean)}
- * @param workspace the workspace to remove
- * @return true if success, false otherwise
- * @deprecated {@link #removeWorkspace(String, boolean)}
- */
- public boolean removeWorkspace(String workspace) {
- return removeWorkspace(workspace, false);
- }
-
- /**
- * Remove a given Workspace.
- *
- * @param workspace The name of the workspace
- * @param recurse The recurse parameter is used to recursively delete all resources contained by the specified workspace. This includes data
- * stores, coverage stores, feature types, etc... Allowable values for this parameter are true or false. The default value is
- * false.
- * @return true if the WorkSpace was successfully removed.
- */
- public boolean removeWorkspace(String workspace, boolean recurse)
- throws IllegalArgumentException {
- workspace = sanitize(workspace);
- try {
- if (workspace == null)
- throw new IllegalArgumentException("Arguments may not be null!");
- if (workspace.isEmpty())
- throw new IllegalArgumentException("Arguments may not be empty!");
-
- StringBuffer url = new StringBuffer(restURL).append("/rest/workspaces/").append(
- workspace);
- if (recurse)
- url.append("?recurse=true");
-
- deleteStylesForWorkspace(workspace); // !!! workaround
-
- final URL deleteUrl = new URL(url.toString());
- boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass);
- if (!deleted) {
- LOGGER.warn("Could not delete Workspace " + workspace);
- } else {
- LOGGER.info("Workspace successfully deleted " + workspace);
- }
-
- return deleted;
- } catch (MalformedURLException ex) {
- if (LOGGER.isErrorEnabled())
- LOGGER.error(ex.getLocalizedMessage(), ex);
- return false;
- }
- }
-
- /**
- * workaround: geoserver does not delete styles inside workspaces
- * https://jira.codehaus.org/browse/GEOS-5986
- */
- private void deleteStylesForWorkspace(String workspace) {
- RESTStyleList styles = styleManager.getStyles(workspace);
- if (styles==null)
- return;
- for (NameLinkElem nameLinkElem : styles) {
- removeStyleInWorkspace(workspace, nameLinkElem.getName(), true);
- }
- }
-
- /**
- * Remove a layer group.
- *
- * @param workspace the layer group workspace.
- * @param name the layer group name.
- * @return true if succeeded.
- */
- public boolean removeLayerGroup(String workspace, String name) {
- String url = restURL + "/rest";
- if (workspace == null) {
- url += "/layergroups/" + name;
- } else {
- url += "/workspaces/" + workspace + "/layergroups/" + name;
- }
-
- try {
- URL deleteUrl = new URL(url);
- boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass);
- if (!deleted) {
- if (LOGGER.isWarnEnabled())
- LOGGER.warn("Could not delete layergroup " + name);
- } else {
- if (LOGGER.isInfoEnabled())
- LOGGER.info("Layergroup successfully deleted: " + name);
- }
-
- return deleted;
- } catch (MalformedURLException ex) {
- if (LOGGER.isErrorEnabled())
- LOGGER.error(ex.getLocalizedMessage(), ex);
- return false;
- }
- }
-
- /**
- * Remove a layer group.
- *
- * @param name the layer group name.
- * @return true if succeeded.
- */
- public boolean removeLayerGroup(String name) {
- return removeLayerGroup(null, name);
- }
-
- /**
- * remove a generic given layer from a given workspace
- *
- * @param workspace
- * @param layerName
- * @return true if success
- */
- public boolean removeLayer(final String workspace, final String layerName) {
-
- final String fqLayerName;
-
- // this null check is here only for backward compatibility. workspace
- // shall be mandatory.
- if (workspace == null) {
-
- fqLayerName = layerName;
-
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("Null workspace while removing layer : " + layerName
- + " -- This behavior is deprecated.");
- }
- } else {
- fqLayerName = workspace + ":" + layerName;
- }
- if (layerName == null) {
- if (LOGGER.isErrorEnabled()) {
- LOGGER.error("Null layerName : " + layerName);
- }
- return false;
- }
-
- final String url = restURL + "/rest/layers/" + fqLayerName;
-
- boolean result = HTTPUtils.delete(url, gsuser, gspass);
- if (result) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info("Layer successfully removed: " + fqLayerName);
- }
- } else {
- if (LOGGER.isWarnEnabled())
- LOGGER.warn("Error removing layer " + fqLayerName);
- }
-
- return result;
- }
-
- // ==========================================================================
- // === CATALOG REFRESHING
- // ==========================================================================
-
- /**
- *
- * /workspaces/
- * NAME_0=VALUE_0&NAME_1=VALUE_1&....&NAME_n-1=VALUE_n-1
- *
- * This call configures all the coverages contained in the ImageMosaic.
- *
- * @param workspace the GeoServer workspace
- * @param coverageStore the GeoServer coverageStore
- * @param the absolute path to the file to upload
- *
- * @return
- * With the options configure we can decide whether or not to configure or not the coverages contained in the ImageMosaic.
- *
- * @param workspace the GeoServer workspace
- * @param coverageStore the GeoServer coverageStore
- * @param the absolute path to the file to upload
- * @param configureOpt tells GeoServer whether to configure all coverages in this mosaic (ALL) or none of them (NONE).
- *
- * @return
- * It throws an exception in case the string is either null or empty.
- *
- * @param string the {@link String} to be checked
- */
- private static void checkString(String string) {
- if (string == null) {
- throw new NullPointerException("Provided string is is null!");
- }
- if (string.length() <= 0) {
- throw new IllegalArgumentException("Provided string is is empty!");
- }
-
- }
-
-}
+/*
+ * GeoServer-Manager - Simple Manager Library for GeoServer
+ *
+ * Copyright (C) 2007,2013 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;
+
+import it.geosolutions.geoserver.rest.decoder.RESTCoverage;
+import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList;
+import it.geosolutions.geoserver.rest.decoder.RESTStyleList;
+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.GSLayerGroupEncoder;
+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.feature.GSFeatureTypeEncoder;
+import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredGridCoverageReaderManager;
+import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredGridCoverageReaderManager.ConfigureCoveragesOption;
+import it.geosolutions.geoserver.rest.manager.GeoServerRESTStyleManager;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.zip.ZipFile;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.io.FilenameUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Connect to a GeoServer instance to publish or modify its contents via REST API.
+ *
+ * There are no modifiable instance fields, so all the calls are thread-safe.
+ *
+ * @author ETj (etj at geo-solutions.it)
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+public class GeoServerRESTPublisher {
+
+ public static final String DEFAULT_CRS = "EPSG:4326";
+
+ /** The logger for this class */
+ private static final Logger LOGGER = LoggerFactory.getLogger(GeoServerRESTPublisher.class);
+
+ /**
+ * GeoServer instance base URL. E.g.: http://localhost:8080/geoserver.
+ */
+ private final String restURL;
+
+ /**
+ * GeoServer instance privileged username, with read & write permission on REST API
+ */
+ private final String gsuser;
+
+ /**
+ * GeoServer instance password for privileged username with r&w permission on REST API
+ */
+ private final String gspass;
+
+
+ private final GeoServerRESTStyleManager styleManager;
+ /**
+ * Creates a GeoServerRESTPublisher to connect against a GeoServer instance with the given URL and user credentials.
+ *
+ * @param restURL the base GeoServer URL (e.g.: http://localhost:8080/geoserver)
+ * @param username auth credential
+ * @param password auth credential
+ */
+ public GeoServerRESTPublisher(String restURL, String username, String password) {
+ this.restURL = HTTPUtils.decurtSlash(restURL);
+ this.gsuser = username;
+ this.gspass = password;
+
+ URL url = null;
+ try {
+ url = new URL(restURL);
+ } catch (MalformedURLException ex) {
+ LOGGER.error("Bad URL: Calls to GeoServer are going to fail" , ex);
+ }
+ styleManager = new GeoServerRESTStyleManager(url, username, password);
+ }
+
+ // ==========================================================================
+ // === BACKUP and RESTORE
+ // ==========================================================================
+
+ /**
+ * Issues a GeoServer BACKUP.
+ *
+ * Won't include data, cached tiles, or logs. Use {@link #backup(String, boolean, boolean, boolean)} to control these parameters.
+ *
+ * @param backupDir the target Backup Dir String.
+ *
+ * @return id of the backup.
+ * @throws IllegalArgumentException if the backupDir is null or empty
+ */
+ public String backup(final String backupDir) throws IllegalArgumentException {
+ /*
+ * This is the equivalent call with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data
+ * "<task><path>${BACKUP_DATADIR}</path></task>" \ ${restURL}/rest/bkprst/backup}
+ */
+ return backup(backupDir, false, false, false);
+ }
+
+ /**
+ * Issues a GeoServer BACKUP.
+ *
+ * @param backupDir the target Backup Dir String.
+ * @param includedata whether or not include the data dir Boolean.
+ * @param includegwc whether or not include the geowebcache dir Boolean.
+ * @param includelog whether or not include the log dir Boolean.
+ *
+ * @return id of the backup.
+ * @throws IllegalArgumentException if the backupDir is null or empty.
+ */
+ public String backup(final String backupDir, final boolean includedata,
+ final boolean includegwc, final boolean includelog) throws IllegalArgumentException {
+ /*
+ * This is the equivalent call with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data
+ * "<task><path>${BACKUP_DATADIR}</path><includedata>${includedata}</includedata><includegwc>${includegwc}</includegwc><includelog>${includelog}</includelog></task>"
+ * \ ${restURL}/rest/bkprst/backup}
+ */
+ if ((backupDir == null) || backupDir.isEmpty()) {
+ throw new IllegalArgumentException("The backup_dir must not be null or empty");
+ }
+
+ StringBuilder bkpUrl = new StringBuilder(restURL);
+ bkpUrl.append("/rest/bkprst/backup");
+
+ final GSBackupEncoder bkpenc = new GSBackupEncoder(backupDir);
+ bkpenc.setIncludeData(includedata);
+ bkpenc.setIncludeGwc(includegwc);
+ bkpenc.setIncludeLog(includelog);
+ final String result = HTTPUtils.post(bkpUrl.toString(), bkpenc.toString(), "text/xml",
+ gsuser, gspass);
+
+ return result;
+ }
+
+ /**
+ * Issues a GeoServer RESTORE.
+ *
+ * @param backupDir the source backup dir.
+ *
+ * @return id of the backup.
+ * @throws IllegalArgumentException if the backupDir is null or empty
+ */
+ public String restore(final String backupDir) throws IllegalArgumentException {
+ /*
+ * This is the equivalent call with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ --data
+ * "<task><path>${BACKUP_DATADIR}</path></task>" \ ${restURL}/rest/bkprst/restore}
+ */
+ if ((backupDir == null) || backupDir.isEmpty()) {
+ throw new IllegalArgumentException("The backup_dir must not be null or empty");
+ }
+
+ StringBuilder bkpUrl = new StringBuilder(restURL);
+ bkpUrl.append("/rest/bkprst/restore");
+
+ final GSBackupEncoder bkpenc = new GSBackupEncoder(backupDir);
+
+ final String result = HTTPUtils.post(bkpUrl.toString(), bkpenc.toString(), "text/xml",
+ gsuser, gspass);
+
+ return result;
+ }
+
+ // ==========================================================================
+ // === WORKSPACES
+ // ==========================================================================
+
+ /**
+ * Create a new Workspace.
+ *
+ * GeoServer will automatically create an associated Namespace with the URI being "http://{workspaceName}". To specify a custom Namespace URI, use
+ * {@link #createWorkspace(String, URI)}.
+ *
+ * @param workspace The name of the new workspace.
+ *
+ * @return true if the workspace was created.
+ */
+ public boolean createWorkspace(final String workspace) {
+ /*
+ * This is the equivalent call with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: text/xml' \ -d "
+ * Note that this method is equivalent to {@link #createNamespace}.
+ *
+ * @param name Name for the new workspace, which will be also its associated namespace prefix.
+ * @param uri Namespace URI. Cannot be empty.
+ * @return true if the Workspace and its associated namespace were successfully created.
+ */
+ public boolean createWorkspace(final String name, final URI uri) {
+ // This is really an alias to createNamespace, as GeoServer
+ // will automatically create the associated workspace as well.
+ return createNamespace(name, uri);
+ }
+
+ // ==========================================================================
+ // === NAMESPACES
+ // ==========================================================================
+
+ /**
+ * Create a new Namespace. GeoServer will automatically create the corresponding Workspace.
+ *
+ * Prefix and URI are mandatory and cannot be empty. If a Namespace with the given prefix already exists, it won't be created.
+ *
+ * @param prefix The name of the new Namespace.
+ * @param uri The URI of the new Namespace.
+ *
+ * @return true if the Namespace was successfully created.
+ * @see GeoServer Documentation
+ */
+ public boolean createNamespace(final String prefix, final URI uri) {
+ final String sUrl = restURL + "/rest/namespaces";
+ final GSNamespaceEncoder nsenc = new GSNamespaceEncoder(prefix, uri);
+ final String nsxml = nsenc.toString();
+ final String result = HTTPUtils.postXml(sUrl, nsxml, gsuser, gspass);
+ return result != null;
+ }
+
+ /**
+ * Update a Namespace URI.
+ *
+ * Prefix and URI are mandatory and cannot be empty. A Namespace with the given prefix should exist.
+ *
+ * @param prefix The prefix of an existing Namespace.
+ * @param uri The new URI.
+ *
+ * @return true if the Namespace was successfully updated.
+ */
+ public boolean updateNamespace(final String prefix, final URI uri) {
+ final String sUrl = restURL + "/rest/namespaces/" + encode(prefix);
+ final GSNamespaceEncoder nsenc = new GSNamespaceEncoder(prefix, uri);
+ final String nsxml = nsenc.toString();
+ final String result = HTTPUtils.put(sUrl, nsxml, "application/xml", gsuser, gspass);
+ return result != null;
+ }
+
+ /**
+ * Remove a given Namespace. It will remove the associated Workspace as well.
+ *
+ * @param prefix The Namespace prefix
+ * @param recurse The recurse parameter is used to recursively delete all resources contained in the workspace associated with this Namespace.
+ * This includes data stores, coverage stores, feature types, etc... Allowable values for this parameter are true or false.
+ * The default (safer) value is false.
+ *
+ * @return true if the Namespace was successfully removed.
+ */
+ public boolean removeNamespace(final String prefix, boolean recurse) {
+ // Hack: We are instead calling removeWorkspace, as DELETE on
+ // a namespace will leave associated workspace in an inconsistent
+ // state. See https://jira.codehaus.org/browse/GEOS-5075
+ // TODO switch to namespace when GEOS-5075 is solved
+ return removeWorkspace(prefix, recurse);
+ }
+
+ // ==========================================================================
+ // === STYLES
+ // ==========================================================================
+
+ /**
+ * Store and publish a Style.
+ *
+ * @param sldBody the full SLD document as a String.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishStyle(String sldBody) {
+ return styleManager.publishStyle(sldBody);
+ }
+
+ /**
+ * Store and publish a Style, assigning it a name.
+ *
+ * @param sldBody the full SLD document as a String.
+ * @param name the Style name.
+ *
+ * @return true if the operation completed successfully.
+ * @throws IllegalArgumentException if the style body is null or empty.
+ */
+ public boolean publishStyle(final String sldBody, final String name)
+ throws IllegalArgumentException {
+ return styleManager.publishStyle(sldBody, name);
+ }
+
+ /**
+ * Store and publish a Style.
+ *
+ * @param sldFile the File containing the SLD document.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishStyle(File sldFile) {
+ return styleManager.publishStyle(sldFile);
+ }
+
+ /**
+ * Store and publish a Style, assigning it a name.
+ *
+ * @param sldFile the File containing the SLD document.
+ * @param name the Style name.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishStyle(File sldFile, String name) {
+ return styleManager.publishStyle(sldFile, name);
+ }
+
+ /**
+ * Store and publish a Style, assigning it a name and choosing the raw format.
+ *
+ * @param sldFile the File containing the SLD document.
+ * @param name the Style name.
+ * @param raw the raw format
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishStyle(File sldFile, String name, boolean raw) {
+ return styleManager.publishStyle(sldFile, name, raw);
+ }
+
+ /**
+ * Update a Style.
+ *
+ * @param sldBody the new SLD document as a String.
+ * @param name the Style name to update.
+ *
+ * @return true if the operation completed successfully.
+ * @throws IllegalArgumentException if the style body or name are null or empty.
+ */
+ public boolean updateStyle(final String sldBody, final String name)
+ throws IllegalArgumentException {
+ return styleManager.updateStyle(sldBody, name);
+ }
+
+ /**
+ * Update a Style.
+ *
+ * @param sldFile the File containing the SLD document.
+ * @param name the Style name.
+ *
+ * @return true if the operation completed successfully.
+ * @throws IllegalArgumentException if the sldFile file or name are null or name is empty.
+ */
+ public boolean updateStyle(final File sldFile, final String name)
+ throws IllegalArgumentException {
+
+ return styleManager.updateStyle(sldFile, name);
+ }
+
+ /**
+ * Remove a Style.
+ *
+ * The Style will be unpublished, and (optionally) the SLD file will be removed.
+ *
+ * @param styleName the name of the Style to remove.
+ * @param purge remove the related SLD file from disk.
+ *
+ * @return true if the operation completed successfully.
+ * @throws IllegalArgumentException if styleName is null or empty.
+ */
+ public boolean removeStyle(String styleName, final boolean purge)
+ throws IllegalArgumentException {
+
+ return styleManager.removeStyle(styleName, purge);
+ }
+
+ /**
+ * Remove a Style.
+ *
+ * The Style will be unpublished and the related SLD file will be removed.
+ *
+ * @param styleName the name of the Style to remove.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean removeStyle(String styleName) {
+ return styleManager.removeStyle(styleName);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#
+ */
+ public boolean publishStyleInWorkspace(String workspace, String sldBody) {
+ return styleManager.publishStyleInWorkspace(workspace, sldBody);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#
+ */
+ public boolean publishStyleInWorkspace(String workspace, String sldBody, String name) throws IllegalArgumentException {
+ return styleManager.publishStyleInWorkspace(workspace, sldBody, name);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#publishStyleInWorkspace(java.lang.String, java.io.File)
+ */
+ public boolean publishStyleInWorkspace(String workspace, File sldFile) {
+ return styleManager.publishStyleInWorkspace(workspace, sldFile);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#publishStyleInWorkspace(java.lang.String, java.io.File, java.lang.String)
+ */
+ public boolean publishStyleInWorkspace(String workspace, File sldFile, String name) {
+ return styleManager.publishStyleInWorkspace(workspace, sldFile, name);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#updateStyleInWorkspace(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public boolean updateStyleInWorkspace(String workspace, String sldBody, String name) throws IllegalArgumentException {
+ return styleManager.updateStyleInWorkspace(workspace, sldBody, name);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#updateStyleInWorkspace(java.lang.String, java.io.File, java.lang.String)
+ */
+ public boolean updateStyleInWorkspace(String workspace, File sldFile, String name) throws IllegalArgumentException {
+ return styleManager.updateStyleInWorkspace(workspace, sldFile, name);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#removeStyleInWorkspace(java.lang.String, java.lang.String, boolean)
+ */
+ public boolean removeStyleInWorkspace(String workspace, String styleName, boolean purge) throws IllegalArgumentException {
+ return styleManager.removeStyleInWorkspace(workspace, styleName, purge);
+ }
+
+ /**
+ * @since GeoServer 2.2
+ * @see GeoServerRESTStyleManager#removeStyleInWorkspace(java.lang.String, java.lang.String)
+ */
+ public boolean removeStyleInWorkspace(String workspace, String styleName) {
+ return styleManager.removeStyleInWorkspace(workspace, styleName);
+ }
+
+
+ // ==========================================================================
+ // === DATASTORE PUBLISHING
+ // ==========================================================================
+
+ /**
+ *
+ * @author cancellieri
+ * @deprecated use {@link StoreType}
+ */
+ public enum DataStoreType {
+ /**
+ * Raster based data sources.
+ */
+ COVERAGESTORES,
+ /**
+ * Vector based data sources. Can be a file in the case of a Shapefile, a database connection in the case of PostGIS, or a server in the case
+ * of a remote Web Feature Service.
+ */
+ DATASTORES;
+
+ /**
+ * @deprecated use {@link StoreType#getTypeNameWithFormat(StoreType, Format)}
+ * @param type
+ * @return
+ */
+ public static String getTypeName(StoreType type) {
+ return StoreType.getTypeNameWithFormat(type, Format.XML);
+ }
+
+ /**
+ * @deprecated use {@link StoreType#toString()}
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * DataStoreType definitions.
+ *
+ * The SRS will be set to EPSG:4326.
+ *
+ * @see {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, ProjectionPolicy, String)}
+ *
+ * @param workspace The workspace name.
+ * @param storename The store name.
+ * @param layername The layer name.
+ * @param zipFile The zipped file to publish.
+ *
+ * @return {@code true} if the operation completed successfully.
+ * @throws FileNotFoundException , IllegalArgumentException
+ */
+ public boolean publishShp(String workspace, String storename, String datasetname, File zipFile)
+ throws FileNotFoundException, IllegalArgumentException {
+ return publishShp(workspace, storename, new NameValuePair[0], datasetname,
+ UploadMethod.FILE, zipFile.toURI(), DEFAULT_CRS, null);
+ }
+
+ /**
+ * Publish a shapefile.
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param storeParams parameters to append to the url (can be null).
+ * 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:
+ *
+ * In a POST or PUT operation the format specifies 1) the representatin of the content being sent to the server, and 2) the representation of the
+ * response to be sent back. The former is specified with the Content-type header. To send a representation in XML, the content type "text/xml" or
+ * "application/xml" would be used. The latter is specified with the Accepts header as specified in the above paragraph describing a GET
+ * operation.
+ *
+ * The following table defines the Content-type values for each format:
+ *
+ * First, the associated layer is removed, then the Coverage configuration itself.
+ *
+ * CHECKME Maybe the coveragestore has to be removed as well.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean unpublishCoverage(String workspace, String storename, String layerName) {
+ try {
+ final String fqLayerName;
+
+ // this null check is here only for backward compatibility.
+ // workspace
+ // shall be mandatory.
+ if (workspace == null) {
+
+ fqLayerName = layerName;
+
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn("Null workspace while configuring layer : " + layerName
+ + " -- This behavior is deprecated.");
+ }
+ } else {
+ fqLayerName = workspace + ":" + layerName;
+ }
+ // delete related layer
+ URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + fqLayerName);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Going to delete " + "/rest/layers/" + fqLayerName);
+ }
+ boolean layerDeleted = HTTPUtils
+ .delete(deleteLayerUrl.toExternalForm(), gsuser, gspass);
+ if (!layerDeleted) {
+ LOGGER.warn("Could not delete layer '" + fqLayerName + "'");
+ return false;
+ }
+ // delete the coverage
+ URL deleteCovUrl = new URL(restURL + "/rest/workspaces/" + workspace
+ + "/coveragestores/" + storename + "/coverages/" + layerName);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Going to delete " + "/rest/workspaces/" + workspace
+ + "/coveragestores/" + storename + "/coverages/" + layerName);
+ }
+ boolean covDeleted = HTTPUtils.delete(deleteCovUrl.toExternalForm(), gsuser, gspass);
+ if (!covDeleted) {
+ LOGGER.warn("Could not delete coverage " + workspace + ":" + storename + "/"
+ + layerName + ", but layer was deleted.");
+ } else {
+ LOGGER.info("Coverage successfully deleted " + workspace + ":" + storename + "/"
+ + layerName);
+ }
+ return covDeleted;
+
+ // the covstore is still there: should we delete it?
+
+ } catch (MalformedURLException ex) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error(ex.getLocalizedMessage(), ex);
+ return false;
+ }
+ }
+
+ /**
+ * Removes the featuretype and the associated layer.
+ *
+ * You may also want to {@link #removeDatastore(String, String) remove the datastore}.
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean unpublishFeatureType(String workspace, String storename, String layerName) {
+ try {
+
+ final String fqLayerName;
+ // this null check is here only for backward compatibility.
+ // workspace
+ // shall be mandatory.
+ if (workspace == null) {
+
+ fqLayerName = layerName;
+
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn("Null workspace while configuring layer : " + layerName
+ + " -- This behavior is deprecated.");
+ }
+ } else {
+ fqLayerName = workspace + ":" + layerName;
+ }
+ // delete related layer
+ URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + fqLayerName);
+ boolean layerDeleted = HTTPUtils
+ .delete(deleteLayerUrl.toExternalForm(), gsuser, gspass);
+ if (!layerDeleted) {
+ LOGGER.warn("Could not delete layer '" + fqLayerName + "'");
+ return false;
+ }
+ // delete the coverage
+ URL deleteFtUrl = new URL(restURL + "/rest/workspaces/" + workspace + "/datastores/"
+ + storename + "/featuretypes/" + layerName);
+ boolean ftDeleted = HTTPUtils.delete(deleteFtUrl.toExternalForm(), gsuser, gspass);
+ if (!ftDeleted) {
+ LOGGER.warn("Could not delete featuretype " + workspace + ":" + storename + "/"
+ + layerName + ", but layer was deleted.");
+ } else {
+ LOGGER.info("FeatureType successfully deleted " + workspace + ":" + storename + "/"
+ + layerName);
+ }
+
+ return ftDeleted;
+
+ // the store is still there: should we delete it?
+
+ } catch (MalformedURLException ex) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error(ex.getLocalizedMessage(), ex);
+ return false;
+ }
+ }
+
+ /**
+ * Remove recursively a given Datastore in a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param storename The name of the Datastore to remove.
+ * @return true if the datastore was successfully removed.
+ *
+ * @deprecated will be removed in next release use {@link GeoServerRESTPublisher#removeDatastore(String, String, boolean)}
+ */
+ public boolean removeDatastore(String workspace, String storename) {
+ try {
+ return removeDatastore(workspace, storename, true);
+ } catch (IllegalArgumentException e) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("Arguments may not be null or empty!", e);
+ }
+ return false;
+ }
+
+ /**
+ * Remove a given Datastore in a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param storename The name of the Datastore to remove.
+ * @param recurse if remove should be performed recursively
+ * @throws IllegalArgumentException if workspace or storename are null or empty
+ * @return true if the datastore was successfully removed.
+ */
+ public boolean removeDatastore(String workspace, String storename, final boolean recurse)
+ throws IllegalArgumentException {
+ return removeStore(workspace, storename, StoreType.DATASTORES, recurse);
+ }
+
+ /**
+ * Remove recursively a given CoverageStore in a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param storename The name of the CoverageStore to remove.
+ * @return true if the CoverageStore was successfully removed.
+ * @deprecated use {@link #removeCoverageStore(String, String, boolean)}
+ */
+ public boolean removeCoverageStore(String workspace, String storename) {
+ return removeCoverageStore(workspace, storename, true);
+ }
+
+ /**
+ * Remove a given CoverageStore in a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param storename The name of the CoverageStore to remove.
+ * @param recurse if remove should be performed recursively
+ * @return true if the CoverageStore was successfully removed.
+ */
+ public boolean removeCoverageStore(final String workspace, final String storename,
+ final boolean recurse) throws IllegalArgumentException {
+ return removeStore(workspace, storename, StoreType.COVERAGESTORES, recurse);
+ }
+
+ /**
+ * Remove a given Datastore in a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param storename The name of the Datastore to remove.
+ * @param the {@link StoreType} type
+ * @param recurse if remove should be performed recursively
+ * @throws IllegalArgumentException if workspace or storename are null or empty
+ * @return true if the store was successfully removed.
+ */
+ private boolean removeStore(String workspace, String storename, StoreType type,
+ final boolean recurse) throws IllegalArgumentException {
+ try {
+ if (workspace == null || storename == null)
+ throw new IllegalArgumentException("Arguments may not be null!");
+ if (workspace.isEmpty() || storename.isEmpty())
+ throw new IllegalArgumentException("Arguments may not be empty!");
+
+ final StringBuilder url = new StringBuilder(restURL);
+ url.append("/rest/workspaces/").append(workspace).append("/").append(type).append("/")
+ .append(storename);
+ if (recurse)
+ url.append("?recurse=true");
+ final URL deleteStore = new URL(url.toString());
+
+ boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass);
+ if (!deleted) {
+ LOGGER.warn("Could not delete store " + workspace + ":" + storename);
+ } else {
+ LOGGER.info("Store successfully deleted " + workspace + ":" + storename);
+ }
+
+ return deleted;
+ } catch (MalformedURLException ex) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error(ex.getLocalizedMessage(), ex);
+ return false;
+ }
+ }
+
+ /**
+ * Remove the workspace given Workspace using default parameters
+ *
+ * @see {@link GeoServerRESTPublisher#removeWorkspace(String, boolean)}
+ * @param workspace the workspace to remove
+ * @return true if success, false otherwise
+ * @deprecated {@link #removeWorkspace(String, boolean)}
+ */
+ public boolean removeWorkspace(String workspace) {
+ return removeWorkspace(workspace, false);
+ }
+
+ /**
+ * Remove a given Workspace.
+ *
+ * @param workspace The name of the workspace
+ * @param recurse The recurse parameter is used to recursively delete all resources contained by the specified workspace. This includes data
+ * stores, coverage stores, feature types, etc... Allowable values for this parameter are true or false. The default value is
+ * false.
+ * @return true if the WorkSpace was successfully removed.
+ */
+ public boolean removeWorkspace(String workspace, boolean recurse)
+ throws IllegalArgumentException {
+ workspace = sanitize(workspace);
+ try {
+ if (workspace == null)
+ throw new IllegalArgumentException("Arguments may not be null!");
+ if (workspace.isEmpty())
+ throw new IllegalArgumentException("Arguments may not be empty!");
+
+ StringBuffer url = new StringBuffer(restURL).append("/rest/workspaces/").append(
+ workspace);
+ if (recurse)
+ url.append("?recurse=true");
+
+ deleteStylesForWorkspace(workspace); // !!! workaround
+
+ final URL deleteUrl = new URL(url.toString());
+ boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass);
+ if (!deleted) {
+ LOGGER.warn("Could not delete Workspace " + workspace);
+ } else {
+ LOGGER.info("Workspace successfully deleted " + workspace);
+ }
+
+ return deleted;
+ } catch (MalformedURLException ex) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error(ex.getLocalizedMessage(), ex);
+ return false;
+ }
+ }
+
+ /**
+ * workaround: geoserver does not delete styles inside workspaces
+ * https://jira.codehaus.org/browse/GEOS-5986
+ */
+ private void deleteStylesForWorkspace(String workspace) {
+ RESTStyleList styles = styleManager.getStyles(workspace);
+ if (styles==null)
+ return;
+ for (NameLinkElem nameLinkElem : styles) {
+ removeStyleInWorkspace(workspace, nameLinkElem.getName(), true);
+ }
+ }
+
+ /**
+ * Remove a layer group.
+ *
+ * @param workspace the layer group workspace.
+ * @param name the layer group name.
+ * @return true if succeeded.
+ */
+ public boolean removeLayerGroup(String workspace, String name) {
+ String url = restURL + "/rest";
+ if (workspace == null) {
+ url += "/layergroups/" + name;
+ } else {
+ url += "/workspaces/" + workspace + "/layergroups/" + name;
+ }
+
+ try {
+ URL deleteUrl = new URL(url);
+ boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass);
+ if (!deleted) {
+ if (LOGGER.isWarnEnabled())
+ LOGGER.warn("Could not delete layergroup " + name);
+ } else {
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("Layergroup successfully deleted: " + name);
+ }
+
+ return deleted;
+ } catch (MalformedURLException ex) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error(ex.getLocalizedMessage(), ex);
+ return false;
+ }
+ }
+
+ /**
+ * Remove a layer group.
+ *
+ * @param name the layer group name.
+ * @return true if succeeded.
+ */
+ public boolean removeLayerGroup(String name) {
+ return removeLayerGroup(null, name);
+ }
+
+ /**
+ * remove a generic given layer from a given workspace
+ *
+ * @param workspace
+ * @param layerName
+ * @return true if success
+ */
+ public boolean removeLayer(final String workspace, final String layerName) {
+
+ final String fqLayerName;
+
+ // this null check is here only for backward compatibility. workspace
+ // shall be mandatory.
+ if (workspace == null) {
+
+ fqLayerName = layerName;
+
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn("Null workspace while removing layer : " + layerName
+ + " -- This behavior is deprecated.");
+ }
+ } else {
+ fqLayerName = workspace + ":" + layerName;
+ }
+ if (layerName == null) {
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Null layerName : " + layerName);
+ }
+ return false;
+ }
+
+ final String url = restURL + "/rest/layers/" + fqLayerName;
+
+ boolean result = HTTPUtils.delete(url, gsuser, gspass);
+ if (result) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Layer successfully removed: " + fqLayerName);
+ }
+ } else {
+ if (LOGGER.isWarnEnabled())
+ LOGGER.warn("Error removing layer " + fqLayerName);
+ }
+
+ return result;
+ }
+
+ // ==========================================================================
+ // === CATALOG REFRESHING
+ // ==========================================================================
+
+ /**
+ *
+ * /workspaces/
+ * NAME_0=VALUE_0&NAME_1=VALUE_1&....&NAME_n-1=VALUE_n-1
+ *
+ * This call configures all the coverages contained in the ImageMosaic.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param the absolute path to the file to upload
+ *
+ * @return
+ * With the options configure we can decide whether or not to configure or not the coverages contained in the ImageMosaic.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param the absolute path to the file to upload
+ * @param configureOpt tells GeoServer whether to configure all coverages in this mosaic (ALL) or none of them (NONE).
+ *
+ * @return
+ * It throws an exception in case the string is either null or empty.
+ *
+ * @param string the {@link String} to be checked
+ */
+ private static void checkString(String string) {
+ if (string == null) {
+ throw new NullPointerException("Provided string is is null!");
+ }
+ if (string.length() <= 0) {
+ throw new IllegalArgumentException("Provided string is is empty!");
+ }
+
+ }
+
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStyleManager.java b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStyleManager.java
index b66f899..50fa601 100644
--- a/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStyleManager.java
+++ b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStyleManager.java
@@ -260,6 +260,15 @@ public class GeoServerRESTStyleManager extends GeoServerRESTAbstractManager {
return result != null;
}
+ /**
+ * Store and publish a Style, assigning it a name and choosing the raw format.
+ *
+ * @param sldFile the File containing the SLD document.
+ * @param name the Style name.
+ * @param raw the raw format
+ *
+ * @return true if the operation completed successfully.
+ */
public boolean publishStyle(final File sldFile, final String name, final boolean raw) {
/*
* This is the equivalent call with cUrl:
true if the call succeeds or false otherwise.
- */
- public boolean harvestExternal(String workspace, String coverageStore, String format,
- String path) {
- try {
- GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
- new URL(restURL), gsuser, gspass);
- return manager.harvestExternal(workspace, coverageStore, format, path);
- } catch (IllegalArgumentException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- } catch (MalformedURLException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- }
- return false;
- }
-
- /**
- * Create a new ImageMosaic with the provided configuration provided as a zip file.
- *
- * true if the call succeeds or false otherwise.
- * @since geoserver-2.4.0, geoserver-mng-1.6.0
- */
- public boolean createImageMosaic(String workspace, String coverageStore, String path) {
- return createImageMosaic(workspace, coverageStore, path, ConfigureCoveragesOption.ALL);
- }
-
- /**
- * Create a new ImageMosaic with the provided configuration provided as a zip file.
- *
- * true if the call succeeds or false otherwise.
- * @since geoserver-2.4.0, geoserver-mng-1.6.0
- */
- public boolean createImageMosaic(String workspace, String coverageStore, String path, ConfigureCoveragesOption configureOpt) {
- // checks
- checkString(workspace);
- checkString(coverageStore);
- checkString(path);
- final File zipFile= new File(path);
- if(!zipFile.exists()||!zipFile.isFile()||!zipFile.canRead()){
- throw new IllegalArgumentException("The provided pathname does not point to a valide zip file: "+path);
- }
- // is it a zip?
- ZipFile zip=null;
- try{
- zip= new ZipFile(zipFile);
- zip.getName();
- }catch (Exception e) {
- LOGGER.trace(e.getLocalizedMessage(),e.getStackTrace());
- throw new IllegalArgumentException("The provided pathname does not point to a valide zip file: "+path);
- }finally{
- if(zip!=null){
- try {
- zip.close();
- } catch (IOException e) {
- // swallow
- LOGGER.trace(e.getLocalizedMessage(),e.getStackTrace());
- }
- }
- }
-
- // create URL
- StringBuilder ss=HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/",
- coverageStore, "/", UploadMethod.EXTERNAL.toString(), ".imagemosaic");
- switch(configureOpt){
- case ALL:
- break;
- case NONE:
- ss.append("?configure=none");
- break;
- default:
- throw new IllegalArgumentException("Unrecognized COnfigureOption: "+configureOpt);
- }
- String sUrl = ss.toString();
-
- // POST request
- String result = HTTPUtils.put(sUrl, zipFile, "application/zip", gsuser, gspass);
- return result != null;
- }
-
- /**
- * Remove a granule from a structured coverage by id.
- *
- * @param workspace the GeoServer workspace
- * @param coverageStore the GeoServer coverageStore
- * @param coverage the name of the target coverage from which we are going to remove
- * @param filter the absolute path to the file to upload
- *
- * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
- *
- * @throws MalformedURLException
- * @throws UnsupportedEncodingException
- */
- public boolean removeGranuleById(final String workspace, String coverageStore, String coverage,
- String granuleId) {
- try {
- GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
- new URL(restURL), gsuser, gspass);
- return manager.removeGranuleById(workspace, coverageStore, coverage, granuleId);
- } catch (IllegalArgumentException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- } catch (MalformedURLException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- }
- return false;
- }
-
- /**
- * Remove granules from a structured coverage, by providing a CQL filter.
- *
- * @param workspace the GeoServer workspace
- * @param coverageStore the GeoServer coverageStore
- * @param coverage the name of the target coverage from which we are going to remove
- * @param filter the absolute path to the file to upload
- *
- * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
- *
- * @throws MalformedURLException
- * @throws UnsupportedEncodingException
- */
- public boolean removeGranulesByCQL(final String workspace, String coverageStore,
- String coverage, String filter) throws UnsupportedEncodingException {
- try {
- GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
- new URL(restURL), gsuser, gspass);
- return manager.removeGranulesByCQL(workspace, coverageStore, coverage, filter);
- } catch (IllegalArgumentException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- } catch (MalformedURLException e) {
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info(e.getLocalizedMessage(), e);
- }
- }
- return false;
-
- }
-
- /**
- * Check the provided string for not being null or empty.
- *
- *
+ *
+ *
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+ public enum StoreType {
+ /**
+ * Raster based data sources.
+ */
+ COVERAGESTORES,
+ /**
+ * Vector based data sources. Can be a file in the case of a Shapefile, a database connection in the case of PostGIS, or a server in the case
+ * of a remote Web Feature Service.
+ */
+ DATASTORES;
+
+ /**
+ * Get the type name of a StoreType with the specified format.
+ *
+ * @param type the StoreType.
+ * @param format see {@link Format}
+ * @return "featureTypes.{xml|html|...}" for DATASTORES, "coverages.{xml|html|...}" otherwise.
+ */
+ public static String getTypeNameWithFormat(StoreType type, Format format) {
+ return getTypeName(type) + "." + format;
+ }
+
+ /**
+ * Get the type name of a StoreType with the specified format.
+ *
+ * @param type the StoreType.
+ * @param format see {@link Format}
+ * @return "featuretypes.{xml|html|...}" for DATASTORES, "coverages.{xml|html|...}" otherwise.
+ */
+ public String getTypeNameWithFormat(Format format) {
+ return getTypeName(this).toLowerCase() + "." + format;
+ }
+
+ /**
+ * Get the type name of a StoreType.
+ *
+ * @param type the StoreType.
+ * @return "featureTypes" for DATASTORES, "coverages" otherwise.
+ */
+ public static String getTypeName(StoreType type) {
+ switch (type) {
+ case COVERAGESTORES:
+ return "coverages"; // Format
+ case DATASTORES:
+ return "featureTypes";
+ default:
+ return "coverages";
+ }
+ }
+
+ /**
+ * Get the type name of a StoreType.
+ *
+ * @param type the StoreType.
+ * @return "dataStore" for DATASTORES, "coverageStore" otherwise.
+ */
+ public static String getType(StoreType type) {
+ switch (type) {
+ case COVERAGESTORES:
+ return "coverageStore"; // Format
+ case DATASTORES:
+ return "dataStore";
+ default:
+ return "coverageStore";
+ }
+ }
+
+ /**
+ * Get the type name of a StoreType.
+ *
+ * @return "featuretypes" for DATASTORES, "coverages" otherwise.
+ */
+ public String getTypeName() {
+ return getTypeName(this);
+ }
+
+ /**
+ * Get the type of a StoreType.
+ *
+ * @param type the StoreType.
+ * @return "dataStore" for DATASTORES, "coverageStore" otherwise.
+ */
+ public String getType() {
+ return getType(this);
+ }
+
+ /**
+ * Returns a lowercase representation of the parameter value, suitable to construct the rest call.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Specifies the method used to publish a resource.
+ *
+ *
+ *
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+ public enum UploadMethod {
+ /**
+ * directly upload a file from a local source. The body of the request is the file itself.
+ */
+ FILE, @Deprecated
+ file,
+ /**
+ * indirectly upload a file from a remote source. The body of the request is the URL where the data is published. This url must be visible
+ * from the server.
+ */
+ URL, @Deprecated
+ url,
+ /**
+ * forgo upload, and use an existing file on the server. The body of the request is the absolute local path to the existing file.
+ */
+ EXTERNAL, @Deprecated
+ external;
+
+ /**
+ * Returns a lowercase representation of the parameter value, suitable to construct the rest call.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Vector data format being uploaded. Following extensions are supported:
+ *
+ *
+ *
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+ public enum DataStoreExtension {
+ /** Shapefile */
+ SHP,
+ /** Properties file */
+ PROPERTIES,
+ /** H2 Database */
+ H2,
+ /** SpatiaLite Database */
+ SPATIALITE;
+
+ /**
+ * Returns a lowercase representation of the parameter value, suitable to construct the rest call.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Raster data format being uploaded. Following extensions are supported:
+ *
+ *
+ *
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+ public enum CoverageStoreExtension {
+ /** GeoTiff coverage */
+ GEOTIFF,
+ /** ImageMosaic */
+ IMAGEMOSAIC,
+ /** Geo referenced image (JPEG,PNG,TIF) */
+ WORLDIMAGE;
+
+ /**
+ * Returns a lowercase representation of the parameter value, suitable to construct the rest call.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Control if feature types are to be automatically configured upon file upload. It can take one of the three values:
+ *
+ *
+ */
+ public static enum ParameterConfigure {
+ /** Configure first feature type only (default). */
+ FIRST,
+ /** Don't configure any feature types. */
+ NONE,
+ /** Configure all feature types. */
+ ALL;
+
+ /**
+ * Returns a lowercase representation of the parameter value, suitable to construct the rest call.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Upload and publish data (vector or raster), and automatically create the associated Store if needed.
+ *
+ * This is a generic method; use {@link #createDataStore} and {@link #createCoverageStore} for vector and raster publishing respectively.
+ *
+ * @param workspace workspace where data will be published.
+ * @param dsType Store type. See {@link DataStoreType}.
+ * @param storeName Store name. Will be created if doesn't exist.
+ * @param method Publication method. See {@link UploadMethod}.
+ * @param extension Dataset format. One of {@link DataStoreExtension} for vector data, or one of {@link CoverageStoreExtension} for raster data.
+ * @param mimeType Dataset MIME type.
+ * @param uri The data location. A local path for {@link UploadMethod#FILE}, a server path for {@link UploadMethod#EXTERNAL}, or a URL for
+ * {@link UploadMethod#URL}.
+ * @param configure Indicate if associated feature types will be automatically configured. See {@link ParameterConfigure}.
+ * @param params Other parameters to be included in request, such as "update", "charset" or "coverageName". See GeoServer REST documentation for
+ * details: dataStore and coverageStore operations.
+ * @return {@code true} if the store was successfully created.
+ * @throws FileNotFoundException if local file does not exist when using the {@link UploadMethod#FILE} method.
+ * @throws IllegalArgumentException if any of the mandatory {@code workspace}, {@code dsType}, {@code storeName}, {@code method},
+ * {@code extension}, {@code mimeType} or {@code uri} parameters are {@code null}.
+ */
+ private boolean createStore(String workspace, StoreType dsType, String storeName,
+ UploadMethod method, Enum extension, String mimeType, URI uri,
+ ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException,
+ IllegalArgumentException {
+ if (workspace == null || dsType == null || storeName == null || method == null
+ || extension == null || mimeType == null || uri == null) {
+ throw new IllegalArgumentException("Null argument");
+ }
+ StringBuilder sbUrl = new StringBuilder(restURL).append("/rest/workspaces/")
+ .append(workspace).append("/").append(dsType).append("/").append(storeName)
+ .append("/").append(method).append(".").append(extension);
+
+ if (configure != null) {
+ sbUrl.append("?configure=").append(configure);
+ if (params != (NameValuePair[]) null) {
+ final String paramString = appendParameters(params);
+ if (!paramString.isEmpty()) {
+ sbUrl.append("&").append(paramString);
+ }
+ }
+ }
+
+ String sentResult = null;
+
+ if (method.equals(UploadMethod.FILE)) {
+ final File file = new File(uri);
+ if (!file.exists())
+ throw new FileNotFoundException("unable to locate file: " + file);
+ sentResult = HTTPUtils.put(sbUrl.toString(), file, mimeType, gsuser, gspass);
+ } else if (method.equals(UploadMethod.EXTERNAL)) {
+ sentResult = HTTPUtils.put(sbUrl.toString(), uri.toString(), mimeType, gsuser, gspass);
+ } else if (method.equals(UploadMethod.URL)) {
+ // TODO check
+ sentResult = HTTPUtils.put(sbUrl.toString(), uri.toString(), mimeType, gsuser, gspass);
+ }
+
+ if (sentResult != null) {
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("Store successfully created using ( " + uri + " )");
+ return true;
+ } else {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("Error in creating store using: " + uri);
+ return false;
+ }
+
+ }
+
+ /**
+ * Upload and publish vector data, and automatically create the associated DataStore if needed.
+ *
+ * Note that this is same as {@link #createStore} but specific for vector data (that is, {@code dsType} being {@link DataStoreType#DATASTORES}).
+ *
+ * @param workspace workspace where data will be published.
+ * @param storeName DataStore name. Will be created if doesn't exist.
+ * @param method Publication method. See {@link UploadMethod}.
+ * @param extension Dataset format. One of {@link DataStoreExtension}.
+ * @param mimeType Dataset MIME type.
+ * @param uri The data location. A local path for {@link UploadMethod#FILE}, a server path for {@link UploadMethod#EXTERNAL}, or a URL for
+ * {@link UploadMethod#URL}.
+ * @param configure Indicate if associated feature types will be automatically configured. See {@link ParameterConfigure}.
+ * @param params Other parameters to be included in request, such as "update" or "charset". See GeoServer REST documentation for details: dataStore operations.
+ * @return {@code true} if the store was successfully created.
+ * @throws FileNotFoundException if local file does not exist when using the {@link UploadMethod#FILE} method.
+ * @throws IllegalArgumentException if any of the mandatory {@code workspace}, {@code storeName}, {@code method}, {@code extension},
+ * {@code mimeType} or {@code uri} parameters are {@code null}.
+ */
+ private boolean createDataStore(String workspace, String storeName, UploadMethod method,
+ DataStoreExtension extension, String mimeType, URI uri, ParameterConfigure configure,
+ NameValuePair... params) throws FileNotFoundException, IllegalArgumentException {
+ return createStore(workspace, StoreType.DATASTORES, storeName, method, extension, mimeType,
+ uri, configure, params);
+ }
+
+ /**
+ * Upload and publish raster data, and automatically create the associated CoverageStore if needed.
+ *
+ * Note that this is same as {@link #createStore} but specific for raster data (that is, {@code dsType} being {@link DataStoreType#COVERAGESTORES}
+ * ).
+ *
+ * @param workspace workspace where data will be published.
+ * @param storeName CoverageStore name. Will be created if doesn't exist.
+ * @param method Publication method. See {@link UploadMethod}.
+ * @param extension Dataset format. One of {@link CoverageStoreExtension}.
+ * @param mimeType Dataset MIME type.
+ * @param uri The data location. A local path for {@link UploadMethod#FILE}, a server path for {@link UploadMethod#EXTERNAL}, or a URL for
+ * {@link UploadMethod#URL}.
+ * @param configure Indicate if associated feature types will be automatically configured. See {@link ParameterConfigure}.
+ * @param params Other parameters to be included in request, such as "coverageName". See GeoServer REST documentation for details: coverageStore operations.
+ * @return {@code true} if the store was successfully created.
+ * @throws FileNotFoundException if local file does not exist when using the {@link UploadMethod#FILE} method.
+ * @throws IllegalArgumentException if any of the mandatory {@code workspace}, {@code storeName}, {@code method}, {@code extension},
+ * {@code mimeType} or {@code uri} parameters are {@code null}.
+ */
+ private boolean createCoverageStore(String workspace, String storeName, UploadMethod method,
+ CoverageStoreExtension extension, String mimeType, URI uri,
+ ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException,
+ IllegalArgumentException {
+ return createStore(workspace, StoreType.COVERAGESTORES, storeName, method, extension,
+ mimeType, uri, configure, params);
+ }
+
+ /**
+ * Create a PostGIS datastore.
+ *
+ * @deprecated Will be deleted in next version 1.5.x, use {@link GeoServerRESTDatastoreManager} instead.
+ *
+ * @param workspace Name of the workspace to contain the database. This will also be the prefix of any layer names created from tables in the
+ * database.
+ * @param datastoreEncoder the set of parameters to be set to the datastore (including connection params).
+ *
+ * @return true if the PostGIS datastore has been successfully created, false otherwise
+ */
+ public boolean createPostGISDatastore(String workspace,
+ GSPostGISDatastoreEncoder datastoreEncoder) {
+ String sUrl = restURL + "/rest/workspaces/" + workspace + "/datastores/";
+ String xml = datastoreEncoder.toString();
+ String result = HTTPUtils.postXml(sUrl, xml, gsuser, gspass);
+ return result != null;
+ }
+
+ /**
+ * @deprecated Will be removed in the next release.
+ */
+ public boolean publishDBLayer(String workspace, String storename, String layername, String srs,
+ String defaultStyle) {
+
+ final GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder();
+
+ fte.setProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED);
+ fte.addKeyword("KEYWORD");
+ fte.setTitle(layername);
+ fte.setName(layername);
+ fte.setSRS(srs); // srs=null?"EPSG:4326":srs);
+ final GSLayerEncoder layerEncoder = new GSLayerEncoder();
+ layerEncoder.setDefaultStyle(defaultStyle);
+ return publishDBLayer(workspace, storename, fte, layerEncoder);
+ }
+
+ /**
+ * Publish and configure a new layer from an existing DataStore (v. gr. a layer from a DB table).
+ *
+ * @param workspace Workspace name where DataStore is.
+ * @param storename DataStore name.
+ * @param fte FeatureType configuration details using a {@link GSFeatureTypeEncoder}.
+ * @return {@code true} if layer is successfully created.
+ */
+ public boolean publishDBLayer(final String workspace, final String storename,
+ final GSFeatureTypeEncoder fte, final GSLayerEncoder layerEncoder) {
+ /*
+ * This is the equivalent call with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPOST -H 'Content-type: text/xml' \ -d
+ * "
restURL + "/rest/layers/" workspace + : + layerName
+ */
+ String ftypeXml = fte.toString();
+ StringBuilder postUrl = new StringBuilder(restURL).append("/rest/workspaces/")
+ .append(workspace).append("/datastores/").append(storename).append("/featuretypes");
+
+ final String layername = fte.getName();
+ if (layername == null || layername.isEmpty()) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("GSFeatureTypeEncoder has no valid name associated, try using GSFeatureTypeEncoder.setName(String)");
+ return false;
+ }
+
+ String configuredResult = HTTPUtils.postXml(postUrl.toString(), ftypeXml, this.gsuser,
+ this.gspass);
+ boolean published = configuredResult != null;
+ boolean configured = false;
+
+ if (!published) {
+ LOGGER.warn("Error in publishing (" + configuredResult + ") " + workspace + ":"
+ + storename + "/" + layername);
+ } else {
+ LOGGER.info("DB layer successfully added (layer:" + layername + ")");
+
+ if (layerEncoder == null) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("GSLayerEncoder is null: Unable to find the defaultStyle for this layer");
+ return false;
+ }
+
+ configured = configureLayer(workspace, layername, layerEncoder);
+
+ if (!configured) {
+ LOGGER.warn("Error in configuring (" + configuredResult + ") " + workspace + ":"
+ + storename + "/" + layername);
+ } else {
+ LOGGER.info("DB layer successfully configured (layer:" + layername + ")");
+ }
+ }
+
+ return published && configured;
+ }
+
+ // ==========================================================================
+ // === SHAPEFILES
+ // ==========================================================================
+
+ /**
+ * Upload an publish a local shapefile.
+ *
+ * Accepted parameters are:
+ *
+ *
+ * @param layername the name of the layer to configure
+ * @param method {@link UploadMethod}
+ * @param fileUri the uri of the file containing the shapefile.It should be:
+ *
+ *
+ * @param srs the SRS for this shapefile. It must be an ESPG code or GeoServer will choke.
+ * @param nativeCRS the nativeCRS for this shapefile. It can be an EPSG code (for {@link ProjectionPolicy#NONE} or a WKT for
+ * {@link ProjectionPolicy#REPROJECT_TO_DECLARED}.
+ * @param policy {@link ProjectionPolicy}
+ * @param defaultStyle the default style to set (can be null).
+ * @return true if success false otherwise
+ *
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ */
+ public boolean publishShp(String workspace, String storeName, NameValuePair[] storeParams,
+ String datasetName, UploadMethod method, URI shapefile, String srs, String nativeCRS,
+ ProjectionPolicy policy, String defaultStyle) throws FileNotFoundException,
+ IllegalArgumentException {
+ if (workspace == null || storeName == null || shapefile == null || datasetName == null
+ || policy == null) {
+ throw new IllegalArgumentException("Unable to run: null parameter");
+ }
+
+ //
+ // SRS Policy Management
+ //
+ boolean srsNull = !(srs != null && srs.length() != 0);
+ boolean nativeSrsNull = !(nativeCRS != null && nativeCRS.length() != 0);
+ // if we are asking to use the reproject policy we must have the native crs
+ if (policy == ProjectionPolicy.REPROJECT_TO_DECLARED && (nativeSrsNull || srsNull)) {
+ throw new IllegalArgumentException(
+ "Unable to run: you can't ask GeoServer to reproject while not specifying a native CRS");
+ }
+
+ // if we are asking to use the NONE policy we must have the native crs.
+ if (policy == ProjectionPolicy.NONE && nativeSrsNull) {
+ throw new IllegalArgumentException(
+ "Unable to run: you can't ask GeoServer to use a native srs which is null");
+ }
+
+ // if we are asking to use the reproject policy we must have the native crs
+ if (policy == ProjectionPolicy.FORCE_DECLARED && srsNull) {
+ throw new IllegalArgumentException(
+ "Unable to run: you can't force GeoServer to use an srs which is null");
+ }
+
+ //
+ final String mimeType;
+ switch (method) {
+ case EXTERNAL:
+ case external:
+ mimeType = "text/plain";
+ break;
+ case URL: // TODO check which mime-type should be used
+ case FILE:
+ case file:
+ case url:
+ mimeType = "application/zip";
+ break;
+ default:
+ mimeType = null;
+ }
+ if (!createDataStore(workspace,
+ (storeName != null) ? storeName : FilenameUtils.getBaseName(shapefile.toString()),
+ method, DataStoreExtension.SHP, mimeType, shapefile, ParameterConfigure.NONE,
+ storeParams)) {
+ LOGGER.error("Unable to create data store for shapefile: " + shapefile);
+ return false;
+ }
+
+ // config coverage props (srs)
+ final GSFeatureTypeEncoder featureTypeEncoder = new GSFeatureTypeEncoder();
+ featureTypeEncoder.setName(datasetName);
+ featureTypeEncoder.setTitle(datasetName);
+ // set destination srs
+ if (!srsNull) {
+ featureTypeEncoder.setSRS(srs);
+ } else {
+ // this under the assumption that when the destination srs is null the nativeCRS has an EPSG one so we force them to be the same
+ featureTypeEncoder.setSRS(nativeCRS);
+ }
+ // set native srs
+ if (!nativeSrsNull) {
+ featureTypeEncoder.setNativeCRS(nativeCRS);
+ }
+ featureTypeEncoder.setProjectionPolicy(policy);
+
+ if (!createResource(workspace, StoreType.DATASTORES, storeName, featureTypeEncoder)) {
+ LOGGER.error("Unable to create a coverage store for coverage: " + shapefile);
+ return false;
+ }
+
+ // config layer props (style, ...)
+ final GSLayerEncoder layerEncoder = new GSLayerEncoder();
+ if (defaultStyle != null && !defaultStyle.isEmpty())
+ layerEncoder.setDefaultStyle(defaultStyle);
+
+ return configureLayer(workspace, datasetName, layerEncoder);
+ }
+
+ /**
+ * Publish a shapefile.
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param storeParams parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ * @param layername the name of the layer to configure
+ * @param method {@link UploadMethod}
+ * @param fileUri the uri of the file containing the shapefile.It should be:
+ *
+ *
+ * @param srs the SRS for this shapefile. It must be an ESPG code or GeoServer will choke. Notice that we can only use
+ * {@link ProjectionPolicy#FORCE_DECLARED}.
+ * @param policy {@link ProjectionPolicy}
+ * @param defaultStyle the default style to set (can be null).
+ * @return true if success false otherwise
+ *
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ * @deprecated use {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, String)} instead as the behaviour of
+ * this method is misleading as it allows you to use wrong ProjectionPolicy values.
+ */
+ public boolean publishShp(String workspace, String storeName, NameValuePair[] storeParams,
+ String datasetName, UploadMethod method, URI shapefile, String srs,
+ ProjectionPolicy policy, String defaultStyle) throws FileNotFoundException,
+ IllegalArgumentException {
+ return publishShp(workspace, storeName, storeParams, datasetName, method, shapefile, srs,
+ null, policy, defaultStyle);
+ }
+
+ /**
+ * Publish a shapefile.
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param storeParams parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ * @param layername the name of the layer to configure
+ * @param method {@link UploadMethod}
+ * @param fileUri the uri of the file containing the shapefile.It should be:
+ *
+ *
+ * @param srs the SRS for this shapefile. It must be an ESPG code or GeoServer will choke.
+ * @param defaultStyle the default style to set (can be null).
+ * @return true if success false otherwise
+ *
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ */
+ public boolean publishShp(String workspace, String storeName, NameValuePair[] storeParams,
+ String datasetName, UploadMethod method, URI shapefile, String srs, String defaultStyle)
+ throws FileNotFoundException, IllegalArgumentException {
+ return publishShp(workspace, storeName, storeParams, datasetName, method, shapefile, srs,
+ null, ProjectionPolicy.FORCE_DECLARED, defaultStyle);
+ }
+
+ /**
+ * Publish a zipped shapefile.
+ *
+ * @see {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, ProjectionPolicy, String)}
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param layerName the name of the layer to configure
+ * @param zipFile The zipped file to publish
+ * @param srs the srs for this shapefile. It will be forced to use this one in GeoServer using {@link ProjectionPolicy#FORCE_DECLARED}.
+ * @param defaultStyle the default style to set (can be null).
+ *
+ * @return {@code true} if the operation completed successfully
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ */
+ public boolean publishShp(String workspace, String storename, String layerName, File zipFile,
+ String srs, String defaultStyle) throws FileNotFoundException, IllegalArgumentException {
+
+ return publishShp(workspace, storename, (NameValuePair[]) null, layerName,
+ UploadMethod.FILE, zipFile.toURI(), srs, defaultStyle);
+ }
+
+ /**
+ * Publish a zipped shapefile forcing the srs to the one provided.
+ *
+ * @see {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, ProjectionPolicy, String)}
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param layername the name of the layer to configure
+ * @param zipFile The zipped file to publish
+ * @param srs the CRS for this shapefile. It must be an EPSG CODE !
+ *
+ * @return {@code true} if the operation completed successfully.
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ */
+ public boolean publishShp(String workspace, String storename, String layername, File zipFile,
+ String srs) throws FileNotFoundException {
+ return publishShp(workspace, storename, (NameValuePair[]) null, layername,
+ UploadMethod.FILE, zipFile.toURI(), srs, null);
+ }
+
+ /**
+ * Publish a zipped shapefile.
+ *
+ * @see {@link #publishShp(String, String, NameValuePair[], String, UploadMethod, URI, String, ProjectionPolicy, String)}
+ *
+ * @param workspace the name of the workspace to use
+ * @param storename the name of the store to create
+ * @param layername the name of the layer to configure
+ * @param zipFile the zip file containing the shapefile
+ * @param srs the shapefile srs. This must be an EPSG Codefor this code to work!
+ * @param params parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ * @return {@code true} if the operation completed successfully.
+ * @throws FileNotFoundException if file to upload is not found
+ * @throws IllegalArgumentException if any of the mandatory arguments are {@code null}.
+ */
+ public boolean publishShp(String workspace, String storename, String layername, File zipFile,
+ String srs, NameValuePair... params) throws FileNotFoundException,
+ IllegalArgumentException {
+
+ return publishShp(workspace, storename, params, layername, UploadMethod.FILE,
+ zipFile.toURI(), srs, null);
+ }
+
+ /**
+ * Publish a collection of shapefiles.
+ *
+ *
+ * @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, StoreType.DATASTORES, storeName, method,
+ DataStoreExtension.SHP, mime, resource, ParameterConfigure.ALL,
+ new NameValuePair[0]);
+ }
+
+ // ==========================================================================
+ // === COVERAGES
+ // ==========================================================================
+
+ /**
+ * Controls how existing data is handled when the file is PUT into a datastore that (a) already exists and (b) already contains a schema that
+ * matches the content of the file. It can take one of the two values:
+ *
+ *
+ *
+ * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+ */
+ public static enum ParameterUpdate {
+ /** Data being uploaded is appended to the existing data. */
+ APPEND,
+ /** Data being uploaded replaces any existing data. */
+ OVERWRITE;
+
+ /**
+ * Returns a lowercase representation of the parameter. Useful when constructing the REST request.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Represents the format used to GET, PUT or POST information via REST. For example consider the resource "foo". To request a representation of
+ * foo as XML the request uri would end with "foo.xml". To request as JSON the request uri would end with "foo.json". When no format is specified
+ * the server will use its own internal format, usually html.
+ *
+ *
+ */
+ public enum Format {
+ XML, JSON, HTML, SLD;
+
+ /**
+ * Gets the mime type from a format.
+ *
+ * @param f the format key.
+ * @return The content-type (mime), or {@code null} if not in the enum.
+ */
+ public static String getContentType(Format f) {
+ switch (f) {
+ case XML:
+ return "application/xml";
+ case HTML:
+ return "application/html";
+ case JSON:
+ return "application/json";
+ case SLD:
+ return "application/vnd.ogc.sld+xml";
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the mime type from a format.
+ *
+ * @param f the format key.
+ * @return The content-type (mime), or {@code null} if not in the enum.
+ */
+ public String getContentType() {
+ return getContentType(this);
+ }
+
+ /**
+ * Returns a lowercase representation of the parameter. Useful when constructing the REST request.
+ */
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ /**
+ * Upload and publish a raster file.
+ *
+ * @param workspace Workspace to use
+ * @param coveragestore Name of the coveragestore
+ * @param file file to upload
+ * @param configure Configure parameter. See {@link ParameterConfigure}. It can be null.
+ * @param params parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ * @return true if the operation completed successfully.
+ */
+ private boolean publishCoverage(String workspace, String coveragestore,
+ CoverageStoreExtension extension, String mimeType, File file,
+ ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException {
+ /*
+ * This is an example with cUrl:
+ *
+ * {@code curl -u admin:geoserver -XPUT -H 'Content-type: application/zip' \ --data-binary @$ZIPFILE \ http://$GSIP:$GSPORT/$SERVLET
+ * /rest/workspaces/$WORKSPACE/coveragestores /$COVERAGESTORE/file.worldimage
+ */
+ return createCoverageStore(workspace, coveragestore, UploadMethod.FILE, extension,
+ mimeType, file.toURI(), configure, params);
+ }
+
+ /**
+ * Publish a raster file local to the server.
+ *
+ * @param workspace Workspace to use
+ * @param coveragestore Name of the coveragestore
+ * @param file absolute path to the file location in the server
+ * @param configure Configure parameter. It may be null.
+ * @param update Accepted parameters are:
+ *
+ *
+ * @see #{@link ParameterConfigure}
+ * @return true if the operation completed successfully.
+ * @throws IllegalArgumentException
+ * @throws FileNotFoundException
+ */
+ private boolean publishExternalCoverage(String workspace, String coveragestore,
+ CoverageStoreExtension extension, String mimeType, File file,
+ ParameterConfigure configure, ParameterUpdate update) throws FileNotFoundException,
+ IllegalArgumentException {
+ /*
+ * Curl example:
+ *
+ * {@code curl -u admin:geoserver -XPUT -H 'Content-type: application/zip' \
+ *
+ * --data-binary @$ZIPFILE \
+ *
+ * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores /$COVERAGESTORE/file.worldimage
+ */
+ return createCoverageStore(
+ workspace,
+ coveragestore,
+ UploadMethod.EXTERNAL,
+ extension,
+ mimeType,
+ file.toURI(),
+ configure,
+ (update != null) ? new NameValuePair[] { new NameValuePair("update", update
+ .toString()) } : (NameValuePair[]) null);
+ }
+
+ // ==========================================================================
+ // === GEOTIFF
+ // ==========================================================================
+
+ /**
+ * Upload and publish a GeoTIFF image.
+ *
+ * @param workspace Workspace to use
+ * @param storeName The store name to be used or created.
+ * @param geotiff The GeoTIFF file.
+ * @return true if success.
+ * @throws FileNotFoundException if GeoTIFF file does not exist.
+ */
+ public boolean publishGeoTIFF(String workspace, String storeName, File geotiff)
+ throws FileNotFoundException {
+ return publishCoverage(workspace, storeName, CoverageStoreExtension.GEOTIFF,
+ "image/geotiff", geotiff, ParameterConfigure.FIRST, (NameValuePair[]) null);
+ }
+
+ /**
+ * Upload and publish a GeoTIFF 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 geotiff file to upload
+ * @return true if the operation completed successfully.
+ * @throws FileNotFoundException if file does not exists
+ * @throws IllegalArgumentException if workspace or geotiff are null
+ */
+ public boolean publishGeoTIFF(final String workspace, final String storeName,
+ final String coverageName, final File geotiff) throws FileNotFoundException,
+ IllegalArgumentException {
+ if (workspace == null || geotiff == null)
+ throw new IllegalArgumentException("Unable to proceed, some arguments are null");
+
+ return publishCoverage(
+ workspace,
+ (storeName != null) ? storeName : FilenameUtils.getBaseName(geotiff
+ .getAbsolutePath()), CoverageStoreExtension.GEOTIFF, "image/geotiff",
+ geotiff, ParameterConfigure.FIRST,
+ (coverageName != null) ? new NameValuePair[] { new NameValuePair("coverageName",
+ coverageName) } : (NameValuePair[]) null);
+ }
+
+ /**
+ * Same as {@link #publishGeoTIFF(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 publishGeoTIFF(String workspace, String storeName, String resourceName,
+ File geotiff, String srs, ProjectionPolicy policy, String defaultStyle)
+ throws FileNotFoundException, IllegalArgumentException {
+ return publishGeoTIFF(workspace, storeName, resourceName, geotiff, srs, policy,
+ defaultStyle, null);
+ }
+
+ /**
+ * Upload and publish a GeoTIFF 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 geotiff 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 geotiff are null
+ *
+ */
+ public boolean publishGeoTIFF(String workspace, String storeName, String coverageName,
+ File geotiff, String srs, ProjectionPolicy policy, String defaultStyle, double[] bbox)
+ throws FileNotFoundException, IllegalArgumentException {
+ if (workspace == null || storeName == null || geotiff == 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(geotiff
+ .getAbsolutePath()), UploadMethod.FILE, CoverageStoreExtension.GEOTIFF,
+ "image/geotiff", geotiff.toURI(), ParameterConfigure.NONE, (NameValuePair[]) null)) {
+ LOGGER.error("Unable to create coverage store for coverage: " + geotiff);
+ return false;
+ }
+
+ // config coverage props (srs)
+ final GSCoverageEncoder coverageEncoder = new GSCoverageEncoder();
+ coverageEncoder.setName(coverageName);
+ coverageEncoder.setTitle(coverageName);
+ coverageEncoder.setSRS(srs);
+ coverageEncoder.setProjectionPolicy(policy);
+ 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: " + geotiff);
+ return false;
+ }
+
+ // config layer props (style, ...)
+ final GSLayerEncoder layerEncoder = new GSLayerEncoder();
+ layerEncoder.setDefaultStyle(defaultStyle);
+
+ return configureLayer(workspace, coverageName, layerEncoder);
+ }
+
+ /**
+ * Publish a GeoTiff already in a filesystem readable by GeoServer.
+ *
+ * @param workspace an existing workspace
+ * @param storeName the coverageStore to be created
+ * @param geotiff the geoTiff 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 publishExternalGeoTIFF(String workspace, String storeName, File geotiff,
+ String coverageName, String srs, ProjectionPolicy policy, String defaultStyle)
+ throws FileNotFoundException, IllegalArgumentException {
+ if (workspace == null || storeName == null || geotiff == 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 publishExternalGeoTIFF(workspace, storeName, geotiff, coverageEncoder, layerEncoder) != null ? true
+ : false;
+ }
+
+ /**
+ * Publish a GeoTiff already in a filesystem readable by GeoServer.
+ *
+ * @param workspace an existing workspace
+ * @param storeName the coverageStore to be created
+ * @param geotiff the geoTiff 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 publishExternalGeoTIFF(final String workspace, final String storeName,
+ final File geotiff, final GSCoverageEncoder coverageEncoder,
+ final GSLayerEncoder layerEncoder) throws IllegalArgumentException,
+ FileNotFoundException {
+
+ if (workspace == null || geotiff == 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.GEOTIFF, "text/plain", geotiff, 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;
+ }
+
+ // ==========================================================================
+ // === WORLDIMAGE
+ // ==========================================================================
+
+ /**
+ * Publish a zipped worldimage file. It is assumed that the the zip-file contain the *.prj to set the srs.
+ *
+ * @param workspace Workspace to use
+ * @param coveragestore Name of the coveragestore
+ * @param zipFile zip file to upload
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishWorldImage(String workspace, String coveragestore, File zipFile)
+ throws FileNotFoundException {
+ return publishWorldImage(workspace, coveragestore, zipFile, ParameterConfigure.FIRST,
+ (NameValuePair) null);
+ }
+
+ /**
+ * Publish a zipped worldimage file. It is assumed that the the zip-file contain the *.prj to set the srs.
+ *
+ * @param workspace Workspace to use
+ * @param coveragestore Name of the coveragestore
+ * @param zipFile zip file to upload
+ * @param configure Configure parameter. See {@link ParameterConfigure}. It can be null.
+ * @param params parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishWorldImage(String workspace, String coveragestore, File zipFile,
+ ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException {
+ return publishCoverage(workspace, coveragestore, CoverageStoreExtension.WORLDIMAGE,
+ "application/zip", zipFile, configure, params);
+ }
+
+ // ==========================================================================
+ // === MOSAIC
+ // ==========================================================================
+
+ /**
+ * Publish imagemosaic as zip file.
+ *
+ * @param workspace Workspace to use
+ * @param storeName Name of the coveragestore
+ * @param zipFile file to upload
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishImageMosaic(String workspace, String storeName, File zipFile)
+ throws FileNotFoundException {
+ return publishCoverage(workspace, storeName, CoverageStoreExtension.IMAGEMOSAIC,
+ "application/zip", zipFile, ParameterConfigure.FIRST, (NameValuePair[]) null);
+ }
+
+ /**
+ * Publish imagemosaic as zip file.
+ *
+ * @param workspace Workspace to use
+ * @param storeName Name of the coveragestore
+ * @param zipFile file to upload
+ * @param configure Configure parameter. See {@link ParameterConfigure}. It can be null.
+ * @param params parameters to append to the url (can be null).
+ * Accepted parameters are:
+ *
+ *
+ *
+ * @return true if the operation completed successfully.
+ */
+ public boolean publishImageMosaic(String workspace, String storeName, File zipFile,
+ ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException {
+ return publishCoverage(workspace, storeName, CoverageStoreExtension.IMAGEMOSAIC,
+ "application/zip", zipFile, configure, params);
+ }
+
+ /**
+ * Publish a Mosaic from a filesystem currently readable by GeoServer.
+ *
+ * @param workspace an existing workspace
+ * @param storeName the name of the coverageStore to be created
+ * @param mosaicDir the directory where the raster images are located
+ * @param configure a specify if a coverage should be configured
+ *
+ * @return true if the operation completed successfully.
+ * @throws FileNotFoundException
+ */
+ public RESTCoverageStore createExternaMosaicDatastore(String workspace, String storeName,
+ File mosaicDir, ParameterConfigure configure, ParameterUpdate update)
+ throws FileNotFoundException {
+
+ /*
+ * Carlo (23 Nov 2011): commented out since this directory should be readable by target GeoServer not the calling client!
+ */
+ if (!mosaicDir.isDirectory()) {
+ if (LOGGER.isWarnEnabled())
+ LOGGER.warn("Directory '"
+ + mosaicDir
+ + "' not exists locally. Continue: please check existance on the remote server.");
+ }
+
+ String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName
+ + "/external.imagemosaic?configure=" + configure.toString() + "&update="
+ + update.toString();
+ String sendResult = HTTPUtils.put(sUrl, mosaicDir.toURI().toString(), "text/plain", gsuser,
+ gspass);
+ return RESTCoverageStore.build(sendResult);
+ }
+
+ /**
+ * Publish a Mosaic already in a filesystem readable by GeoServer.
+ *
+ * @param workspace an existing workspace
+ * @param storeName the name of the coverageStore to be created
+ * @param mosaicDir the directory where the raster images are located
+ * @param srs the coverage declared SRS
+ * @param defaultStyle may be null
+ *
+ * @return true if the operation completed successfully.
+ *
+ * @throws FileNotFoundException
+ */
+ public boolean publishExternalMosaic(String workspace, String storeName, File mosaicDir,
+ String srs, String defaultStyle) throws FileNotFoundException {
+
+ final GSCoverageEncoder coverageEncoder = new GSCoverageEncoder();
+ coverageEncoder.setSRS(srs);
+ final String name = FilenameUtils.getBaseName(mosaicDir.getName());
+ coverageEncoder.setName(name);
+
+ final GSLayerEncoder layerEncoder = new GSLayerEncoder();
+ layerEncoder.setDefaultStyle(defaultStyle);
+
+ return publishExternalMosaic(workspace, storeName, mosaicDir, coverageEncoder, layerEncoder);
+ }
+
+ /**
+ * @deprecated use {@link #publishExternalMosaic(String, String, File, GSCoverageEncoder, GSLayerEncoder)}
+ */
+ public boolean createExternalMosaic(String workspace, String storeName, File mosaicDir,
+ GSCoverageEncoder coverageEncoder, GSLayerEncoder layerEncoder)
+ throws FileNotFoundException {
+ return publishExternalMosaic(workspace, storeName, mosaicDir, coverageEncoder, layerEncoder);
+ }
+
+ /**
+ * Publish a Mosaic already in a filesystem readable by GeoServer.
+ *
+ * @param workspace an existing workspace
+ * @param storeName the name of the coverageStore to be created
+ * @param mosaicDir the directory where the raster images are located
+ * @param coverageEncoder the set of parameters to be set to the coverage (bbox, srs, ...)
+ * @param layerEncoder the set of parameters to be set to the layer (defaultstyle, wmspath, ...)
+ *
+ * @return true if the operation completed successfully.
+ * @throws FileNotFoundException
+ */
+ public boolean publishExternalMosaic(String workspace, final String storeName, File mosaicDir,
+ GSCoverageEncoder coverageEncoder, GSLayerEncoder layerEncoder)
+ throws FileNotFoundException, IllegalArgumentException {
+
+ if (coverageEncoder == null) {
+ throw new IllegalArgumentException("no coverageEncoder provided for mosaic "
+ + mosaicDir);
+ }
+
+ if (layerEncoder == null) {
+ throw new IllegalArgumentException("no layerEncoder provided for " + mosaicDir);
+ }
+
+ RESTCoverageStore store = createExternaMosaicDatastore(workspace, storeName, mosaicDir,
+ ParameterConfigure.NONE, ParameterUpdate.OVERWRITE);
+
+ if (store == null) {
+ return false;
+ }
+
+ // override name to match the FIRST configured coverage
+ String coverageName = coverageEncoder.getName();
+ if (coverageName==null){
+ coverageName=mosaicDir.getName();
+ coverageEncoder.setName(coverageName);
+ }
+ if (!createCoverage(workspace, storeName, coverageEncoder)) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("Unable to create a coverage for the store:" + coverageName);
+ return false;
+ }
+ if (!configureLayer(workspace, coverageName, layerEncoder)) {
+ if (LOGGER.isErrorEnabled())
+ LOGGER.error("Unable to configure the Layer for the coverage:" + coverageName);
+ return false;
+ }
+ return true;
+ }
+
+ // ==========================================================================
+ // === REMOVING THINGS
+ // ==========================================================================
+
+ /**
+ * Remove the Coverage configuration from GeoServer.
+ * true if the call succeeds or false otherwise.
+ */
+ public boolean harvestExternal(String workspace, String coverageStore, String format,
+ String path) {
+ try {
+ GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
+ new URL(restURL), gsuser, gspass);
+ return manager.harvestExternal(workspace, coverageStore, format, path);
+ } catch (IllegalArgumentException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ } catch (MalformedURLException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Create a new ImageMosaic with the provided configuration provided as a zip file.
+ *
+ * true if the call succeeds or false otherwise.
+ * @since geoserver-2.4.0, geoserver-mng-1.6.0
+ */
+ public boolean createImageMosaic(String workspace, String coverageStore, String path) {
+ return createImageMosaic(workspace, coverageStore, path, ConfigureCoveragesOption.ALL);
+ }
+
+ /**
+ * Create a new ImageMosaic with the provided configuration provided as a zip file.
+ *
+ * true if the call succeeds or false otherwise.
+ * @since geoserver-2.4.0, geoserver-mng-1.6.0
+ */
+ public boolean createImageMosaic(String workspace, String coverageStore, String path, ConfigureCoveragesOption configureOpt) {
+ // checks
+ checkString(workspace);
+ checkString(coverageStore);
+ checkString(path);
+ final File zipFile= new File(path);
+ if(!zipFile.exists()||!zipFile.isFile()||!zipFile.canRead()){
+ throw new IllegalArgumentException("The provided pathname does not point to a valide zip file: "+path);
+ }
+ // is it a zip?
+ ZipFile zip=null;
+ try{
+ zip= new ZipFile(zipFile);
+ zip.getName();
+ }catch (Exception e) {
+ LOGGER.trace(e.getLocalizedMessage(),e.getStackTrace());
+ throw new IllegalArgumentException("The provided pathname does not point to a valide zip file: "+path);
+ }finally{
+ if(zip!=null){
+ try {
+ zip.close();
+ } catch (IOException e) {
+ // swallow
+ LOGGER.trace(e.getLocalizedMessage(),e.getStackTrace());
+ }
+ }
+ }
+
+ // create URL
+ StringBuilder ss=HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/",
+ coverageStore, "/", UploadMethod.EXTERNAL.toString(), ".imagemosaic");
+ switch(configureOpt){
+ case ALL:
+ break;
+ case NONE:
+ ss.append("?configure=none");
+ break;
+ default:
+ throw new IllegalArgumentException("Unrecognized COnfigureOption: "+configureOpt);
+ }
+ String sUrl = ss.toString();
+
+ // POST request
+ String result = HTTPUtils.put(sUrl, zipFile, "application/zip", gsuser, gspass);
+ return result != null;
+ }
+
+ /**
+ * Remove a granule from a structured coverage by id.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranuleById(final String workspace, String coverageStore, String coverage,
+ String granuleId) {
+ try {
+ GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
+ new URL(restURL), gsuser, gspass);
+ return manager.removeGranuleById(workspace, coverageStore, coverage, granuleId);
+ } catch (IllegalArgumentException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ } catch (MalformedURLException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove granules from a structured coverage, by providing a CQL filter.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranulesByCQL(final String workspace, String coverageStore,
+ String coverage, String filter) throws UnsupportedEncodingException {
+ try {
+ GeoServerRESTStructuredGridCoverageReaderManager manager = new GeoServerRESTStructuredGridCoverageReaderManager(
+ new URL(restURL), gsuser, gspass);
+ return manager.removeGranulesByCQL(workspace, coverageStore, coverage, filter);
+ } catch (IllegalArgumentException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ } catch (MalformedURLException e) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(e.getLocalizedMessage(), e);
+ }
+ }
+ return false;
+
+ }
+
+ /**
+ * Check the provided string for not being null or empty.
+ *
+ *