/* (c) 2014-2015 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.wcs.responses;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.geoserver.config.GeoServer;
import org.geoserver.platform.ServiceException;
import org.geoserver.wcs2_0.response.GranuleStack;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.imageio.netcdf.utilities.NetCDFUtilities;
import org.geotools.util.logging.Logging;
import ucar.ma2.InvalidRangeException;
/**
* {@link CoverageResponseDelegate} implementation for NetCDF multidimensional Grids
*
* @author Daniele Romagnoli, GeoSolutions SAS
*/
public class NetCDFCoverageResponseDelegate extends BaseCoverageResponseDelegate implements
CoverageResponseDelegate {
public static final Logger LOGGER = Logging.getLogger("org.geoserver.wcs.responses.NetCDFCoverageResponseDelegate");
@SuppressWarnings("serial")
public NetCDFCoverageResponseDelegate(GeoServer geoserver) {
super(geoserver, Arrays.asList(NetCDFUtilities.NETCDF), // output formats
new HashMap<String, String>() { // file extensions
{
put(NetCDFUtilities.NETCDF, "nc");
put(NetCDFUtilities.NETCDF.toLowerCase(), "nc");
put(NetCDFUtilities.NETCDF.toUpperCase(), "nc");
put(NetCDFUtilities.NETCDF3_MIMETYPE, "nc");
put(NetCDFUtilities.NETCDF4_MIMETYPE, "nc");
}
}, new HashMap<String, String>() { // mime types
{
put(NetCDFUtilities.NETCDF, NetCDFUtilities.NETCDF3_MIMETYPE);
put(NetCDFUtilities.NETCDF.toLowerCase(), NetCDFUtilities.NETCDF3_MIMETYPE);
put(NetCDFUtilities.NETCDF.toUpperCase(), NetCDFUtilities.NETCDF3_MIMETYPE);
put(NetCDFUtilities.NETCDF4, NetCDFUtilities.NETCDF4_MIMETYPE);
put(NetCDFUtilities.NETCDF4.toLowerCase(), NetCDFUtilities.NETCDF4_MIMETYPE);
put(NetCDFUtilities.NETCDF4.toUpperCase(), NetCDFUtilities.NETCDF4_MIMETYPE);
}
});
}
public void encode(GridCoverage2D sourceCoverage, String outputFormat,
Map<String, String> encodingParameters, OutputStream output) throws ServiceException,
IOException {
if (sourceCoverage == null) {
throw new IllegalStateException(new StringBuffer(
"It seems prepare() has not been called").append(" or has not succeed")
.toString());
}
if (!(sourceCoverage instanceof GranuleStack)) {
throw new IllegalArgumentException(
"NetCDF encoding only supports granuleStack coverages");
}
GranuleStack granuleStack = (GranuleStack) sourceCoverage;
File tempFile = null;
NetCDFOutputManager manager = null;
try {
tempFile = File.createTempFile("tempNetCDF", ".nc");
manager = new NetCDFOutputManager(granuleStack, tempFile, encodingParameters, outputFormat);
manager.write();
streamBack(tempFile, output);
} catch (InvalidRangeException e) {
throw new IOException(e);
} finally {
sourceCoverage.dispose(true);
boolean deleted = FileUtils.deleteQuietly(tempFile);
if (!deleted) {
LOGGER.warning("Could not delete temp file: " + tempFile.getAbsolutePath());
}
if (manager != null) {
manager.close();
}
}
}
/**
* Stream back the content of the temporary file to the output stream
* @param file the temporary file containing the NetCDF output.
* @param output the outputStream where to write the output
* @throws IOException
*/
private void streamBack(final File file, final OutputStream output) throws IOException {
final byte[] buffer = new byte[8 * 1024];
if (file.exists()) {
final InputStream in = new FileInputStream(file);
int c;
try {
while (-1 != (c = in.read(buffer))) {
output.write(buffer, 0, c);
}
} finally {
in.close();
}
}
output.flush();
}
}