org.geoserver.wps.gs.download.DownloadProcessTest.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.wps.gs.download.DownloadProcessTest.java

Source

/* (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.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.data.util.IOUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.wcs.CoverageCleanerCallback;
import org.geoserver.wps.ProcessEvent;
import org.geoserver.wps.WPSTestSupport;
import org.geoserver.wps.executor.ExecutionStatus;
import org.geoserver.wps.executor.ProcessState;
import org.geoserver.wps.ppio.WFSPPIO;
import org.geoserver.wps.ppio.ZipArchivePPIO;
import org.geoserver.wps.resource.WPSResourceManager;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.data.DataUtilities;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.NameImpl;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKTReader2;
import org.geotools.process.ProcessException;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.resources.coverage.CoverageUtilities;
import org.geotools.util.DefaultProgressListener;
import org.geotools.util.NullProgressListener;
import org.geotools.util.logging.Logging;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.util.InternationalString;
import org.opengis.util.ProgressListener;

import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.ParseException;

/**
 * This class tests checks if the DownloadProcess class behaves correctly.
 * 
 * @author "Alessio Fabiani - alessio.fabiani@geo-solutions.it"
 */
public class DownloadProcessTest extends WPSTestSupport {

    /**
     * This method is used for decoding an input file.
     * 
     * @param input the input stream to decode
     * @param tempDirectory temporary directory on where the file is decoded.
     * @return the object the decoded file
     * @throws Exception the exception TODO review
     */
    public static File decode(InputStream input, File tempDirectory) throws Exception {

        // unzip to the temporary directory
        ZipInputStream zis = null;
        try {
            zis = new ZipInputStream(input);
            ZipEntry entry = null;

            // Copy the whole file in the new position
            while ((entry = zis.getNextEntry()) != null) {
                File file = new File(tempDirectory, entry.getName());
                if (entry.isDirectory()) {
                    file.mkdir();
                } else {
                    int count;
                    byte data[] = new byte[4096];
                    // write the files to the disk
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(file);
                        while ((count = zis.read(data)) != -1) {
                            fos.write(data, 0, count);
                        }
                        fos.flush();
                    } finally {
                        if (fos != null) {
                            org.apache.commons.io.IOUtils.closeQuietly(fos);
                        }
                    }
                }
                zis.closeEntry();
            }
        } finally {
            if (zis != null) {
                org.apache.commons.io.IOUtils.closeQuietly(zis);
            }
        }

        return tempDirectory;
    }

    /** Test ROI used */
    final static Polygon roi;

    static {
        try {
            roi = (Polygon) new WKTReader2().read(
                    "POLYGON (( 500116.08576537756 499994.25579707103, 500116.08576537756 500110.1012210889, 500286.2657688021 500110.1012210889, 500286.2657688021 499994.25579707103, 500116.08576537756 499994.25579707103 ))");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void onSetUp(SystemTestData testData) throws Exception {
        super.onSetUp(testData);
        testData.addRasterLayer(MockData.USA_WORLDIMG, "usa.zip", MockData.PNG, getCatalog());
    }

    @Override
    protected void setUpTestData(SystemTestData testData) throws Exception {
        super.setUpTestData(testData);
        // add limits properties file
        testData.copyTo(DownloadProcessTest.class.getClassLoader()
                .getResourceAsStream("download-process/download.properties"), "download.properties");
    }

    @Before
    public void clearPolygons() throws IOException {
        revertLayer(MockData.POLYGONS);
    }

    /**
     * Test get features as shapefile.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testGetFeaturesAsShapefile() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(MockData.POLYGONS));
        SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null, null).getFeatures();
        // Download
        File shpeZip = downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                null, // mail
                "application/zip", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:32615"), // roiCRS
                roi, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(shpeZip);

        SimpleFeatureCollection rawTarget = (SimpleFeatureCollection) decodeShape(new FileInputStream(shpeZip));

        Assert.assertNotNull(rawTarget);

        Assert.assertEquals(rawSource.size(), rawTarget.size());
    }

    /**
     * Test downloading with a duplicate style
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadWithDuplicateStyle() throws Exception {
        String polygonsName = getLayerId(MockData.POLYGONS);
        LayerInfo li = getCatalog().getLayerByName(polygonsName);
        // setup an alternative equal to the main style
        li.getStyles().add(li.getDefaultStyle());
        getCatalog().save(li);

        testGetFeaturesAsShapefile();
    }

    /**
     * Test filtered clipped features.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testFilteredClippedFeatures() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI object
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON ((0.0008993124415341 0.0006854377923293, 0.0008437876520112 0.0006283489242283, 0.0008566913002806 0.0005341131898971, 0.0009642217025257 0.0005188634237605, 0.0011198475210477 0.000574779232928, 0.0010932581852198 0.0006572843779233, 0.0008993124415341 0.0006854377923293))");

        FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(MockData.BUILDINGS));
        SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null, null).getFeatures();

        // Download
        File shpeZip = downloadProcess.execute(getLayerId(MockData.BUILDINGS), // layerName
                CQL.toFilter("ADDRESS = '123 Main Street'"), // filter
                "application/zip", // outputFormat
                null, // targetCRS
                DefaultGeographicCRS.WGS84, // roiCRS
                roi, // roi
                true, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(shpeZip);

        SimpleFeatureCollection rawTarget = (SimpleFeatureCollection) decodeShape(new FileInputStream(shpeZip));

        Assert.assertNotNull(rawTarget);

        Assert.assertEquals(1, rawTarget.size());

        SimpleFeature srcFeature = rawSource.features().next();
        SimpleFeature trgFeature = rawTarget.features().next();

        Assert.assertEquals(srcFeature.getAttribute("ADDRESS"), trgFeature.getAttribute("ADDRESS"));

        // Final checks on the ROI
        Geometry srcGeometry = (Geometry) srcFeature.getDefaultGeometry();
        Geometry trgGeometry = (Geometry) trgFeature.getDefaultGeometry();

        Assert.assertTrue("Target geometry clipped and included into the source one",
                srcGeometry.contains(trgGeometry));
    }

    /**
     * Test get features as gml.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testGetFeaturesAsGML() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(MockData.POLYGONS));
        SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null, null).getFeatures();

        // Download as GML 2
        File gml2Zip = downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                null, // filter
                "application/wfs-collection-1.0", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:32615"), // roiCRS
                roi, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(gml2Zip);

        File[] files = exctractGMLFile(gml2Zip);

        SimpleFeatureCollection rawTarget = (SimpleFeatureCollection) new WFSPPIO.WFS10()
                .decode(new FileInputStream(files[0]));

        Assert.assertNotNull(rawTarget);

        Assert.assertEquals(rawSource.size(), rawTarget.size());

        // Download as GML 3
        File gml3Zip = downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                null, // filter
                "application/wfs-collection-1.1", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:32615"), // roiCRS
                roi, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(gml3Zip);

        files = exctractGMLFile(gml2Zip);

        rawTarget = (SimpleFeatureCollection) new WFSPPIO.WFS11().decode(new FileInputStream(files[0]));

        Assert.assertNotNull(rawTarget);

        Assert.assertEquals(rawSource.size(), rawTarget.size());
    }

    /**
     * This method is used for extracting only the xml file from a GML output file
     * 
     * @param gml2Zip
     *
     * @throws IOException
     */
    private File[] exctractGMLFile(File gml2Zip) throws IOException {
        IOUtils.decompress(gml2Zip, gml2Zip.getParentFile());

        File[] files = gml2Zip.getParentFile().listFiles(new FilenameFilter() {

            public boolean accept(File dir, String name) {
                return FilenameUtils.getExtension(name).equalsIgnoreCase("xml");
            }
        });
        return files;
    }

    /**
     * This method is used for extracting only the json file from a JSON output file
     * 
     * @param jsonZip
     *
     * @throws IOException
     */
    private File[] exctractJSONFile(File jsonZip) throws IOException {
        IOUtils.decompress(jsonZip, jsonZip.getParentFile());

        File[] files = jsonZip.getParentFile().listFiles(new FilenameFilter() {

            public boolean accept(File dir, String name) {
                return FilenameUtils.getExtension(name).equalsIgnoreCase("json");
            }
        });
        return files;
    }

    /**
     * This method is used for extracting only the tiff file from a Tiff/GeoTiff output file
     * 
     * @param gtiffZip
     *
     * @throws IOException
     */
    private File[] extractTIFFFile(final File gtiffZip) throws IOException {
        IOUtils.decompress(gtiffZip, gtiffZip.getParentFile());

        File[] files = gtiffZip.getParentFile().listFiles(new FilenameFilter() {

            public boolean accept(File dir, String name) {
                return

                (FilenameUtils.getExtension(name).equalsIgnoreCase("tif")
                        || FilenameUtils.getExtension(name).equalsIgnoreCase("tiff")
                        || FilenameUtils.getExtension(name).equalsIgnoreCase("geotiff"));
            }
        });
        return files;
    }

    /**
     * Test get features as geo json.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testGetFeaturesAsGeoJSON() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(MockData.POLYGONS));
        SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null, null).getFeatures();
        // Download the file as Json
        File jsonZip = downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                null, // filter
                "application/json", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:32615"), // roiCRS
                roi, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );
        // Final checks on the result
        Assert.assertNotNull(jsonZip);

        File[] files = exctractJSONFile(jsonZip);

        SimpleFeatureCollection rawTarget = (SimpleFeatureCollection) new FeatureJSON()
                .readFeatureCollection(new FileInputStream(files[0]));

        Assert.assertNotNull(rawTarget);

        Assert.assertEquals(rawSource.size(), rawTarget.size());
    }

    /**
     * Test download of raster data.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        // test ROI
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.88669845369998 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);
        // ROI reprojection
        Polygon roiResampled = (Polygon) JTS.transform(roi,
                CRS.findMathTransform(CRS.decode("EPSG:4326", true), CRS.decode("EPSG:900913", true)));
        // Download the coverage as tiff (Not reprojected)
        File rasterZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                roi, // roi
                true, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(rasterZip);
        GeoTiffReader reader = null;
        GridCoverage2D gc = null, gcResampled = null;
        try {
            final File[] tiffFiles = extractTIFFFile(rasterZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            Assert.assertEquals(-130.88669845369998, gc.getEnvelope().getLowerCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(48.611129008700004, gc.getEnvelope().getLowerCorner().getOrdinate(1), 1E-6);
            Assert.assertEquals(-123.95304462109999, gc.getEnvelope().getUpperCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(54.0861661371, gc.getEnvelope().getUpperCorner().getOrdinate(1), 1E-6);

        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }
        // Download the coverage as tiff (Reprojected)
        File resampledZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                CRS.decode("EPSG:900913", true), // targetCRS
                CRS.decode("EPSG:900913", true), // roiCRS
                roiResampled, // roi
                true, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );
        // Final checks on the result
        Assert.assertNotNull(resampledZip);

        try {
            File[] files = extractTIFFFile(resampledZip);
            reader = new GeoTiffReader(files[files.length - 1]);
            gcResampled = reader.read(null);

            Assert.assertNotNull(gcResampled);

            Assert.assertEquals(-1.457024062347863E7, gcResampled.getEnvelope().getLowerCorner().getOrdinate(0),
                    1E-6);
            Assert.assertEquals(6209706.404894806, gcResampled.getEnvelope().getLowerCorner().getOrdinate(1), 1E-6);
            Assert.assertEquals(-1.379838980949677E7, gcResampled.getEnvelope().getUpperCorner().getOrdinate(0),
                    1E-6);
            Assert.assertEquals(7187128.139081598, gcResampled.getEnvelope().getUpperCorner().getOrdinate(1), 1E-6);

        } finally {

            if (gcResampled != null) {
                CoverageCleanerCallback.disposeCoverage(gcResampled);
            }
            if (reader != null)

                reader.dispose();
            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }

    }

    /**
     * Test download of selected bands of raster data. Result contains only bands 0 and 2.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadRasterSelectedBands() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        ///////////////////////////////////////
        //      test full coverage           //
        ///////////////////////////////////////

        // Download the coverage as tiff
        File rasterZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                null, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                new int[] { 0, 2 }, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(rasterZip);
        GeoTiffReader reader = null;
        GridCoverage2D gc = null;
        try {
            final File[] tiffFiles = extractTIFFFile(rasterZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // check bands
            Assert.assertEquals(2, gc.getNumSampleDimensions());

            // check visible band index for new coverage
            Assert.assertEquals(0, CoverageUtilities.getVisibleBand(gc));

            // check non existing band index
            Assert.assertNotEquals(3, gc.getNumSampleDimensions());

        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }
    }

    /**
     * Test download of selected bands of raster data, scald and using a ROI area. 
     * Result contains only band 1.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadRasterSelectedBandsScaledWithROI() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        ///////////////////////////////////////
        //      test full coverage           //
        ///////////////////////////////////////

        Polygon roi = (Polygon) new WKTReader2().read("POLYGON (( " + "-127.57473954542964 54.06575021619523, "
                + "-130.88669845369998 52.00807146727025, " + "-129.50812897394974 49.85372324691927, "
                + "-130.5300633861675 49.20465679591609, " + "-129.25955033314003 48.60392508062591, "
                + "-128.00975216684665 50.986137055052474, " + "-125.8623089087404 48.63154492960477, "
                + "-123.984159178178 50.68231871628503, " + "-126.91186316993704 52.15307567440926, "
                + "-125.3444367403868 53.54787804784162, " + "-127.57473954542964 54.06575021619523 " + "))");
        roi.setSRID(4326);

        // Download the coverage as tiff
        File rasterZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                roi, // roi
                false, // cropToGeometry
                null, // interpolation
                40, // targetSizeX
                40, // targetSizeY
                new int[] { 1 }, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(rasterZip);
        GeoTiffReader reader = null;
        GridCoverage2D gc = null;
        try {
            final File[] tiffFiles = extractTIFFFile(rasterZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // check bands
            Assert.assertEquals(1, gc.getNumSampleDimensions());

            Rectangle2D originalGridRange = (GridEnvelope2D) reader.getOriginalGridRange();
            Assert.assertEquals(40, Math.round(originalGridRange.getWidth()));
            Assert.assertEquals(40, Math.round(originalGridRange.getHeight()));

            // check envelope
            Assert.assertEquals(-130.88669845369998, gc.getEnvelope().getLowerCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(48.611129008700004, gc.getEnvelope().getLowerCorner().getOrdinate(1), 1E-6);
            Assert.assertEquals(-123.95304462109999, gc.getEnvelope().getUpperCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(54.0861661371, gc.getEnvelope().getUpperCorner().getOrdinate(1), 1E-6);

        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }
    }

    /**
     * Test download of raster data. The output is scaled to fit exactly the provided size.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadScaledRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        ///////////////////////////////////////
        //      test full coverage           //
        ///////////////////////////////////////

        // Download the coverage as tiff
        File rasterZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                null, // roi
                false, // cropToGeometry
                null, // interpolation
                80, // targetSizeX
                80, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(rasterZip);
        GeoTiffReader reader = null;
        GridCoverage2D gc = null;
        try {
            final File[] tiffFiles = extractTIFFFile(rasterZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // check coverage size
            Rectangle2D originalGridRange = (GridEnvelope2D) reader.getOriginalGridRange();
            Assert.assertEquals(80, Math.round(originalGridRange.getWidth()));
            Assert.assertEquals(80, Math.round(originalGridRange.getHeight()));

            // check envelope
            Assert.assertEquals(-130.8866985, gc.getEnvelope().getLowerCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(48.5552613, gc.getEnvelope().getLowerCorner().getOrdinate(1), 1E-6);
            Assert.assertEquals(-123.8830077, gc.getEnvelope().getUpperCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(54.1420339, gc.getEnvelope().getUpperCorner().getOrdinate(1), 1E-6);
        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }

        ///////////////////////////////////////
        //      test partial input           //
        ///////////////////////////////////////

        // Download the coverage as tiff
        File largerZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                null, // roi
                false, // cropToGeometry
                null, // interpolation
                160, // targetSizeX
                null, // targetSizeY not specified, will be calculated based on targetSizeX and aspect ratio of the original image
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(largerZip);
        try {
            final File[] tiffFiles = extractTIFFFile(largerZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // check coverage size
            Rectangle2D originalGridRange = (GridEnvelope2D) reader.getOriginalGridRange();
            Assert.assertEquals(160, Math.round(originalGridRange.getWidth()));
            Assert.assertEquals(160, Math.round(originalGridRange.getHeight()));
        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }

        //////////////////////////////////
        //      test with ROI           //
        //////////////////////////////////

        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.88669845369998 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);

        // Download the coverage as tiff
        File resampledZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                roi, // roi
                true, // cropToGeometry
                null, // interpolation
                80, // targetSizeX
                80, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(resampledZip);
        try {
            final File[] tiffFiles = extractTIFFFile(resampledZip);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // check coverage size
            Rectangle2D originalGridRange = (GridEnvelope2D) reader.getOriginalGridRange();
            Assert.assertEquals(80, Math.round(originalGridRange.getWidth()));
            Assert.assertEquals(80, Math.round(originalGridRange.getHeight()));

            // check envelope
            Assert.assertEquals(-130.88669845369998, gc.getEnvelope().getLowerCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(48.611129008700004, gc.getEnvelope().getLowerCorner().getOrdinate(1), 1E-6);
            Assert.assertEquals(-123.95304462109999, gc.getEnvelope().getUpperCorner().getOrdinate(0), 1E-6);
            Assert.assertEquals(54.0861661371, gc.getEnvelope().getUpperCorner().getOrdinate(1), 1E-6);
        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }
    }

    /**
     * PPIO Test.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testZipGeoTiffPPIO() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        ZipArchivePPIO ppio = new ZipArchivePPIO(DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL);
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI as a BBOX
        Envelope env = new Envelope(-125.074006936869, -123.88300771369998, 48.5552612829, 49.03872);
        Polygon roi = JTS.toGeometry(env);

        // Download the data with ROI
        File rasterZip = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326"), // roiCRS
                roi, // roi
                true, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        // Final checks on the result
        Assert.assertNotNull(rasterZip);

        // make sure we create files locally so that we don't clog the sytem temp
        final File currentDirectory = new File(DownloadProcessTest.class.getResource(".").toURI());
        File tempZipFile = File.createTempFile("zipppiotemp", ".zip", currentDirectory);
        ppio.encode(rasterZip, new FileOutputStream(tempZipFile));

        Assert.assertTrue(tempZipFile.length() > 0);

        final File tempDir = new File(currentDirectory, Long.toString(System.nanoTime()));
        Assert.assertTrue(tempDir.mkdir());
        File tempFile = decode(new FileInputStream(tempZipFile), tempDir);
        Assert.assertNotNull(tempFile);
        IOUtils.delete(tempFile);
    }

    /**
     * Test download estimator for raster data. The result should exceed the limits
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadEstimatorReadLimitsRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(
                new DownloadServiceConfiguration(DownloadServiceConfiguration.NO_LIMIT, 10,
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI as polygon
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.8545966116691 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);

        try {
            // Download the data with ROI. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    roi, // roi
                    true, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );
            Assert.assertFalse(true);
        } catch (ProcessException e) {
            Assert.assertEquals(
                    "java.lang.IllegalArgumentException: Download Limits Exceeded. Unable to proceed!: Download Limits Exceeded. Unable to proceed!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        }

    }

    /**
     * Test download estimator write limits raster. The result should exceed the limits
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadEstimatorWriteLimitsRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(
                new StaticDownloadServiceConfiguration(new DownloadServiceConfiguration(
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT, 10, 10,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.88669845369998 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);

        try {
            // Download the data with ROI. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    roi, // roi
                    true, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );

            Assert.assertFalse(true);
        } catch (ProcessException e) {
            Assert.assertEquals(
                    "org.geotools.process.ProcessException: java.io.IOException: Download Exceeded the maximum HARD allowed size!: java.io.IOException: Download Exceeded the maximum HARD allowed size!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        }
    }

    /**
     * Test download estimator write limits raster for scaled output. Scaled image should exceed the limits, whereas the original raster should not.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadEstimatorWriteLimitsScaledRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(
                new DownloadServiceConfiguration(DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT, 921600, // 900KB
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        File nonScaled = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                null, // filter
                "image/tiff", // outputFormat
                null, // targetCRS
                CRS.decode("EPSG:4326", true), // roiCRS
                null, // roi
                false, // cropToGeometry
                null, // interpolation
                null, // targetSizeX
                null, // targetSizeY
                null, // bandSelectIndices
                new NullProgressListener() // progressListener
        );

        Assert.assertNotNull(nonScaled);

        GeoTiffReader reader = null;
        GridCoverage2D gc = null;
        try {
            final File[] tiffFiles = extractTIFFFile(nonScaled);
            Assert.assertNotNull(tiffFiles);
            Assert.assertTrue(tiffFiles.length > 0);
            reader = new GeoTiffReader(tiffFiles[0]);
            gc = reader.read(null);

            Assert.assertNotNull(gc);

            // ten times the size of the original coverage
            int targetSizeX = (int) (gc.getGridGeometry().getGridRange2D().getWidth() * 10);
            int targetSizeY = (int) (gc.getGridGeometry().getGridRange2D().getHeight() * 10);
            downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    null, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    targetSizeX, // targetSizeX
                    targetSizeY, // targetSizeY
                    null, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );

            // exception should have been thrown at this stage
            Assert.assertFalse(true);
        } catch (ProcessException e) {
            Assert.assertEquals(
                    "org.geotools.process.ProcessException: java.io.IOException: Download Exceeded the maximum HARD allowed size!: java.io.IOException: Download Exceeded the maximum HARD allowed size!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        } finally {
            if (gc != null) {
                CoverageCleanerCallback.disposeCoverage(gc);
            }
            if (reader != null) {
                reader.dispose();
            }

            // clean up process
            resourceManager.finished(resourceManager.getExecutionId(true));
        }

        // Test same process for checking write output limits, using selected band indices
        limits = new DownloadEstimatorProcess(
                new StaticDownloadServiceConfiguration(new DownloadServiceConfiguration(
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT, 30000, //= 100x100 pixels x 3 bands x 1 byte (8 bits) per band
                        DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        try {
            // create a scaled 100x100 raster, with 4 bands
            int targetSizeX = 100;
            int targetSizeY = 100;
            int[] bandIndices = new int[] { 0, 2, 2, 2 };
            File scaled = downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    null, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    targetSizeX, // targetSizeX
                    targetSizeY, // targetSizeY
                    bandIndices, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );

            // exception should have been thrown at this stage
            Assert.assertFalse(true);
        } catch (ProcessException e) {
            Assert.assertEquals(
                    "java.lang.IllegalArgumentException: Download Limits Exceeded. "
                            + "Unable to proceed!: Download Limits Exceeded. Unable to proceed!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        }
    }

    /**
     * Test download estimator for raster data. The result should exceed the integer limits
     *
     * @throws Exception the exception
     */
    @Test
    public void testDownloadEstimatorIntegerMaxValueLimitRaster() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(
                new DownloadServiceConfiguration(DownloadServiceConfiguration.NO_LIMIT, (long) 1E12, // huge number, way above integer limits
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI as polygon
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.8545966116691 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);

        try {
            // Download the data with ROI. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    roi, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    100000, // targetSizeX
                    60000, // targetSizeY
                    null, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );
            Assert.fail();
        } catch (ProcessException e) {
            Assert.assertEquals("java.lang.IllegalArgumentException: Download Limits Exceeded. Unable to proceed!",
                    e.getMessage());
        }

    }

    /**
     * Test download estimator for vectorial data. The result should be exceed the hard output limits
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadEstimatorHardOutputLimit() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(
                new DownloadServiceConfiguration(DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT, 10,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        try {
            // Download the features. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                    null, // filter
                    "application/zip", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:32615"), // roiCRS
                    roi, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    new NullProgressListener() // progressListener
            );

            Assert.assertFalse(true);
        } catch (ProcessException e) {
            Assert.assertEquals(
                    "java.io.IOException: Download Exceeded the maximum HARD allowed size!: Download Exceeded the maximum HARD allowed size!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        }
    }

    private WPSResourceManager getResourceManager() {
        return GeoServerExtensions.bean(WPSResourceManager.class);
    }

    /**
     * Test download physical limit for raster data. It should throw an exception
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadPhysicalLimitsRaster() throws Exception {
        final WPSResourceManager resourceManager = getResourceManager();
        ProcessListener listener = new ProcessListener(new ExecutionStatus(new NameImpl("gs", "DownloadEstimator"),
                resourceManager.getExecutionId(false), false));
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());

        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);
        // ROI data
        Polygon roi = (Polygon) new WKTReader2().read(
                "POLYGON (( -127.57473954542964 54.06575021619523, -130.88669845369998 52.00807146727025, -129.50812897394974 49.85372324691927, -130.5300633861675 49.20465679591609, -129.25955033314003 48.60392508062591, -128.00975216684665 50.986137055052474, -125.8623089087404 48.63154492960477, -123.984159178178 50.68231871628503, -126.91186316993704 52.15307567440926, -125.3444367403868 53.54787804784162, -127.57473954542964 54.06575021619523 ))");
        roi.setSRID(4326);

        try {
            // Download the data. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.USA_WORLDIMG), // layerName
                    null, // filter
                    "image/tiff", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:4326", true), // roiCRS
                    roi, // roi
                    true, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    listener // progressListener
            );
        } catch (Exception e) {
            Throwable e1 = listener.exception;
            Assert.assertNotNull(e1);
            Assert.assertEquals(
                    "org.geotools.process.ProcessException: java.io.IOException: Download Exceeded the maximum HARD allowed size!: java.io.IOException: Download Exceeded the maximum HARD allowed size!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));
        }

    }

    /**
     * Test download physical limit for vectorial data. It should throw an exception
     * 
     * @throws Exception the exception
     */
    @Test
    public void testDownloadPhysicalLimitsVector() throws Exception {
        final WPSResourceManager resourceManager = getResourceManager();
        ProcessListener listener = new ProcessListener(new ExecutionStatus(new NameImpl("gs", "DownloadEstimator"),
                resourceManager.getExecutionId(false), false));
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(
                new DownloadServiceConfiguration(DownloadServiceConfiguration.NO_LIMIT,
                        DownloadServiceConfiguration.NO_LIMIT, DownloadServiceConfiguration.NO_LIMIT, 1,
                        DownloadServiceConfiguration.DEFAULT_COMPRESSION_LEVEL)),
                getGeoServer());

        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        try {
            // Download the features. It should throw an exception
            downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                    null, // filter
                    "application/zip", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:32615"), // roiCRS
                    roi, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    listener // progressListener
            );

        } catch (ProcessException e) {
            Assert.assertEquals(
                    "java.io.IOException: Download Exceeded the maximum HARD allowed size!: Download Exceeded the maximum HARD allowed size!",
                    e.getMessage() + (e.getCause() != null ? ": " + e.getCause().getMessage() : ""));

            Throwable le = listener.exception;
            Assert.assertEquals(
                    "java.io.IOException: Download Exceeded the maximum HARD allowed size!: Download Exceeded the maximum HARD allowed size!",
                    le.getMessage() + (le.getCause() != null ? ": " + le.getCause().getMessage() : ""));

            return;
        }

        Assert.assertFalse(true);
    }

    /**
     * Test with a wrong output format. It should thrown an exception.
     * 
     * @throws Exception the exception
     */
    @Test
    public void testWrongOutputFormat() throws Exception {
        // Estimator process for checking limits
        DownloadEstimatorProcess limits = new DownloadEstimatorProcess(new StaticDownloadServiceConfiguration(),
                getGeoServer());
        final WPSResourceManager resourceManager = getResourceManager();
        // Creates the new process for the download
        DownloadProcess downloadProcess = new DownloadProcess(getGeoServer(), limits, resourceManager);

        FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(MockData.POLYGONS));
        SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null, null).getFeatures();

        final DefaultProgressListener progressListener = new DefaultProgressListener();
        try {
            // Download the features. It should throw an exception.
            downloadProcess.execute(getLayerId(MockData.POLYGONS), // layerName
                    null, // filter
                    "IAmWrong!!!", // outputFormat
                    null, // targetCRS
                    CRS.decode("EPSG:32615"), // roiCRS
                    roi, // roi
                    false, // cropToGeometry
                    null, // interpolation
                    null, // targetSizeX
                    null, // targetSizeY
                    null, // bandSelectIndices
                    progressListener // progressListener
            );
            Assert.assertTrue("We did not get an exception", false);
        } catch (Exception e) {
            Assert.assertTrue("Everything as expected", true);
        }
    }

    /**
     * The listener interface for receiving process events. The class that is interested in processing a process event implements this interface, and
     * the object created with that class is registered with a component using the component's <code>addProcessListener<code> method. When
     * the process event occurs, that object's appropriate
     * method is invoked.
     * 
     * @see ProcessEvent
     */
    static class ProcessListener implements ProgressListener {

        /** The Constant LOGGER. */
        static final Logger LOGGER = Logging.getLogger(ProcessListener.class);

        /** The status. */
        ExecutionStatus status;

        /** The task. */
        InternationalString task;

        /** The description. */
        String description;

        /** The exception. */
        Throwable exception;

        /**
         * Instantiates a new process listener.
         * 
         * @param status the status
         */
        public ProcessListener(ExecutionStatus status) {
            this.status = status;
        }

        /**
         * Gets the task.
         * 
         * @return the task
         */
        public InternationalString getTask() {
            return task;
        }

        /**
         * Sets the task.
         * 
         * @param task the new task
         */
        public void setTask(InternationalString task) {
            this.task = task;
        }

        /**
         * Gets the description.
         * 
         * @return the description
         */
        public String getDescription() {
            return this.description;
        }

        /**
         * Sets the description.
         * 
         * @param description the new description
         */
        public void setDescription(String description) {
            this.description = description;

        }

        /**
         * Started.
         */
        public void started() {
            status.setPhase(ProcessState.RUNNING);
        }

        /**
         * Progress.
         * 
         * @param percent the percent
         */
        public void progress(float percent) {
            status.setProgress(percent);
        }

        /**
         * Gets the progress.
         * 
         * @return the progress
         */
        public float getProgress() {
            return status.getProgress();
        }

        /**
         * Complete.
         */
        public void complete() {
            // nothing to do
        }

        /**
         * Dispose.
         */
        public void dispose() {
            // nothing to do
        }

        /**
         * Checks if is canceled.
         * 
         * @return true, if is canceled
         */
        public boolean isCanceled() {
            return status.getPhase() == ProcessState.DISMISSING;
        }

        /**
         * Sets the canceled.
         * 
         * @param cancel the new canceled
         */
        public void setCanceled(boolean cancel) {
            if (cancel == true) {
                status.setPhase(ProcessState.DISMISSING);
            }

        }

        /**
         * Warning occurred.
         * 
         * @param source the source
         * @param location the location
         * @param warning the warning
         */
        public void warningOccurred(String source, String location, String warning) {
            LOGGER.log(Level.WARNING,
                    "Got a warning during process execution " + status.getExecutionId() + ": " + warning);
        }

        /**
         * Exception occurred.
         * 
         * @param exception the exception
         */
        public void exceptionOccurred(Throwable exception) {
            this.exception = exception;
        }

    }

    /**
     * Private method for decoding a Shapefile
     * 
     * @param input the input shp
     * @return the object a {@link SimpleFeatureCollection} object related to the shp file.
     * @throws Exception the exception
     */
    private Object decodeShape(InputStream input) throws Exception {
        // create the temp directory and register it as a temporary resource
        File tempDir = IOUtils.createRandomDirectory(IOUtils.createTempDirectory("shpziptemp").getAbsolutePath(),
                "download-process", "download-services");

        // unzip to the temporary directory
        ZipInputStream zis = null;
        File shapeFile = null;
        File zipFile = null;

        // extract shp-zip file
        try {
            zis = new ZipInputStream(input);
            ZipEntry entry = null;

            // Cycle on all the entries and copies the input shape in the target directory
            while ((entry = zis.getNextEntry()) != null) {
                String name = entry.getName();
                File file = new File(tempDir, entry.getName());
                if (entry.isDirectory()) {
                    file.mkdir();
                } else {

                    if (file.getName().toLowerCase().endsWith(".shp")) {
                        shapeFile = file;
                    } else if (file.getName().toLowerCase().endsWith(".zip")) {
                        zipFile = file;
                    }

                    int count;
                    byte data[] = new byte[4096];
                    // write the files to the disk
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(file);
                        while ((count = zis.read(data)) != -1) {
                            fos.write(data, 0, count);
                        }
                        fos.flush();
                    } finally {
                        if (fos != null) {
                            fos.close();
                        }
                    }

                }
                zis.closeEntry();
            }
        } finally {
            if (zis != null) {
                zis.close();
            }
        }

        // Read the shapefile
        if (shapeFile == null) {
            if (zipFile != null)
                return decodeShape(new FileInputStream(zipFile));
            else {
                FileUtils.deleteDirectory(tempDir);
                throw new IOException("Could not find any file with .shp extension in the zip file");
            }
        } else {
            ShapefileDataStore store = new ShapefileDataStore(DataUtilities.fileToURL(shapeFile));
            return store.getFeatureSource().getFeatures();
        }
    }
}