diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java index da1ee34..90b00b0 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -37,6 +37,7 @@ import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder; import java.io.File; import java.io.FileNotFoundException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.net.URLEncoder; import java.util.Iterator; @@ -343,6 +344,122 @@ public class GeoServerRESTPublisher { } return false; } + + 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, DataStoreType.datastores, storeName, method, extension, mimeType, uri, configure, params); + } + + 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, DataStoreType.coveragestores, storeName, method, extension, mimeType, uri, configure, params); + } + + /** + * + * @param workspace + * @param dsType + * @param storeName + * @param method + * @param extension + * @param mimeType + * @param uri + * @param configure + * @param params + * @return + * @throws FileNotFoundException + * @throws IllegalArgumentException + */ + private boolean createStore(String workspace, DataStoreType 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 + && !configure.equals(ParameterConfigure.NONE)) { + 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.isEnabledFor(Level.ERROR)) + LOGGER.error("Error in creating store using: " + uri); + return false; + } + + } + + /** + * A data store is a source of spatial data that is vector based. It can be + * a file in the case of a Shapefile, a database in the case of PostGIS, or + * a server in the case of a remote Web Feature Service.
+ * + * A coverage store is a source of spatial data that is raster based.
+ * + * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it + * + */ + public enum DataStoreType{ + coveragestores, + datastores + } + /** + * The file, url, and external endpoints are used to specify the method that + * is used to upload the file. + * + * The file method is used to directly upload a file from a local source. + * The body of the request is the file itself. + * + * The url method is used to indirectly upload a file from an remote source. + * The body of the request is a url pointing to the file to upload. This url + * must be visible from the server. + * + * The external method is used to forgo upload and use an existing file on + * the server. The body of the request is the absolute path to the existing + * file. + * + * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it + * + */ + public enum UploadMethod { + file, + url, + external + } // ========================================================================== // === DATASTORE @@ -510,9 +627,9 @@ public class GeoServerRESTPublisher { .append("/featuretypes/").append(layername); GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); - fte.addName(layername); - fte.addSRS(srs); - fte.addProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); + fte.setName(layername); + fte.setSRS(srs); + fte.setProjectionPolicy(ProjectionPolicy.FORCE_DECLARED); String configuredResult = HTTPUtils.putXml(postUrl.toString(), fte.toString(), this.gsuser, this.gspass); @@ -552,10 +669,10 @@ public class GeoServerRESTPublisher { fte.setProjectionPolicy(ProjectionPolicy.REPROJECT_TO_DECLARED); fte.addKeyword("KEYWORD"); - fte.addName(layername); - fte.addSRS(srs); // srs=null?"EPSG:4326":srs); + fte.setName(layername); + fte.setSRS(srs); // srs=null?"EPSG:4326":srs); final GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); + layerEncoder.setDefaultStyle(defaultStyle); return publishDBLayer(workspace, storename, fte, layerEncoder); } @@ -633,12 +750,13 @@ public class GeoServerRESTPublisher { /** * 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. + * configured upon file upload. It can take one of the three values first, + * none, or all. + * */ public static enum ParameterConfigure { FIRST, NONE, ALL; @@ -681,10 +799,9 @@ public class GeoServerRESTPublisher { /** * - * Publish a zipped worldimage file. It is assumed that the the zip-file - * contain the *.prj to set the srs. + * Publish a file. *

- * This is equivalent call with cUrl: + * This is an example with cUrl: * *

 	 * {@code
@@ -715,38 +832,145 @@ public class GeoServerRESTPublisher {
 	 * @return true if the operation completed successfully.
 	 */
 	private boolean publishCoverage(String workspace, String coveragestore,
-			String format, String mimeType, File file,
+			CoverageStoreExtension extension, String mimeType, File file,
 			ParameterConfigure configure, NameValuePair... params)
 			throws FileNotFoundException {
-		// build full URL
-		StringBuilder sbUrl = new StringBuilder(restURL)
-				.append("/rest/workspaces/").append(workspace)
-				.append("/coveragestores/").append(coveragestore)
-				.append("/file.").append(format);
-
-		if (configure != null) {
-			sbUrl.append("?configure=").append(configure);
-			if (params != (NameValuePair[]) null
-					&& !configure.equals(ParameterConfigure.NONE)) {
-				final String paramString = appendParameters(params);
-				if (!paramString.isEmpty()) {
-					sbUrl.append("&").append(paramString);
-				}
-			}
-		}
-		String sentResult = HTTPUtils.put(sbUrl.toString(), file, mimeType,
-				gsuser, gspass);
-		boolean fileSent = sentResult != null;
-
-		if (fileSent) {
-			if (LOGGER.isInfoEnabled())
-				LOGGER.info("File successfully uploaded ( " + file + ")");
-		} else {
-			if (LOGGER.isEnabledFor(Level.WARN))
-				LOGGER.warn("Error in sending file " + file);
-		}
-		return fileSent;
+	    return createCoverageStore(workspace, coveragestore, UploadMethod.file, extension, mimeType, file.toURI(), configure, params);
+//		// build full URL
+//		StringBuilder sbUrl = new StringBuilder(restURL)
+//				.append("/rest/workspaces/").append(workspace)
+//				.append("/coveragestores/").append(coveragestore)
+//				.append("/file.").append(format);
+//
+//		if (configure != null) {
+//			sbUrl.append("?configure=").append(configure);
+//			if (params != (NameValuePair[]) null
+//					&& !configure.equals(ParameterConfigure.NONE)) {
+//				final String paramString = appendParameters(params);
+//				if (!paramString.isEmpty()) {
+//					sbUrl.append("&").append(paramString);
+//				}
+//			}
+//		}
+//		String sentResult = HTTPUtils.put(sbUrl.toString(), file, mimeType,
+//				gsuser, gspass);
+//		boolean fileSent = sentResult != null;
+//
+//		if (fileSent) {
+//			if (LOGGER.isInfoEnabled())
+//				LOGGER.info("File successfully uploaded ( " + file + ")");
+//		} else {
+//			if (LOGGER.isEnabledFor(Level.WARN))
+//				LOGGER.warn("Error in sending file " + file);
+//		}
+//		return fileSent;
 	}
+	
+        /**
+         * 
+         * The extension parameter specifies the type of data being uploaded. The
+         * following extensions are supported:
+         * 
+         * 
+         * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+         * 
+         */
+	public enum CoverageStoreExtension {
+	   geotiff,
+	   imagemosaic,
+	   worldimage
+	}
+	
+	/**
+         * 
+         * The extension parameter specifies the type of data being uploaded. The
+         * following extensions are supported:
+         * 
+         * 
+         * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
+         * 
+         */
+        public enum DataStoreExtension {
+           shp,
+           properties,
+           h2,
+           spatialite
+        }
+	
+	/**
+         * 
+         * Publish a file sending it to the GeoServer.
+         * 
+         * 

+ * Here is an example call 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
+         * 
+ * + * @param workspace + * Workspace to use + * @param coveragestore + * Name of the coveragestore + * @param file + * file to upload + * @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 { + return createCoverageStore(workspace, coveragestore, UploadMethod.external, extension, mimeType, file.toURI(), configure, (update!=null)?new NameValuePair[]{new NameValuePair("update",update.toString())}:(NameValuePair[])null); +// // build full URL +// StringBuilder sbUrl = new StringBuilder(restURL) +// .append("/rest/workspaces/").append(workspace) +// .append("/coveragestores/").append(coveragestore) +// .append("/external.").append(format); +// +// if (configure!=null){ +// sbUrl.append("?configure=").append(configure); +// if (update!=null){ +// sbUrl.append("&update=").append(update.toString()); +// } +// } else if (update!=null){ +// sbUrl.append("?update=").append(update.toString()); +// } +// +// final String sentResult = HTTPUtils.put(sbUrl.toString(), file.getAbsoluteFile().toURI().toString(), mimeType, gsuser, gspass); +// +// if (sentResult != null) { +// if (LOGGER.isInfoEnabled()) +// LOGGER.info("Store successfully created using ( " + file + " )"); +// return true; +// } else { +// if (LOGGER.isEnabledFor(Level.ERROR)) +// LOGGER.error("Error in creating store using file " + file); +// return false; +// } + } // ========================================================================== // === GEOTIFF @@ -757,14 +981,14 @@ public class GeoServerRESTPublisher { */ public boolean publishGeoTIFF(String workspace, String storeName, File geotiff) throws FileNotFoundException { - return publishCoverage(workspace, storeName, "geotiff", + return publishCoverage(workspace, storeName, CoverageStoreExtension.geotiff, "image/geotiff", geotiff, ParameterConfigure.FIRST, (NameValuePair[]) null); } /** * Publish a GeoTiff. - * Simple wrapper for {@link #publishCoverage(String, String, String, String, File, ParameterConfigure, NameValuePair...)} + * Simple wrapper for {@link #publishCoverage(String, String, CoverageStoreExtension, String, File, ParameterConfigure, NameValuePair...)} *

* This is the equivalent call with cUrl: * @@ -777,83 +1001,132 @@ public class GeoServerRESTPublisher { * * @param workspace Workspace to use * @param storeName Name of the coveragestore (if null the file name will be used) - * @param layerName the name of the coverage (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 layerName, + 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()), "geotiff", + return publishCoverage(workspace, (storeName!=null)?storeName:FilenameUtils.getBaseName(geotiff.getAbsolutePath()), CoverageStoreExtension.geotiff, "image/geotiff", geotiff, ParameterConfigure.FIRST, - (layerName!=null)?new NameValuePair[]{new NameValuePair("coverageName", layerName)}:(NameValuePair[]) null); + (coverageName!=null)?new NameValuePair[]{new NameValuePair("coverageName", coverageName)}:(NameValuePair[]) null); } - /** - * 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; - } + /** + * + * 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 + * @param policy + * @param defaultStyle + * @return + * @throws FileNotFoundException + */ + 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.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; + } + +// /** +// * +// * @param workspace +// * @param storeName +// * @param geotiff +// * @param srs +// * @param defaultStyle +// * @return +// * @throws FileNotFoundException +// * @deprecated +// */ +// public RESTCoverageStore publishExternalGeoTIFF(String workspace, +// String storeName, File geotiff, String srs, String defaultStyle) +// throws FileNotFoundException { +// +// if (publishExternalGeoTIFF(workspace, storeName, geotiff, storeName, srs,ProjectionPolicy.FORCE_DECLARED,defaultStyle)){ +// GeoServerRESTReader reader=new GeoServerRESTReader(this.restURL, this.gsuser, this.gspass); +// return reader.getCoverageStore(workspace, storeName); +// } +// return null; +// } + + /** + * 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 + * @param layerEncoder + * @return true if successfully configured + * + * + * @throws FileNotFoundException + * @throws IllegalArgumentException if null parameter + */ + 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.isEnabledFor(Level.ERROR)) + 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.log(Level.ERROR, e.getMessage(), e); + } + } + return null; + } // ========================================================================== // === WORLDIMAGE @@ -906,7 +1179,7 @@ public class GeoServerRESTPublisher { public boolean publishWorldImage(String workspace, String coveragestore, File zipFile, ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException { - return publishCoverage(workspace, coveragestore, "worldimage", + return publishCoverage(workspace, coveragestore, CoverageStoreExtension.worldimage, "application/zip", zipFile, configure, params); } @@ -921,7 +1194,7 @@ public class GeoServerRESTPublisher { */ public boolean publishImageMosaic(String workspace, String storeName, File zipFile) throws FileNotFoundException { - return publishCoverage(workspace, storeName, "imagemosaic", + return publishCoverage(workspace, storeName, CoverageStoreExtension.imagemosaic, "application/zip", zipFile, ParameterConfigure.FIRST, (NameValuePair[]) null); } @@ -934,7 +1207,7 @@ public class GeoServerRESTPublisher { public boolean publishImageMosaic(String workspace, String storeName, File zipFile, ParameterConfigure configure, NameValuePair... params) throws FileNotFoundException { - return publishCoverage(workspace, storeName, "imagemosaic", + return publishCoverage(workspace, storeName, CoverageStoreExtension.imagemosaic, "application/zip", zipFile, configure, params); } @@ -992,11 +1265,11 @@ public class GeoServerRESTPublisher { * @return * @throws FileNotFoundException */ - public RESTCoverageStore configureExternaMosaicDatastore(String workspace, - String storeName, File mosaicDir) throws FileNotFoundException { - return createExternaMosaicDatastore(workspace, storeName, mosaicDir, - ParameterConfigure.FIRST, ParameterUpdate.APPEND); - } +// 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. @@ -1021,74 +1294,37 @@ public class GeoServerRESTPublisher { * * @throws FileNotFoundException */ - public RESTCoverageStore publishExternalMosaic(String workspace, + public boolean publishExternalMosaic(String workspace, String storeName, File mosaicDir, String srs, String defaultStyle) throws FileNotFoundException { + final GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); - coverageEncoder.addSRS(srs); - coverageEncoder.addName(FilenameUtils.getBaseName(mosaicDir.getName())); + coverageEncoder.setSRS(srs); + final String name=FilenameUtils.getBaseName(mosaicDir.getName()); + coverageEncoder.setName(name); + final GSLayerEncoder layerEncoder = new GSLayerEncoder(); - layerEncoder.addDefaultStyle(defaultStyle); + layerEncoder.setDefaultStyle(defaultStyle); - return publishExternalMosaic(workspace, storeName, mosaicDir, - coverageEncoder, layerEncoder); + 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 - * + * @deprecated use {@link #publishExternalMosaic(String workspace, final String storeName, File mosaicDir, GSCoverageEncoder coverageEncoder, + GSLayerEncoder layerEncoder)} * @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 - * + * @return * @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 target geoserver."); - return null; - } - - return store; + public boolean createExternalMosaic(String workspace, String storeName, + File mosaicDir, GSCoverageEncoder coverageEncoder, + GSLayerEncoder layerEncoder) throws FileNotFoundException { + return publishExternalMosaic(workspace, storeName, mosaicDir, coverageEncoder, layerEncoder); } /** @@ -1111,69 +1347,41 @@ public class GeoServerRESTPublisher { * @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()); + public boolean publishExternalMosaic(String workspace, final String storeName, File mosaicDir, GSCoverageEncoder coverageEncoder, + GSLayerEncoder layerEncoder) throws FileNotFoundException,IllegalArgumentException { if (coverageEncoder == null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("no coverageEncoder provided for " + workspace - + ":" + storeName); - } - - coverageEncoder = new GSCoverageEncoder(); - coverageEncoder.setName(coverageStoreName); + throw new IllegalArgumentException("no coverageEncoder provided for mosaic " + mosaicDir); } + // override name to match the FIRST configured coverage + String coverageName=coverageEncoder.getName(); if (layerEncoder == null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("no layerEncoder provided for " + workspace + ":" - + storeName); - } - layerEncoder = new GSLayerEncoder(); + throw new IllegalArgumentException("no layerEncoder provided for " + workspace + ":" + + coverageName); } - if (store != null) { - try { - // override name - coverageEncoder.setName(coverageStoreName); + RESTCoverageStore store = createExternaMosaicDatastore(workspace, storeName, mosaicDir, ParameterConfigure.NONE, + ParameterUpdate.OVERWRITE); - 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; + if (store == null) { + return false; } - return false; + if (!createCoverage(workspace, storeName, coverageEncoder)) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to create a coverage for the store:" + coverageName); + return false; + } + if (!configureLayer(workspace, coverageName, layerEncoder)) { + if (LOGGER.isEnabledFor(Level.ERROR)) + LOGGER.error("Unable to configure the Layer for the coverage:" + coverageName); + return false; + } + return true; } // ========================================================================== @@ -1569,15 +1777,6 @@ public class GeoServerRESTPublisher { // === // ========================================================================== - /** - * @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 * @@ -1626,50 +1825,42 @@ public class GeoServerRESTPublisher { /** * Allows to configure some layer attributes such and DefaultStyle - * - * @TODO WmsPath - */ + * + * @param workspace + * @param resourceName the name of the resource to use (featureStore or coverageStore name) + * @param layer the layer encoder used to configure the layer + * @return true if success + * @throws IllegalArgumentException if some arguments are null or empty + * + * @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; + final String resourceName, final GSLayerEncoder layer) throws IllegalArgumentException { + + if (workspace == null || resourceName == null || layer == null) { + throw new IllegalArgumentException("Null argument"); + } + // TODO: check this usecase, layer should always be defined + if (workspace.isEmpty() || resourceName.isEmpty() || layer.isEmpty()) { + throw new IllegalArgumentException("Empty argument"); + } + + final String fqLayerName = workspace + ":" + resourceName; + + 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; } /** @@ -1692,7 +1883,6 @@ public class GeoServerRESTPublisher { LOGGER.error("Unable to configure a coverage with no name try using GSCoverageEncoder.setName(String)"); return false; } - // retrieve coverage name GeoServerRESTReader reader; try { @@ -1746,75 +1936,60 @@ public class GeoServerRESTPublisher { return sendResult != null; } - + /** - * Create a new coverage in a given workspace and coverage store - * + * @deprecated use {@link #createCoverage(String, String, GSCoverageEncoder)} * @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; + public boolean createCoverage(final GSCoverageEncoder ce, final String wsname, final String csname) { + return createCoverage(wsname, csname, ce); } - + /** - * Allows to configure some coverage's attributes - * - * @param ce - * Coverage encoder + * Create a new coverage in a given workspace and coverage store * @param wsname - * workspace name - * @param csname - * coveragestore name - * @param cname - * coverage name (if != null will override the CoverageEncoder - * name) + * the workspace to search for existent coverage + * @param storeName + * an existent store name to use as data source + * @param ce + * contains the coverage name to create and the configuration to + * apply * @return true if success - * @deprecated use - * {@link GeoServerRESTPublisher#configureCoverage(GSCoverageEncoder, String, String)} + * @throws IllegalArgumentException if arguments are null or empty */ - 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 createCoverage(final String wsname, final String storeName, final GSCoverageEncoder ce) + throws IllegalArgumentException { + + if (wsname.isEmpty() || wsname==null || ce == null || ce.isEmpty()) { + throw new IllegalArgumentException( + "Unable to configure a coverage with null or empty arguments"); + } + final String coverageName = ce.getName(); + if (coverageName == null) { + throw new IllegalArgumentException("Unable to configure a coverage with unnamed coverage encoder"); + } + + // configure the selected coverage + final String url = restURL + "/rest/workspaces/" + wsname + "/coveragestores/" + storeName + + "/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 + ":" + storeName + ":" + coverageName); + } + } else { + if (LOGGER.isEnabledFor(Level.WARN)) + LOGGER.warn("Error creating coverage " + wsname + ":" + storeName + ":" + coverageName + " (" + + sendResult + ")"); + } + + return sendResult != null; + } /** * diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java index c194dbe..52f5b28 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java @@ -154,7 +154,7 @@ public class RESTLayer { * } */ public String getResourceUrl() { - Element resource = layerElem.getChild("resource"); + Element resource = layerElem.getChild("resource"); Element atom = resource.getChild("link", Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom")); return atom.getAttributeValue("href"); } diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java index a58f313..f144794 100644 --- a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java @@ -25,6 +25,8 @@ package it.geosolutions.geoserver.rest.encoder; +import org.jdom.Element; + import it.geosolutions.geoserver.rest.encoder.utils.PropertyXMLEncoder; /** @@ -42,6 +44,9 @@ public class GSLayerEncoder extends PropertyXMLEncoder { addEnabled(); } + /** + * enabled the layer + */ protected void addEnabled(){ add("enabled","true"); } @@ -55,18 +60,72 @@ public class GSLayerEncoder extends PropertyXMLEncoder { else set("enabled","false"); } - + +// /** +// * @param name the name of the layer +// */ +// protected void addName(final String name){ +// add("name",name); +// } +// +// /** +// * @return name the name of the layer or null +// */ +// public String getName() { +// final Element nameNode = get("name"); +// if (nameNode != null) +// return nameNode.getText(); +// else +// return null; +// } +// +// /** +// * @param name the name of the layer +// * @throws IllegalArgumentException +// */ +// public void setName(final String name) throws IllegalArgumentException { +// if (name==null || name.isEmpty()) +// throw new IllegalArgumentException("Unable to set an empty or null parameter"); +// set("name",name); +// } + /** + * @see {@link GSLayerEncoder#setWmsPath(String)} * - * @param defaultStyle - * @deprecated will be set to protected in the next release, please use setDefaultStyle - * + * @param path the wms path to set */ - public void addDefaultStyle(String defaultStyle) { - add("defaultStyle", defaultStyle); + protected void addWmsPath(final String path) { + add("path", path); } - public void setDefaultStyle(String defaultStyle) { + /** + * Default WMS Path The GeoServer WMS path is, by default, /geoserver/wms. + * However you can change it to /geoserver/anythingyouwant + * + * @param path the wms path to set + * @throws IllegalArgumentException if path is null or empty + */ + public void setWmsPath(final String path) throws IllegalArgumentException { + if (path==null || path.isEmpty()) + throw new IllegalArgumentException("Unable to set an empty or null parameter"); + set("path",path); + } + + /** + * @see {@link GSLayerEncoder#setDefaultStyle(String)} + * @param defaultStyle + */ + protected void addDefaultStyle(String defaultStyle) { + add("defaultStyle", defaultStyle); + } + + /** + * @param defaultStyle The style that will be applied if no style is specified. + * @throws IllegalArgumentException if defaultStyle is null or empty + */ + public void setDefaultStyle(final String defaultStyle) throws IllegalArgumentException { + if (defaultStyle==null || defaultStyle.isEmpty()) + throw new IllegalArgumentException("Unable to set an empty or null parameter"); set("defaultStyle", defaultStyle); } } diff --git a/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java index 5c5792b..86fec28 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java @@ -27,6 +27,9 @@ package it.geosolutions.geoserver.rest; import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; +import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy; +import it.geosolutions.geoserver.rest.encoder.coverage.GSCoverageEncoder; import java.io.File; import java.io.FileNotFoundException; @@ -90,19 +93,18 @@ public class ConfigTest extends GeoserverRESTTest { String layerName = "resttestdem"; File geotiff = new ClassPathResource("testdata/resttestdem.tif").getFile(); - RESTCoverageStore pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, null, null); + boolean pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, layerName,"EPSG:4326",ProjectionPolicy.FORCE_DECLARED,"raster"); - assertNotNull(pc); + assertTrue(pc); } public void insertExternalShape() throws FileNotFoundException, IOException { File zipFile = new ClassPathResource("testdata/resttestshp.zip").getFile(); - boolean published = publisher.publishShp(DEFAULT_WS, "anyname", "cities", zipFile, "EPSG:4326", "default_point"); + boolean published = publisher.publishShp(DEFAULT_WS, "anyname", "cities", zipFile, "EPSG:41001", "default_point"); assertTrue("publish() failed", published); - //test delete boolean ok = publisher.unpublishFeatureType(DEFAULT_WS, "anyname", "cities"); assertTrue("Unpublish() failed", ok); diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTGeoTiffTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTGeoTiffTest.java index fe853a1..9e11cd2 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTGeoTiffTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTGeoTiffTest.java @@ -27,6 +27,9 @@ package it.geosolutions.geoserver.rest.publisher; import it.geosolutions.geoserver.rest.GeoserverRESTTest; import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; +import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy; +import it.geosolutions.geoserver.rest.encoder.coverage.GSCoverageEncoder; import java.io.File; import java.io.FileNotFoundException; @@ -66,14 +69,14 @@ public class GeoserverRESTGeoTiffTest extends GeoserverRESTTest { assertFalse("Cleanup failed", existsLayer(layerName)); // test insert - RESTCoverageStore pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, null, null); - assertNotNull("publish() failed", pc); + boolean pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, layerName,"EPSG:4326",ProjectionPolicy.FORCE_DECLARED,"raster"); + assertTrue("publish() failed", pc); assertTrue(existsLayer(layerName)); LOGGER.info(pc); RESTCoverageStore reloadedCS = reader.getCoverageStore(DEFAULT_WS, storeName); - assertEquals(pc.getName(), reloadedCS.getName()); - assertEquals(pc.getWorkspaceName(), reloadedCS.getWorkspaceName()); + assertEquals(storeName, reloadedCS.getName()); + assertEquals(DEFAULT_WS, reloadedCS.getWorkspaceName()); //test delete assertTrue("Unpublish() failed", publisher.unpublishCoverage(DEFAULT_WS, storeName, layerName)); diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTImageMosaicTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTImageMosaicTest.java index 08fa7f2..9200038 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTImageMosaicTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTImageMosaicTest.java @@ -139,7 +139,7 @@ public class GeoserverRESTImageMosaicTest extends GeoserverRESTTest { try { final File mosaicFile = new ClassPathResource("testdata/time_geotiff/").getFile(); - if (!publisher.createExternalMosaic(wsName,coverageStoreName,mosaicFile,coverageEncoder,layerEncoder)){ + if (!publisher.publishExternalMosaic(wsName,coverageStoreName,mosaicFile,coverageEncoder,layerEncoder)){ fail(); } coverageStore = reader.getCoverageStore(wsName,coverageStoreName); diff --git a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTWorkspaceTest.java b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTWorkspaceTest.java index d8aba9c..dfc109e 100644 --- a/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTWorkspaceTest.java +++ b/src/test/java/it/geosolutions/geoserver/rest/publisher/GeoserverRESTWorkspaceTest.java @@ -27,6 +27,9 @@ package it.geosolutions.geoserver.rest.publisher; import it.geosolutions.geoserver.rest.GeoserverRESTTest; import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; +import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy; +import it.geosolutions.geoserver.rest.encoder.coverage.GSCoverageEncoder; import java.io.File; import java.io.IOException; @@ -84,7 +87,7 @@ public class GeoserverRESTWorkspaceTest extends GeoserverRESTTest { assertFalse("Cleanup failed", existsLayer(layerName)); // test insert - RESTCoverageStore pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, null, null); + boolean pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, layerName, "EPSG:4326",ProjectionPolicy.REPROJECT_TO_DECLARED,"raster"); // remove workspace and all of its contents assertTrue(publisher.removeWorkspace(DEFAULT_WS,true));