/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.gs.download;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.config.GeoServer;
import org.geotools.process.ProcessException;
import org.geotools.process.factory.DescribeParameter;
import org.geotools.process.factory.DescribeProcess;
import org.geotools.process.factory.DescribeResult;
import org.geotools.process.gs.GSProcess;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.util.ProgressListener;
import com.vividsolutions.jts.geom.Geometry;
/**
* The DownloadEstimatorProcess is used for checking if the download request does not exceeds the defined limits.
*
* @author "Alessio Fabiani - alessio.fabiani@geo-solutions.it"
*/
@DescribeProcess(title = "Estimator Process", description = "Checks if the input file does not exceed the limits")
public class DownloadEstimatorProcess implements GSProcess {
/** The Constant LOGGER. */
private static final Logger LOGGER = Logging.getLogger(DownloadEstimatorProcess.class);
private DownloadServiceConfigurationGenerator downloadServiceConfigurationGenerator;
/** The catalog. */
private final Catalog catalog;
/**
* @param readLimits
* @param writeLimits
* @param hardOutputLimit
* @param geoserver
*/
public DownloadEstimatorProcess(
DownloadServiceConfigurationGenerator downloadServiceConfigurationGenerator,
GeoServer geoserver) {
this.catalog = geoserver.getCatalog();
this.downloadServiceConfigurationGenerator = downloadServiceConfigurationGenerator;
}
/**
* This process returns a boolean value which indicates if the requested download does not exceed the imposed limits, if present
*
* @param layerName the layer name
* @param filter the filter
* @param email the email
* @param outputFormat the output format
* @param targetCRS the target crs
* @param roiCRS the roi crs
* @param roi the roi
* @param clip the crop to geometry
* @param targetSizeX the size of the target image along the X axis
* @param targetSizeY the size of the target image along the Y axis
* @param bandIndices the band indices selected for output, in case of raster input
* @param progressListener the progress listener
* @return the boolean
*/
@DescribeResult(name = "result", description = "Download Limits are respected or not!")
public Boolean execute(
@DescribeParameter(name = "layerName", min = 1, description = "Original layer to download") String layerName,
@DescribeParameter(name = "filter", min = 0, description = "Optional Vectorial Filter") Filter filter,
@DescribeParameter(name = "targetCRS", min = 0, description = "Target CRS") CoordinateReferenceSystem targetCRS,
@DescribeParameter(name = "RoiCRS", min = 0, description = "Region Of Interest CRS") CoordinateReferenceSystem roiCRS,
@DescribeParameter(name = "ROI", min = 0, description = "Region Of Interest") Geometry roi,
@DescribeParameter(name = "cropToROI", min = 0, description = "Crop to ROI") Boolean clip,
@DescribeParameter(name = "targetSizeX", min = 0, minValue = 1, description = "X Size of the Target Image (applies to raster data only)") Integer targetSizeX,
@DescribeParameter(name = "targetSizeY", min = 0, minValue = 1, description = "Y Size of the Target Image (applies to raster data only)") Integer targetSizeY,
@DescribeParameter(name = "selectedBands", description = "Band Selection Indices", min = 0) int[] bandIndices,
ProgressListener progressListener) throws Exception {
//
// initial checks on mandatory params
//
// layer name
if (layerName == null || layerName.length() <= 0) {
throw new IllegalArgumentException("Empty or null layerName provided!");
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Estimator process called on resource: " + layerName);
}
if (clip == null) {
clip = false;
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Clipping disabled");
}
}
if (roi != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "ROI present");
}
DownloadUtilities.checkPolygonROI(roi);
if (roiCRS == null) {
throw new IllegalArgumentException("ROI without a CRS is not usable!");
}
roi.setUserData(roiCRS);
}
//
// Move on with the real code
//
// checking for the resources on the GeoServer catalog
LayerInfo layerInfo = catalog.getLayerByName(layerName);
if (layerInfo == null) {
// could not find any layer ... abruptly interrupt the process
throw new IllegalArgumentException("Unable to locate layer: " + layerName);
}
ResourceInfo resourceInfo = layerInfo.getResource();
if (resourceInfo == null) {
// could not find any data store associated to the specified layer ... abruptly interrupt the process
throw new IllegalArgumentException("Unable to locate ResourceInfo for layer:"
+ layerName);
}
//
// Get curent limits
//
DownloadServiceConfiguration limits = downloadServiceConfigurationGenerator
.getConfiguration();
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Getting configuration limits");
}
// ////
// 1. DataStore -> look for vectorial data download
// 2. CoverageStore -> look for raster data download
// ////
if (resourceInfo instanceof FeatureTypeInfo) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Working with Vectorial dataset");
}
final FeatureTypeInfo featureTypeInfo = (FeatureTypeInfo) resourceInfo;
return new VectorEstimator(limits).execute(featureTypeInfo, roi, clip, filter,
targetCRS, progressListener);
} else if (resourceInfo instanceof CoverageInfo) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Working with Raster dataset");
}
final CoverageInfo coverage = (CoverageInfo) resourceInfo;
return new RasterEstimator(limits).execute(progressListener, coverage, roi, targetCRS,
clip, filter, targetSizeX, targetSizeY, bandIndices);
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Working with a wrong Resource");
}
// the requested layer is neither a featuretype nor a coverage --> error
final ProcessException ex = new ProcessException(
"Could not complete the Download Process: target resource is of Illegal type --> "
+ resourceInfo != null ? resourceInfo.getClass().getCanonicalName()
: "null");
// Notify the listener if present
if (progressListener != null) {
progressListener.exceptionOccurred(ex);
}
throw ex;
}
/**
* @return the {@link DownloadServiceConfiguration} containing the limits to check
*/
public DownloadServiceConfiguration getDownloadServiceConfiguration() {
return downloadServiceConfigurationGenerator.getConfiguration();
}
}