diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java index 813c46d..895fb30 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -26,10 +26,11 @@ package it.geosolutions.geoserver.rest; import it.geosolutions.geoserver.rest.decoder.RESTCoverageList; import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; import it.geosolutions.geoserver.rest.encoder.GSPostGISDatastoreEncoder; -import it.geosolutions.geoserver.rest.encoder.GSWorkspaceEncoder; 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; @@ -38,825 +39,1320 @@ import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; +import java.util.Iterator; import org.apache.commons.io.FilenameUtils; import org.apache.log4j.Level; import org.apache.log4j.Logger; -import org.apache.log4j.Priority; /** * Connect to a GeoServer instance to publish or modify data. *

* There are no modifiable instance fields, so all the calls are thread-safe. - * + * * @author ETj (etj at geo-solutions.it) */ public class GeoServerRESTPublisher { - private static final Logger LOGGER = Logger.getLogger(GeoServerRESTPublisher.class); - private final String restURL; - private final String gsuser; - private final String gspass; + private static final Logger LOGGER = Logger + .getLogger(GeoServerRESTPublisher.class); + private final String restURL; + private final String gsuser; + private final String gspass; - /** - * Creates a GeoServerRESTPublisher for a given GeoServer instance - * with the given auth credentials. - * - * @param restURL the base GeoServer URL (e.g.: http://localhost:8080/geoserver) - * @param username username auth credential - * @param password password auth credential - */ - public GeoServerRESTPublisher(String restURL, String username, String password) { - this.restURL = HTTPUtils.decurtSlash(restURL); - this.gsuser = username; - this.gspass = password; - } + /** + * Creates a GeoServerRESTPublisher for a given GeoServer instance + * with the given auth credentials. + * + * @param restURL + * the base GeoServer URL (e.g.: + * http://localhost:8080/geoserver) + * @param username + * username auth credential + * @param password + * password auth credential + */ + public GeoServerRESTPublisher(String restURL, String username, + String password) { + this.restURL = HTTPUtils.decurtSlash(restURL); + this.gsuser = username; + this.gspass = password; + } - //========================================================================== - //=== WORKSPACES - //========================================================================== + // ========================================================================== + // === WORKSPACES + // ========================================================================== - /** - * Create a new Workspace - * - * @param workspace The name of the new workspace. - * - *

- * This is the equivalent call with cUrl: - *

{@code curl -u admin:geoserver -XPOST \
-     *      -H 'Content-type: text/xml' \
-     *      -d "$WORKSPACE" \
-     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces
-     * }
- */ - public boolean createWorkspace(final String workspace) { - final String sUrl = restURL + "/rest/workspaces"; - final GSWorkspaceEncoder wsenc = new GSWorkspaceEncoder(workspace); - final String wsxml = wsenc.toString(); - final String result = HTTPUtils.postXml(sUrl, wsxml, gsuser, gspass); - return result != null; - } + /** + * Create a new Workspace + * + * @param workspace + * The name of the new workspace. + * + *

+ * This is the equivalent call with cUrl: + * + *

+	 * {@code curl -u admin:geoserver -XPOST \
+	 *      -H 'Content-type: text/xml' \
+	 *      -d "$WORKSPACE" \
+	 *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces
+	 * }
+	 * 
+ */ + public boolean createWorkspace(final String workspace) { + final String sUrl = restURL + "/rest/workspaces"; + final GSWorkspaceEncoder wsenc = new GSWorkspaceEncoder(workspace); + final String wsxml = wsenc.toString(); + final String result = HTTPUtils.postXml(sUrl, wsxml, gsuser, gspass); + return result != null; + } - //========================================================================== - //=== STYLES - //========================================================================== + // ========================================================================== + // === STYLES + // ========================================================================== - /** - * Store and publish an SLD. - *

- * This is the equivalent call with cUrl: - *

-     * {@code curl -u admin:geoserver -XPOST \
-     *      -H 'Content-type: application/vnd.ogc.sld+xml' \
-     *      -d @$FULLSLD \
-     *      http://$GSIP:$GSPORT/$SERVLET/rest/styles}
- * - * @param sldBody the SLD document as an XML String. - * - * @return true if the operation completed successfully. - */ - public boolean publishStyle(String sldBody) { - String sUrl = restURL + "/rest/styles"; - String result = HTTPUtils.post(sUrl, sldBody, "application/vnd.ogc.sld+xml", gsuser, gspass); - return result != null; - } + /** + * Store and publish an SLD. + *

+ * This is the equivalent call with cUrl: + * + *

+	 * {@code curl -u admin:geoserver -XPOST \
+	 *      -H 'Content-type: application/vnd.ogc.sld+xml' \
+	 *      -d @$FULLSLD \
+	 *      http://$GSIP:$GSPORT/$SERVLET/rest/styles}
+	 * 
+ * + * @param sldBody + * the SLD document as an XML String. + * + * @return true if the operation completed successfully. + */ + public boolean publishStyle(String sldBody) { + String sUrl = restURL + "/rest/styles"; + String result = HTTPUtils.post(sUrl, sldBody, + "application/vnd.ogc.sld+xml", gsuser, gspass); + return result != null; + } - /** - * Store and publish an SLD. - * - * @param sldFile the File containing the SLD document. - * - * @return true if the operation completed successfully. - */ - public boolean publishStyle(File sldFile) { - return publishStyle(sldFile, null); - } + /** + * Store and publish an SLD. + * + * @param sldFile + * the File containing the SLD document. + * + * @return true if the operation completed successfully. + */ + public boolean publishStyle(File sldFile) { + return publishStyle(sldFile, null); + } - /** - * Store and publish an SLD, 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) { - String sUrl = restURL + "/rest/styles"; - if (name != null) { - sUrl += "?name=" + encode(name); - } - LOGGER.debug("POSTing new style " + name + " to " + sUrl); - String result = HTTPUtils.post(sUrl, sldFile, "application/vnd.ogc.sld+xml", gsuser, gspass); - return result != null; - } + /** + * Store and publish an SLD, 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) { + String sUrl = restURL + "/rest/styles"; + if (name != null) { + sUrl += "?name=" + encode(name); + } + LOGGER.debug("POSTing new style " + name + " to " + sUrl); + String result = HTTPUtils.post(sUrl, sldFile, + "application/vnd.ogc.sld+xml", gsuser, gspass); + return result != null; + } - /** - * 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) { - styleName = styleName.replaceAll(":", "_"); // ??? - styleName = encode(styleName); // spaces may - String sUrl = restURL + "/rest/styles/" + styleName + "?purge=true"; - return HTTPUtils.delete(sUrl, gsuser, gspass); - } + /** + * 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) { + styleName = styleName.replaceAll(":", "_"); // ??? + styleName = encode(styleName); // spaces may + String sUrl = restURL + "/rest/styles/" + styleName + "?purge=true"; + return HTTPUtils.delete(sUrl, gsuser, gspass); + } - //========================================================================== - //=== DATASTORE - //========================================================================== + // ========================================================================== + // === DATASTORE + // ========================================================================== - /** - * Create a PostGIS datastore. - * - * @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; - } + /** + * Create a PostGIS datastore. + * + * @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; + } - //========================================================================== - //=== SHAPEFILES - //========================================================================== + // ========================================================================== + // === SHAPEFILES + // ========================================================================== - /** - * Publish a zipped shapefile. - *
The CRS will be forced to EPSG:4326. - * - * @param workspace - * @param storename - * @param layername - * @param zipFile - * @return true if the operation completed successfully. - * @throws FileNotFoundException - */ - public boolean publishShp(String workspace, String storename, String layername, File zipFile) throws FileNotFoundException { - return publishShp(workspace, storename, layername, zipFile, "EPSG:4326"); - } + /** + * Publish a zipped shapefile.
+ * The CRS will be forced to EPSG:4326. + * + * @param workspace + * @param storename + * @param layername + * @param zipFile + * @return true if the operation completed successfully. + * @throws FileNotFoundException + */ + public boolean publishShp(String workspace, String storename, + String layername, File zipFile) throws FileNotFoundException { + return publishShp(workspace, storename, layername, zipFile, "EPSG:4326"); + } - /** - * Publish a zipped shapefile. - * - * @param workspace - * @param storename - * @param layerName - * @param nativeCrs - * @param defaultStyle may be null - * @return true if the operation completed successfully. - * @throws FileNotFoundException - */ - public boolean publishShp(String workspace, String storename, String layerName, File zipFile, String nativeCrs, String defaultStyle) throws FileNotFoundException { - boolean sent = publishShp(workspace, storename, layerName, zipFile, nativeCrs); - if (sent) { + /** + * Publish a zipped shapefile. + * + * @param workspace + * @param storename + * @param layerName + * @param nativeCrs + * @param defaultStyle + * may be null + * @return true if the operation completed successfully. + * @throws FileNotFoundException + */ + public boolean publishShp(String workspace, String storename, + String layerName, File zipFile, String nativeCrs, + String defaultStyle) throws FileNotFoundException { + boolean sent = publishShp(workspace, storename, layerName, zipFile, + nativeCrs); + if (sent) { - try { - GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); - configureLayer(workspace, layerName, layerEncoder); - } catch (Exception e) { - LOGGER.warn("Error in publishing shapefile " + e.getMessage(), e); - sent = false; - } - } + try { + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.addDefaultStyle(defaultStyle); + configureLayer(workspace, layerName, layerEncoder); + } catch (Exception e) { + LOGGER.warn("Error in publishing shapefile " + e.getMessage(), + e); + sent = false; + } + } - return sent; - } + return sent; + } - /** - * Publish a zipped shapefile. - * - *

These are the equivalent calls with cUrl: - *

{@code
-     *curl -u admin:geoserver -XPUT -H 'Content-type: application/zip' \
-     *      --data-binary @$ZIPFILE \
-     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/file.shp
-     *
-     *curl -u admin:geoserver -XPOST -H 'Content-type: text/xml'  \
-     *      -d "$BAREEPSG:4326true"  \
-     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/featuretypes/$LAYERNAME
-     * }
- * - * @return true if the operation completed successfully. - */ - public boolean publishShp(String workspace, String storename, String layername, File zipFile, String srs) throws FileNotFoundException { - // build full URL - StringBuilder sbUrl = new StringBuilder(restURL) - .append("/rest/workspaces/").append(workspace) - .append("/datastores/").append(storename) - .append("/file.shp?"); -// if (workspace != null) { -// sbUrl.append("namespace=").append(workspace); -// } -// sbUrl.append("&SRS=4326&SRSHandling=Force"); // hack + /** + * Publish a zipped shapefile. + * + *

+ * These are the equivalent calls with cUrl: + * + *

+	 * {@code
+	 * curl -u admin:geoserver -XPUT -H 'Content-type: application/zip' \
+	 *       --data-binary @$ZIPFILE \
+	 *       http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/file.shp
+	 * 
+	 * curl -u admin:geoserver -XPOST -H 'Content-type: text/xml'  \
+	 *       -d "$BAREEPSG:4326true"  \
+	 *       http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/featuretypes/$LAYERNAME
+	 *  }
+	 * 
+ * + * @return true if the operation completed successfully. + */ + public boolean publishShp(String workspace, String storename, + String layername, File zipFile, String srs) + throws FileNotFoundException { + // build full URL + StringBuilder sbUrl = new StringBuilder(restURL) + .append("/rest/workspaces/").append(workspace) + .append("/datastores/").append(storename).append("/file.shp?"); + // if (workspace != null) { + // sbUrl.append("namespace=").append(workspace); + // } + // sbUrl.append("&SRS=4326&SRSHandling=Force"); // hack - String sentResult = HTTPUtils.put(sbUrl.toString(), zipFile, "application/zip", gsuser, gspass); - boolean shpSent = sentResult != null; + String sentResult = HTTPUtils.put(sbUrl.toString(), zipFile, + "application/zip", gsuser, gspass); + boolean shpSent = sentResult != null; - if (shpSent) { - LOGGER.info("Zipfile successfully uploaded (layer:" + layername + " zip:" + zipFile + ")"); + if (shpSent) { + LOGGER.info("Zipfile successfully uploaded (layer:" + layername + + " zip:" + zipFile + ")"); - StringBuilder postUrl = new StringBuilder(restURL) - .append("/rest/workspaces/").append(workspace) - .append("/datastores/").append(storename) - .append("/featuretypes/").append(layername); + StringBuilder postUrl = new StringBuilder(restURL) + .append("/rest/workspaces/").append(workspace) + .append("/datastores/").append(storename) + .append("/featuretypes/").append(layername); - GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); - fte.addName(layername); - fte.addSRS(srs); - fte.addProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); + GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); + fte.addName(layername); + fte.addSRS(srs); + fte.addProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); - String configuredResult = HTTPUtils.putXml(postUrl.toString(), fte.toString(), this.gsuser, this.gspass); - boolean shpConfigured = configuredResult != null; + String configuredResult = HTTPUtils.putXml(postUrl.toString(), + fte.toString(), this.gsuser, this.gspass); + boolean shpConfigured = configuredResult != null; - if (!shpConfigured) { - LOGGER.warn("Error in configuring " + workspace + ":" + storename + "/" + layername + " -- Zipfile was uploaded successfully: " + zipFile); - } else { - LOGGER.info("Shapefile successfully configured (layer:" + layername + ")"); - } + if (!shpConfigured) { + LOGGER.warn("Error in configuring " + workspace + ":" + + storename + "/" + layername + + " -- Zipfile was uploaded successfully: " + zipFile); + } else { + LOGGER.info("Shapefile successfully configured (layer:" + + layername + ")"); + } - return shpConfigured; + return shpConfigured; - } else { - LOGGER.warn("Error in sending zipfile " + workspace + ":" + storename + "/" + layername + " " + zipFile); - return false; - } + } else { + LOGGER.warn("Error in sending zipfile " + workspace + ":" + + storename + "/" + layername + " " + zipFile); + return false; + } - } + } - /** - * Publish a table in a PostGis store as a new layer. - * - *

This is the equivalent call with cUrl: - *

{@code curl -u admin:geoserver -XPOST -H 'Content-type: text/xml' \
-     *      -d "easia_gaul_1_aggrEPSG:4326true" \
-     *      http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/datastores/pg_kids/featuretypes
-     * }
- * - * and a PUT to - *
restURL + "/rest/layers/" + layerName + /** + * Publish a table in a PostGis store as a new layer. + * + *

+ * This is the equivalent call with cUrl: + * + *

+	 * {@code curl -u admin:geoserver -XPOST -H 'Content-type: text/xml' \
+	 *      -d "easia_gaul_1_aggrEPSG:4326true" \
+	 *      http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/datastores/pg_kids/featuretypes
+	 * }
+	 * 
+ * + * and a PUT to
+ * restURL + "/rest/layers/" + layerName + * + */ + public boolean publishDBLayer(String workspace, String storename, + String layername, String srs, String defaultStyle) { + StringBuilder postUrl = new StringBuilder(restURL) + .append("/rest/workspaces/").append(workspace) + .append("/datastores/").append(storename) + .append("/featuretypes"); + + GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); + fte.addName(layername); + fte.addSRS(srs); // srs=null?"EPSG:4326":srs); + String ftypeXml = fte.toString(); + + 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 + ")"); + + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.addDefaultStyle(defaultStyle); + 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; + } + + /** + * The configure parameter is used to control how the data store is + * configured upon file upload. It can take one of the three values “first”, + * “none”, or “all”.
+ * first - Only setup the first feature type available in the data store. + * This is the default.
+ * none - Do not configure any feature types.
+ * all - Configure all feature types. + */ + public static enum ParameterConfigure { + FIRST, NONE, ALL; + + @Override + public String toString() { + return this.name().toLowerCase(); + } + } + + /** + * The update parameter is used to control 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 “append”, or “overwrite”.
+ * append - Data being uploaded is appended to the existing data. This is + * the default.
+ * overwrite - Data being uploaded replaces any existing data.
+ * + * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it + * + */ + public static enum ParameterUpdate { + APPEND, OVERWRITE; + + @Override + public String toString() { + return this.name().toLowerCase(); + } + } + + // ========================================================================== + // === COVERAGES + // ========================================================================== + + // ========================================================================== + // === GEOTIFF + // ========================================================================== + + /** + * Publish a GeoTiff. + * + *

+ * This is the equivalent call with cUrl: + * + *

+	 * {@code
+	 * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$FULLPATH" \
+	 *       http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$STORENAME/external.geotiff
+	 *  }
+	 * 
+ * + * @return true if the operation completed successfully. + * @deprecated UNTESTED + */ + public boolean publishGeoTIFF(String workspace, String storeName, + File geotiff) throws FileNotFoundException { + String sUrl = restURL + "/rest/workspaces/" + workspace + + "/coveragestores/" + storeName + "/geotiff"; + String sendResult = HTTPUtils + .put(sUrl, geotiff, "text", gsuser, gspass); // CHECKME: text?!? + boolean sent = sendResult != null; + return sent; + } + + /** + * 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 + * + * @return a PublishedCoverage, or null on errors + * @throws FileNotFoundException + */ + public RESTCoverageStore publishExternalGeoTIFF(String workspace, + String storeName, File geotiff, String srs, String defaultStyle) + throws FileNotFoundException { + // create store + String sUrl = restURL + "/rest/workspaces/" + workspace + + "/coveragestores/" + storeName + "/external.geotiff"; + String sendResult = HTTPUtils.put(sUrl, geotiff.toURI().toString(), + "text/plain", gsuser, gspass); + RESTCoverageStore store = RESTCoverageStore.build(sendResult); + + if (store != null) { + try { + // retrieve coverage name + GeoServerRESTReader reader = new GeoServerRESTReader(restURL, + gsuser, gspass); + RESTCoverageList covList = reader.getCoverages(workspace, + storeName); + if (covList.isEmpty()) { + LOGGER.error("No coverages found in new coveragestore " + + storeName); + return null; + } + final String coverageName = covList.get(0).getName(); + + // config coverage props (srs) + GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.addName(FilenameUtils.getBaseName(geotiff + .getName())); + coverageEncoder.addSRS(srs); + coverageEncoder + .addProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); + configureCoverage(coverageEncoder, workspace, storeName, + coverageName); + + // config layer props (style, ...) + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.addDefaultStyle(defaultStyle); + configureLayer(workspace, coverageName, layerEncoder); + + } catch (Exception e) { + LOGGER.warn( + "Could not configure external GEOTiff:" + storeName, e); + store = null; // TODO: should we remove the configured pc? + } + } + + return store; + } + + // ========================================================================== + // === MOSAIC + // ========================================================================== + + /** + * Publish a Mosaic from a filesystem currently readable by GeoServer. + * + *

+ * Sample cUrl usage:
+ * <> + * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @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 { + if (!mosaicDir.isDirectory()) { + throw new IllegalArgumentException("Not a directory '" + mosaicDir + + "'"); + } + 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); + } + + /** + * @deprecated provided for backward compatibility use {@link + * createExternaMosaicDatastore(String workspace, String + * storeName, File mosaicDir, CoverageConfigure configure)} + * @param workspace + * @param storeName + * @param mosaicDir + * @return + * @throws FileNotFoundException + */ + public RESTCoverageStore configureExternaMosaicDatastore(String workspace, + String storeName, File mosaicDir) throws FileNotFoundException { + return createExternaMosaicDatastore(workspace, storeName, mosaicDir, + ParameterConfigure.FIRST, ParameterUpdate.APPEND); + } + + /** + * Publish a Mosaic already in a filesystem readable by GeoServer. + * + *

+ * Sample cUrl usage:
+ * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @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 RESTCoverageStore publishExternalMosaic(String workspace, + String storeName, File mosaicDir, String srs, String defaultStyle) + throws FileNotFoundException { + GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.addSRS(srs); + coverageEncoder.addName(FilenameUtils.getBaseName(mosaicDir.getName())); + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.addDefaultStyle(defaultStyle); + + return publishExternalMosaic(workspace, storeName, mosaicDir, + coverageEncoder, layerEncoder); + } + + /** + * Publish a Mosaic already in a filesystem readable by GeoServer. + * + *

+ * Sample cUrl usage:
+ * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @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 the created RESTCoverageStore + * @deprecated this is keep only for backward compatibility use + * createExternalMosaic and getCoverageStore separately + * + * @throws FileNotFoundException + */ + public RESTCoverageStore publishExternalMosaic(String workspace, + String storeName, File mosaicDir, + GSCoverageEncoder coverageEncoder, GSLayerEncoder layerEncoder) + throws FileNotFoundException { + + if (!createExternalMosaic(workspace, storeName, mosaicDir, + coverageEncoder, layerEncoder)) { + return null; + } + + GeoServerRESTReader reader; + try { + reader = new GeoServerRESTReader(restURL, gsuser, gspass); + } catch (MalformedURLException e1) { + LOGGER.warn("Could not configure external Mosaic:" + storeName, e1); + return null; + } + + final RESTCoverageStore store = reader.getCoverageStore(workspace, + storeName); + + if (store == null) { + LOGGER.warn("Unable to get the store" + workspace + ":" + storeName + + " from the targhet geoserver."); + return null; + } + + return store; + } + + /** + * Publish a Mosaic already in a filesystem readable by GeoServer. + * + *

+ * Sample cUrl usage:
+ * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @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 createExternalMosaic(String workspace, String storeName, + File mosaicDir, GSCoverageEncoder coverageEncoder, + GSLayerEncoder layerEncoder) throws FileNotFoundException { + + RESTCoverageStore store = createExternaMosaicDatastore(workspace, + storeName, mosaicDir, ParameterConfigure.NONE, + ParameterUpdate.OVERWRITE); + + // override name to match the FIRST configured coverage + final String coverageStoreName = FilenameUtils.getBaseName(mosaicDir + .getName()); + + if (coverageEncoder == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("no coverageEncoder provided for " + workspace + + ":" + storeName); + } + + coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.setName(coverageStoreName); + } + + if (layerEncoder == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("no layerEncoder provided for " + workspace + ":" + + storeName); + } + layerEncoder = new GSLayerEncoder(); + } + + if (store != null) { + try { + // override name + coverageEncoder.setName(coverageStoreName); + + if (!createCoverage(coverageEncoder, workspace, storeName)) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to create a coverage for the store:" + + storeName); + return false; + } + if (!configureLayer(workspace, coverageStoreName, layerEncoder)) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to configure the Layer for the coverage:" + + coverageStoreName); + return false; + } + + } catch (Exception e) { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Could not configure external mosaic:" + + storeName, e); + store = null; // TODO: should we remove the configured store? + return false; + } + return true; + } + return false; + } + + // ========================================================================== + // === COVERAGES + // ========================================================================== + + /** + * Remove the Coverage configuration from GeoServer.
+ * First, the associated layer is removed, then the Coverage configuration + * itself. + *

+ * CHECKME Maybe the coveragestore has to be removed as well. + * + *

+ * REST URL: + * http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/coveragestores/gbRESTtestStore/coverages/resttestdem.xml + * + * @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.isEnabledFor(Level.WARN)) { + 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.isEnabledFor(Level.ERROR)) + LOGGER.error(ex); + return false; + } + } + + // ========================================================================== + // === FEATURETYPES + // ========================================================================== + + /** + * 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.isEnabledFor(Level.WARN)) { + 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.isEnabledFor(Level.ERROR)) + LOGGER.error(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. + */ + public boolean removeDatastore(String workspace, String storename) { + return removeDatastore(workspace, storename, true); + } + + /** + * 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 + * @return true if the datastore was successfully removed. + */ + public boolean removeDatastore(String workspace, String storename, + final boolean recurse) { + try { + final StringBuilder url = new StringBuilder(restURL); + // restURL + "/rest/workspaces/" + workspace + "/datastores/" + + // storename + url.append("/rest/workspaces/").append(workspace) + .append("/datastores/").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 datastore " + workspace + ":" + + storename); + } else { + LOGGER.info("Datastore successfully deleted " + workspace + ":" + + storename); + } + + return deleted; + } catch (MalformedURLException ex) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error(ex); + return false; + } + } + + /** + * 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. + */ + 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) { + try { + final StringBuilder url = new StringBuilder(restURL); + // restURL + "/rest/workspaces/" + workspace + "/datastores/" + + // storename + url.append("/rest/workspaces/").append(workspace) + .append("/coveragestores/").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 CoverageStore " + workspace + ":" + + storename); + } else { + LOGGER.info("CoverageStore successfully deleted " + workspace + + ":" + storename); + } + return deleted; + + } catch (MalformedURLException ex) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error(ex); + return false; + } + } + + /** + * Remove a given Workspace. + * + * @param workspace + * The name of the workspace + * @return true if the WorkSpace was successfully removed. + */ + public boolean removeWorkspace(String workspace) { + workspace = sanitize(workspace); + try { + URL deleteUrl = new URL(restURL + "/rest/workspaces/" + workspace); + 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) { + LOGGER.error(ex); + return false; + } + } + + /** + * reload the target geoserver configuration + * + * @return true if success + * + * @see http + * ://docs.geoserver.org/stable/en/user/restconfig/rest-config-api.html + */ + public boolean reload() { + String sUrl = restURL + "/rest/reload"; + String result = HTTPUtils.post(sUrl, "", "text/plain", gsuser, gspass); + return result != null; + } + + /** + * reset the target geoserver configuration + * + * @return true if success + * + * @see http + * ://docs.geoserver.org/stable/en/user/restconfig/rest-config-api.html + */ + public boolean reset() { + String sUrl = restURL + "/rest/reset"; + String result = HTTPUtils.post(sUrl, "", "text/plain", gsuser, gspass); + return result != null; + } + + public boolean removeLayerGroup(String name) { + try { + URL deleteUrl = new URL(restURL + "/rest/layergroups/" + name); + boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), + gsuser, gspass); + if (!deleted) { + LOGGER.warn("Could not delete layergroup " + name); + } else { + if (LOGGER.isInfoEnabled()) + LOGGER.info("Layergroup successfully deleted: " + name); + } + + return deleted; + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + // ========================================================================== + // === + // ========================================================================== + + /** + * @deprecated please use {@link configureLayer(String workspace, String + * layerName, GSLayerEncoder layer) } + */ + public boolean configureLayer(final GSLayerEncoder layer, + final String layerName) { + return configureLayer(null, layerName, layer); + } + + /** + * 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.isEnabledFor(Level.WARN)) { + LOGGER.warn("Null workspace while removing layer : " + + layerName + " -- This behavior is deprecated."); + } + } else { + fqLayerName = workspace + ":" + layerName; + } + if (layerName == null) { + if (LOGGER.isEnabledFor(Level.ERROR)) { + 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.isEnabledFor(Level.WARN)) + LOGGER.warn("Error removing layer " + fqLayerName); + } + + return result; + } + + /** + * Allows to configure some layer attributes such and DefaultStyle TODO + * WmsPath + */ + public boolean configureLayer(final String workspace, + final String layerName, final GSLayerEncoder layer) { + + // TODO: check this usecase, layer should always be defined + if (layer.isEmpty()) { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Null layer name while configuring layer -- This behavior is suspicious."); + return true; + } + + final String fqLayerName; + + // this null check is here only for backward compatibility. workspace + // shall be mandatory. + if (workspace == null) { + + fqLayerName = layerName; + + if (LOGGER.isEnabledFor(Level.WARN)) { + LOGGER.warn("Null workspace while configuring layer : " + + layerName + " -- This behavior is deprecated."); + } + } else { + fqLayerName = workspace + ":" + layerName; + } + + final String url = restURL + "/rest/layers/" + fqLayerName; + + String layerXml = layer.toString(); + String sendResult = HTTPUtils.putXml(url, layerXml, gsuser, gspass); + if (sendResult != null) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Layer successfully configured: " + fqLayerName); + } + } else { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Error configuring layer " + fqLayerName + " (" + + sendResult + ")"); + } + + return sendResult != null; + } + + /** + * Configure an existent coverage in a given workspace and coverage store + * + * @param ce + * contains the coverage name to configure and the configuration + * to apply + * @param wsname + * the workspace to search for existent coverage + * @param csname + * the coverage store to search for existent coverage + * @return + */ + public boolean configureCoverage(final GSCoverageEncoder ce, + final String wsname, final String csname) { + final String cname = ce.getName(); + if (cname == null) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to configure a coverage with no name try using GSCoverageEncoder.setName(String)"); + return false; + } + + // retrieve coverage name + GeoServerRESTReader reader; + try { + reader = new GeoServerRESTReader(restURL, gsuser, gspass); + } catch (MalformedURLException e) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error(e); + return false; + } + final RESTCoverageList covList = reader.getCoverages(wsname, csname); + if (covList.isEmpty()) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("No coverages found in new coveragestore " + + csname); + return false; + } + final Iterator it = covList.iterator(); + boolean found = false; + while (it.hasNext()) { + NameLinkElem nameElem = it.next(); + if (nameElem.getName().equals(cname)) { + found = true; + break; + } + } + // if no coverage to configure is found return false + if (!found) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("No coverages found in new coveragestore " + + csname + " called " + cname); + return false; + } + + // configure the selected coverage + final String url = restURL + "/rest/workspaces/" + wsname + + "/coveragestores/" + csname + "/coverages/" + cname + ".xml"; + + final String xmlBody = ce.toString(); + final String sendResult = HTTPUtils + .putXml(url, xmlBody, gsuser, gspass); + if (sendResult != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Coverage successfully configured " + wsname + ":" + + csname + ":" + cname); + } + } else { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Error configuring coverage " + wsname + ":" + + csname + ":" + cname + " (" + sendResult + ")"); + } + + return sendResult != null; + } + + /** + * Create a new coverage in a given workspace and coverage store + * + * @deprecated to be tested + * @param ce + * contains the coverage name to create and the configuration to + * apply + * @param wsname + * the workspace to search for existent coverage + * @param csname + * the coverage store to search for existent coverage + * @return + */ + public boolean createCoverage(final GSCoverageEncoder ce, + final String wsname, final String csname) { + + final String cname = ce.getName(); + if (cname == null) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to configure a coverage with no name try using GSCoverageEncoder.setName(String)"); + return false; + } + + // configure the selected coverage + final String url = restURL + "/rest/workspaces/" + wsname + + "/coveragestores/" + csname + "/coverages.xml"; + + final String xmlBody = ce.toString(); + final String sendResult = HTTPUtils.postXml(url, xmlBody, gsuser, + gspass); + if (sendResult != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Coverage successfully created " + wsname + ":" + + csname + ":" + cname); + } + } else { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Error creating coverage " + wsname + ":" + csname + + ":" + cname + " (" + sendResult + ")"); + } + + return sendResult != null; + } + + /** + * Allows to configure some coverage's attributes + * + * @param ce + * Coverage encoder + * @param wsname + * workspace name + * @param csname + * coveragestore name + * @param cname + * coverage name (if != null will override the CoverageEncoder + * name) + * @return true if success + * @deprecated + */ + protected boolean configureCoverage(final GSCoverageEncoder ce, + final String wsname, final String csname, String cname) { + + if (cname != null) + ce.setName(cname); + else + cname = ce.getName(); + return configureCoverage(ce, wsname, csname); + } + + /** * */ - public boolean publishDBLayer(String workspace, String storename, String layername, String srs, String defaultStyle) { - StringBuilder postUrl = new StringBuilder(restURL) - .append("/rest/workspaces/").append(workspace) - .append("/datastores/").append(storename) - .append("/featuretypes"); + protected String sanitize(String s) { + if (s.indexOf(".") != -1) { + return s + ".DUMMY"; + } + return s; + } - GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); - fte.addName(layername); - fte.addSRS(srs); // srs=null?"EPSG:4326":srs); - String ftypeXml = fte.toString(); - - 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 + ")"); - - GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); - 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; - } - - //========================================================================== - //=== GEOTIFF - //========================================================================== - - /** - * Publish a GeoTiff. - * - *

This is the equivalent call with cUrl: - *

{@code
-     *curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$FULLPATH" \
-     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$STORENAME/external.geotiff
-     * }
- * - * @return true if the operation completed successfully. - * @deprecated UNTESTED - */ - public boolean publishGeoTIFF(String workspace, String storeName, File geotiff) throws FileNotFoundException { - String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/geotiff"; - String sendResult = HTTPUtils.put(sUrl, geotiff, "text", gsuser, gspass); // CHECKME: text?!? - boolean sent = sendResult != null; - return sent; - } - - /** - * 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 - * - * @return a PublishedCoverage, or null on errors - * @throws FileNotFoundException - */ - public RESTCoverageStore publishExternalGeoTIFF(String workspace, String storeName, File geotiff, String srs, String defaultStyle) throws FileNotFoundException { - // create store - String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/external.geotiff"; - String sendResult = HTTPUtils.put(sUrl, geotiff.toURI().toString(), "text/plain", gsuser, gspass); - RESTCoverageStore store = RESTCoverageStore.build(sendResult); - - if (store != null) { - try { -// // retrieve coverage name - GeoServerRESTReader reader = new GeoServerRESTReader(restURL, gsuser, gspass); - RESTCoverageList covList = reader.getCoverages(workspace, storeName); - if (covList.isEmpty()) { - LOGGER.error("No coverages found in new coveragestore " + storeName); - return null; - } - final String coverageName = covList.get(0).getName(); - - // config coverage props (srs) - GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); - coverageEncoder.addName(FilenameUtils.getBaseName(geotiff.getName())); - coverageEncoder.addSRS(srs); - coverageEncoder.addProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); - configureCoverage(coverageEncoder, workspace, storeName, coverageName); - - // config layer props (style, ...) - GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); - configureLayer(workspace, coverageName, layerEncoder); - - } catch (Exception e) { - LOGGER.warn("Could not configure external GEOTiff:" + storeName, e); - store = null; // TODO: should we remove the configured pc? - } - } - - return store; - } - - //========================================================================== - //=== MOSAIC - //========================================================================== - - /** - * Publish a Mosaic already in a filesystem readable by GeoServer. - * - *

Sample cUrl usage:
- * <> - * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" - * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic - * - * @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 - * @return true if the operation completed successfully. - * @throws FileNotFoundException - */ - public RESTCoverageStore configureExternaMosaicDatastore(String workspace, String storeName, File mosaicDir) throws FileNotFoundException { - if (!mosaicDir.isDirectory()) { - throw new IllegalArgumentException("Not a directory '" + mosaicDir + "'"); - } - String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/external.imagemosaic"; - 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. - * - *

Sample cUrl usage:
- * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" - * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic - * - * @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 RESTCoverageStore publishExternalMosaic(String workspace, String storeName, File mosaicDir, String srs, String defaultStyle) throws FileNotFoundException { - GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); - coverageEncoder.addSRS(srs); - coverageEncoder.addName(FilenameUtils.getBaseName(mosaicDir.getName())); - GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); - - return publishExternalMosaic(workspace, storeName, mosaicDir, coverageEncoder, layerEncoder); - } - - /** - * Publish a Mosaic already in a filesystem readable by GeoServer. - * - *

Sample cUrl usage:
- * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" - * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic - * - * @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 RESTCoverageStore publishExternalMosaic(String workspace, String storeName, File mosaicDir, GSCoverageEncoder coverageEncoder, GSLayerEncoder layerEncoder) throws FileNotFoundException { - RESTCoverageStore store = configureExternaMosaicDatastore(workspace, storeName, mosaicDir); - - if (coverageEncoder == null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("no coverageEncoder provided for " + workspace + ":" + storeName); - } - coverageEncoder = new GSCoverageEncoder(); - } - - if (layerEncoder == null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("no layerEncoder provided for " + workspace + ":" + storeName); - } - layerEncoder = new GSLayerEncoder(); - } - - if (store != null) { - try { -// // retrieve coverage name - GeoServerRESTReader reader = new GeoServerRESTReader(restURL, gsuser, gspass); - RESTCoverageList covList = reader.getCoverages(store.getWorkspaceName(), storeName); - if (covList.isEmpty()) { - LOGGER.error("No coverages found in new coveragestore " + storeName); - return null; - } - String coverageName = covList.get(0).getName(); -coverageEncoder.setName(FilenameUtils.getBaseName(mosaicDir.getName())); - configureCoverage(coverageEncoder, workspace, storeName, coverageName); - - configureLayer(workspace, storeName, layerEncoder); - - } catch (Exception e) { - if (LOGGER.isEnabledFor(Level.WARN)) - LOGGER.warn("Could not configure external mosaic:" + storeName, e); - store = null; // TODO: should we remove the configured store? - } - } - - return store; - } - - //========================================================================== - //=== COVERAGES - //========================================================================== - - /** - * Remove the Coverage configuration from GeoServer. - *
- * First, the associated layer is removed, then the Coverage configuration itself. - *

- * CHECKME Maybe the coveragestore has to be removed as well. - * - *

REST URL: - * http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/coveragestores/gbRESTtestStore/coverages/resttestdem.xml - * - * @return true if the operation completed successfully. - */ - public boolean unpublishCoverage(String workspace, String storename, String layername) { - try { - // delete related layer - URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + layername); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Going to delete " + "/rest/layers/" + layername); - } - boolean layerDeleted = HTTPUtils.delete(deleteLayerUrl.toExternalForm(), gsuser, gspass); - if (!layerDeleted) { - LOGGER.warn("Could not delete layer '" + layername + "'"); - 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) { - LOGGER.error(ex); - return false; - } - } - - //========================================================================== - //=== FEATURETYPES - //========================================================================== - - /** - * 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 { - // delete related layer - URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + layername); - boolean layerDeleted = HTTPUtils.delete(deleteLayerUrl.toExternalForm(), gsuser, gspass); - if (!layerDeleted) { - LOGGER.warn("Could not delete layer '" + layername + "'"); - 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) { - LOGGER.error(ex); - 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. - * @return true if the datastore was successfully removed. - */ - public boolean removeDatastore(String workspace, String storename) { - try { - URL deleteStore = new URL(restURL + "/rest/workspaces/" + workspace + "/datastores/" + storename); - boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass); - if (!deleted) { - LOGGER.warn("Could not delete datastore " + workspace + ":" + storename); - } else { - LOGGER.info("Datastore successfully deleted " + workspace + ":" + storename); - } - - return deleted; - } catch (MalformedURLException ex) { - LOGGER.error(ex); - return false; - } - } - - /** - * Remove 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. - */ - public boolean removeCoverageStore(String workspace, String storename) { - try { - URL deleteStore = new URL(restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storename); - boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass); - if (!deleted) { - LOGGER.warn("Could not delete CoverageStore " + workspace + ":" + storename); - } else { - LOGGER.info("CoverageStore successfully deleted " + workspace + ":" + storename); - } - - return deleted; - } catch (MalformedURLException ex) { - LOGGER.error(ex); - return false; - } - } - - /** - * Remove a given Workspace. - * - * @param workspace The name of the workspace - * @return true if the WorkSpace was successfully removed. - */ - public boolean removeWorkspace(String workspace) { - workspace = sanitize(workspace); - try { - URL deleteUrl = new URL(restURL + "/rest/workspaces/" + workspace); - 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) { - LOGGER.error(ex); - return false; - } - } - - /** - * reload the target geoserver configuration - * @return true if success - * - * @see http://docs.geoserver.org/stable/en/user/restconfig/rest-config-api.html - */ - public boolean reload() { - String sUrl = restURL + "/rest/reload"; - String result = HTTPUtils.post(sUrl, "", "text/plain", gsuser, gspass); - return result != null; - } - - /** - * reset the target geoserver configuration - * @return true if success - * - * @see http://docs.geoserver.org/stable/en/user/restconfig/rest-config-api.html - */ - public boolean reset() { - String sUrl = restURL + "/rest/reset"; - String result = HTTPUtils.post(sUrl, "", "text/plain", gsuser, gspass); - return result != null; - } - - public boolean removeLayerGroup(String name) { - try { - URL deleteUrl = new URL(restURL + "/rest/layergroups/" + name); - boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass); - if (!deleted) { - LOGGER.warn("Could not delete layergroup " + name); - } else { - if (LOGGER.isInfoEnabled()) - LOGGER.info("Layergroup successfully deleted: " + name); - } - - return deleted; - } catch (MalformedURLException ex) { - LOGGER.error(ex); - return false; - } - } - - //========================================================================== - //=== - //========================================================================== - - /** - * @deprecated please use {@link configureLayer(String workspace, String layerName, GSLayerEncoder layer) } - */ - public boolean configureLayer(final GSLayerEncoder layer, final String layerName) - { - return configureLayer(null, layerName, layer); - } - - 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.isEnabledFor(Level.WARN)){ - LOGGER.warn("Null workspace while removing layer : " + layerName + " -- This behavior is deprecated."); - } - } else { - fqLayerName = workspace + ":" + layerName; - } - if (layerName==null) { - if (LOGGER.isEnabledFor(Level.ERROR)){ - 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.isEnabledFor(Level.WARN)) - LOGGER.warn("Error removing layer " + fqLayerName); - } - - return result; - } - - /** - * Allows to configure some layer attributes such as WmsPath and DefaultStyle - * - */ - public boolean configureLayer(final String workspace, final String layerName, final GSLayerEncoder layer) { - - // TODO: check this usecase, layer should always be defined - if (layer.isEmpty()) { - if (LOGGER.isEnabledFor(Level.WARN)) - LOGGER.warn("Null layer name while configuring layer -- This behavior is suspicious."); - return true; - } - - final String fqLayerName; - - // this null check is here only for backward compatibility. workspace shall be mandatory. - if(workspace == null) { - - fqLayerName = layerName; - - if (LOGGER.isEnabledFor(Level.WARN)){ - LOGGER.warn("Null workspace while configuring layer : " + layerName + " -- This behavior is deprecated."); - } - } else { - fqLayerName = workspace + ":" + layerName; - } - - final String url = restURL + "/rest/layers/" + fqLayerName; - - String layerXml = layer.toString(); - String sendResult = HTTPUtils.putXml(url, layerXml, gsuser, gspass); - if (sendResult != null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Layer successfully configured: " + fqLayerName); - } - } else { - if (LOGGER.isEnabledFor(Level.WARN)) - LOGGER.warn("Error configuring layer " + fqLayerName + " (" + sendResult + ")"); - } - - return sendResult != null; - } - - /** - * Allows to configure some coverage's attributes - * - */ - protected boolean configureCoverage(final GSCoverageEncoder ce, String wsname, String csname, String cname) { - - final String url = restURL + "/rest/workspaces/" + wsname + "/coveragestores/" + csname + "/coverages/" + cname + ".xml"; - - String xmlBody = ce.toString(); - String sendResult = HTTPUtils.putXml(url, xmlBody, gsuser, gspass); - if (sendResult != null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Coverage successfully configured " + wsname + ":" + csname + ":" + cname); - } - } else { - if (LOGGER.isEnabledFor(Level.WARN)) - LOGGER.warn("Error configuring coverage " + wsname + ":" + csname + ":" + cname + " (" + sendResult + ")"); - } - - return sendResult != null; - } - - /** - * - */ - protected String sanitize(String s) { - if (s.indexOf(".") != -1) { - return s + ".DUMMY"; - } - return s; - } - - protected String encode(String s) { -// try { -// return URLEncoder.encode(s,"UTF-8"); -// } catch (UnsupportedEncodingException e) { -// LOGGER.warn("Error encoding :"+s+" with UTF-8: "+e.getLocalizedMessage()); - return URLEncoder.encode(s); -// } - } + protected String encode(String s) { + // try { + // return URLEncoder.encode(s,"UTF-8"); + // } catch (UnsupportedEncodingException e) { + // LOGGER.warn("Error encoding :"+s+" with UTF-8: "+e.getLocalizedMessage()); + return URLEncoder.encode(s); + // } + } } diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java index 69b2863..04b8316 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java @@ -68,7 +68,9 @@ public class RESTCoverageStore { public static RESTCoverageStore build(String response) { if(response == null) return null; - + if(response.isEmpty()) + return new RESTCoverageStore(new Element("coverageStore")); // TODO check how to response + Element pb = JDOMBuilder.buildElement(response); if(pb != null) return new RESTCoverageStore(pb); diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSResourceEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSResourceEncoder.java index 07b3b04..ee7920c 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSResourceEncoder.java +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSResourceEncoder.java @@ -48,10 +48,11 @@ import org.jdom.filter.Filter; */ public abstract class GSResourceEncoder extends PropertyXMLEncoder { - private final static String NAME="name"; + private final static String NAME = "name"; final private GSMetadataEncoder metadata = new GSMetadataEncoder(); final private Element keywordsListEncoder = new Element("keywords"); + /** * @param rootName * Actually 'feature' or 'coverage' @@ -66,9 +67,9 @@ public abstract class GSResourceEncoder addContent(metadata.getRoot()); addContent(keywordsListEncoder); } - - public void setEnabled(boolean enabled){ - set("enabled",(enabled)?"true":"false"); + + public void setEnabled(boolean enabled) { + set("enabled", (enabled) ? "true" : "false"); } /** @@ -79,28 +80,29 @@ public abstract class GSResourceEncoder public void addMetadata(String key, T dimensionInfo) { metadata.add(key, dimensionInfo.getRoot()); } - + /** - * @param key the name of the metadata to add (f.e.: elevation, time) + * @param key + * the name of the metadata to add (f.e.: elevation, time) * @return true if something is removed, false otherwise */ public boolean delMetadata(String key) { return metadata.remove(key); } - + public void setMetadata(String key, T dimensionInfo) { metadata.set(key, dimensionInfo.getRoot()); } - public void addKeyword(String keyword) { final Element el = new Element("string"); el.setText(keyword); keywordsListEncoder.addContent(el); } - + /** * delete a keyword from the list + * * @param keyword * @return true if something is removed, false otherwise */ @@ -109,13 +111,14 @@ public abstract class GSResourceEncoder el.setText(keyword); return (keywordsListEncoder.removeContent(new Filter() { private static final long serialVersionUID = 1L; + public boolean matches(Object obj) { - if (((Element)obj).getText().equals(keyword)){ + if (((Element) obj).getText().equals(keyword)) { return true; } return false; } - })).size()==0?false:true; + })).size() == 0 ? false : true; } /** @@ -125,7 +128,8 @@ public abstract class GSResourceEncoder REPROJECT_TO_DECLARED, FORCE_DECLARED, NONE } - private final static String PROJECTIONPOLICY="projectionPolicy"; + private final static String PROJECTIONPOLICY = "projectionPolicy"; + /** * NONE, REPROJECT_TO_DECLARED, FORCE_DECLARED * @@ -153,6 +157,7 @@ public abstract class GSResourceEncoder public void addName(final String name) { add(NAME, name); } + /** * Set or modify the 'name' node with a text value from 'name' * @@ -161,16 +166,17 @@ public abstract class GSResourceEncoder public void setName(final String name) { set(NAME, name); } - - public String getName(){ - final Element nameNode=get(NAME); - if (nameNode!=null) + + public String getName() { + final Element nameNode = get(NAME); + if (nameNode != null) return nameNode.getText(); else return null; } - private final static String TITLE="title"; + private final static String TITLE = "title"; + /** * Add the 'title' node with a text value from 'title' * @@ -180,7 +186,7 @@ public abstract class GSResourceEncoder public void addTitle(final String title) { add(TITLE, title); } - + /** * Set or modify the 'title' node with a text value from 'title' */ @@ -188,7 +194,8 @@ public abstract class GSResourceEncoder set(TITLE, title); } - private final static String SRS="srs"; + private final static String SRS = "srs"; + /** * Add the 'SRS' node with a text value from 'srs' * @@ -198,7 +205,7 @@ public abstract class GSResourceEncoder public void addSRS(final String srs) { add(SRS, srs); } - + /** * Set or modify the 'SRS' node with a text value from 'srs' */ @@ -206,67 +213,67 @@ public abstract class GSResourceEncoder set(SRS, srs); } - private final static String LATLONBBMINX="latLonBoundingBox/minx"; - private final static String LATLONBBMAXX="latLonBoundingBox/maxx"; - private final static String LATLONBBMINY="latLonBoundingBox/miny"; - private final static String LATLONBBMAXY="latLonBoundingBox/maxy"; - private final static String LATLONBBCRS="latLonBoundingBox/crs"; - + private final static String LATLONBBMINX = "latLonBoundingBox/minx"; + private final static String LATLONBBMAXX = "latLonBoundingBox/maxx"; + private final static String LATLONBBMINY = "latLonBoundingBox/miny"; + private final static String LATLONBBMAXY = "latLonBoundingBox/maxy"; + private final static String LATLONBBCRS = "latLonBoundingBox/crs"; + /** * @deprecated use the setSRS.
* This method will be set as protected in the next release - * + * * @param minx * @param maxy * @param maxx * @param miny * @param crs */ - public void addLatLonBoundingBox(double minx, double maxy, double maxx, - double miny, final String crs) { + public void addLatLonBoundingBox(double minx, double miny, double maxx, + double maxy, final String crs) { add(LATLONBBMINX, String.valueOf(minx)); + add(LATLONBBMINY, String.valueOf(miny)); add(LATLONBBMAXY, String.valueOf(maxy)); add(LATLONBBMAXX, String.valueOf(maxx)); - add(LATLONBBMINY, String.valueOf(miny)); add(LATLONBBCRS, crs); } - public void setLatLonBoundingBox(double minx, double maxy, double maxx, - double miny, final String crs) { + public void setLatLonBoundingBox(double minx, double miny, double maxx, + double maxy, final String crs) { set(LATLONBBMINX, String.valueOf(minx)); set(LATLONBBMAXY, String.valueOf(maxy)); set(LATLONBBMAXX, String.valueOf(maxx)); set(LATLONBBMINY, String.valueOf(miny)); set(LATLONBBCRS, crs); } - - private final static String NATIVEBBMINX="nativeBoundingBox/minx"; - private final static String NATIVEBBMAXX="nativeBoundingBox/maxx"; - private final static String NATIVEBBMINY="nativeBoundingBox/miny"; - private final static String NATIVEBBMAXY="nativeBoundingBox/maxy"; - private final static String NATIVEBBCRS="nativeBoundingBox/crs"; - + + private final static String NATIVEBBMINX = "nativeBoundingBox/minx"; + private final static String NATIVEBBMAXX = "nativeBoundingBox/maxx"; + private final static String NATIVEBBMINY = "nativeBoundingBox/miny"; + private final static String NATIVEBBMAXY = "nativeBoundingBox/maxy"; + private final static String NATIVEBBCRS = "nativeBoundingBox/crs"; + /** * @deprecated use the setSRS.
* This method will be set as protected in the next release - * + * * @param minx * @param maxy * @param maxx * @param miny * @param crs */ - public void addNativeBoundingBox(double minx, double maxy, double maxx, - double miny, final String crs) { + public void addNativeBoundingBox(double minx, double miny, double maxx, + double maxy, final String crs) { add(NATIVEBBMINX, String.valueOf(minx)); add(NATIVEBBMAXY, String.valueOf(maxy)); add(NATIVEBBMAXX, String.valueOf(maxx)); add(NATIVEBBMINY, String.valueOf(miny)); add(NATIVEBBCRS, crs); } - - public void setNativeBoundingBox(double minx, double maxy, double maxx, - double miny, final String crs) { + + public void setNativeBoundingBox(double minx, double miny, double maxx, + double maxy, final String crs) { set(NATIVEBBMINX, String.valueOf(minx)); set(NATIVEBBMAXY, String.valueOf(maxy)); set(NATIVEBBMAXX, String.valueOf(maxx)); diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/coverage/GSImageMosaicEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/coverage/GSImageMosaicEncoder.java index 0c1cfc0..f016d43 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/encoder/coverage/GSImageMosaicEncoder.java +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/coverage/GSImageMosaicEncoder.java @@ -110,10 +110,10 @@ public class GSImageMosaicEncoder extends GSCoverageEncoder { * @param val */ public void addFilter(final String val){ - final Element param=new Element(ENTRY); - param.addContent(new Element(STRING).setText(filter)); - param.addContent(new Element(STRING).setText(val)); - parameters.add(null,param); + final List list=new ArrayList(2); + list.add(new Element(STRING).setText(filter)); + list.add(new Element(STRING).setText(val)); + parameters.add(null,list); } private final static Filter filterFilter=new parametersFilter(filter); diff --git a/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java index 73aa895..5c5792b 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java @@ -50,7 +50,7 @@ import org.springframework.core.io.ClassPathResource; public class ConfigTest extends GeoserverRESTTest { private final static Logger LOGGER = Logger.getLogger(ConfigTest.class); - private static final String DEFAULT_WS = "it.geosolutions"; + private static final String DEFAULT_WS = "geosolutions"; public ConfigTest(String testName) { diff --git a/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java index fb1de65..9bbecc9 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java @@ -175,7 +175,6 @@ public class GeoserverRESTPublisherTest extends GeoserverRESTTest { deleteAllWorkspaces(); assertTrue(publisher.createWorkspace(DEFAULT_WS)); -// String ns = "it.geosolutions"; String storeName = "resttestshp"; String layerName = "cities"; diff --git a/src/test/resources/testdata/time_geotiff/indexer.properties b/src/test/resources/testdata/time_geotiff/indexer.properties new file mode 100644 index 0000000..52a708a --- /dev/null +++ b/src/test/resources/testdata/time_geotiff/indexer.properties @@ -0,0 +1,3 @@ +TimeAttribute=time +Schema= the_geom:Polygon,location:String,time:java.util.Date +PropertyCollectors=TimestampFileNameExtractorSPI[timeregex](time) diff --git a/src/test/resources/testdata/time_geotiff/stringregex.properties b/src/test/resources/testdata/time_geotiff/stringregex.properties new file mode 100644 index 0000000..d4c6d0a --- /dev/null +++ b/src/test/resources/testdata/time_geotiff/stringregex.properties @@ -0,0 +1 @@ +regex=[a-z]{5,5} diff --git a/src/test/resources/testdata/time_geotiff/timeregex.properties b/src/test/resources/testdata/time_geotiff/timeregex.properties new file mode 100644 index 0000000..8f0e125 --- /dev/null +++ b/src/test/resources/testdata/time_geotiff/timeregex.properties @@ -0,0 +1 @@ +regex=[0-9]{6} diff --git a/src/test/resources/testdata/time_geotiff/world.200401.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200401.3x5400x2700.tiff new file mode 100644 index 0000000..8b0612f Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200401.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200402.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200402.3x5400x2700.tiff new file mode 100644 index 0000000..4814a5f Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200402.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200403.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200403.3x5400x2700.tiff new file mode 100644 index 0000000..f8c7d50 Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200403.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200404.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200404.3x5400x2700.tiff new file mode 100644 index 0000000..5e8979a Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200404.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200405.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200405.3x5400x2700.tiff new file mode 100644 index 0000000..bbb15d0 Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200405.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200406.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200406.3x5400x2700.tiff new file mode 100644 index 0000000..94a94f5 Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200406.3x5400x2700.tiff differ diff --git a/src/test/resources/testdata/time_geotiff/world.200407.3x5400x2700.tiff b/src/test/resources/testdata/time_geotiff/world.200407.3x5400x2700.tiff new file mode 100644 index 0000000..82b8fb0 Binary files /dev/null and b/src/test/resources/testdata/time_geotiff/world.200407.3x5400x2700.tiff differ