/* (c) 2014 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.response;
import static org.geoserver.ows.util.ResponseUtils.appendPath;
import static org.geoserver.ows.util.ResponseUtils.buildURL;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import javax.xml.transform.TransformerException;
import net.opengis.wcs11.GetCoverageType;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.Response;
import org.geoserver.ows.URLMangler.URLType;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.Operation;
import org.geoserver.platform.ServiceException;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geoserver.wcs.WCSInfo;
import org.geoserver.wcs.responses.CoverageResponseDelegate;
import org.geoserver.wcs.responses.CoverageResponseDelegateFinder;
import org.geotools.coverage.grid.GridCoverage2D;
import org.opengis.coverage.grid.GridCoverage;
import org.vfny.geoserver.wcs.WcsException;
/**
* Response object for the store=true path, that is, one that stores the coverage
* on disk and returns its path thru the Coverages document
* @author Andrea Aime - TOPP
*/
public class WCSGetCoverageStoreResponse extends Response {
GeoServer geoServer;
Catalog catalog;
CoverageResponseDelegateFinder responseFactory;
public WCSGetCoverageStoreResponse(GeoServer gs, CoverageResponseDelegateFinder responseFactory) {
super(GridCoverage[].class);
this.geoServer = gs;
this.catalog = gs.getCatalog();
this.responseFactory = responseFactory;
}
@Override
public String getMimeType(Object value, Operation operation) throws ServiceException {
return "application/xml";
}
@Override
public boolean canHandle(Operation operation) {
// this one can handle GetCoverage responses where store = false
if(!(operation.getParameters()[0] instanceof GetCoverageType))
return false;
GetCoverageType getCoverage = (GetCoverageType) operation.getParameters()[0];
return getCoverage.getOutput().isStore();
}
@Override
public void write(Object value, OutputStream output, Operation operation) throws IOException,
ServiceException {
GridCoverage[] coverages = (GridCoverage[]) value;
// grab the delegate for coverage encoding
GetCoverageType request = (GetCoverageType) operation.getParameters()[0];
String outputFormat = request.getOutput().getFormat();
CoverageResponseDelegate delegate = responseFactory.encoderFor(outputFormat);
if (delegate == null)
throw new WcsException("Could not find encoder for output format " + outputFormat);
// grab the coverage info for Coverages document encoding
final GridCoverage2D coverage = (GridCoverage2D) coverages[0];
CoverageInfo coverageInfo = catalog.getCoverageByName(request.getIdentifier().getValue());
// write the coverage to temporary storage in the data dir
Resource wcsStore = null;
try {
GeoServerResourceLoader loader = geoServer.getCatalog().getResourceLoader();
wcsStore = loader.get("temp/wcs");
} catch(Exception e) {
throw new WcsException("Could not create the temporary storage directory for WCS");
}
// Make sure we create a file name that's not already there (even if splitting the same nanosecond
// with two requests should not ever happen...)
Resource coverageFile = null;
while(true) {
// TODO: find a way to get good extensions
coverageFile = wcsStore.get(coverageInfo.getName().replace(':', '_') + "_" + System.nanoTime() + "." + delegate.getFileExtension(outputFormat));
if(!Resources.exists(coverageFile))
break;
}
// store the coverage
try (OutputStream os = new BufferedOutputStream(coverageFile.out())) {
delegate.encode(coverage, outputFormat,Collections.EMPTY_MAP, os);
os.flush();
}
System.out.println(coverageFile);
// build the path where the clients will be able to retrieve the coverage files
final String coverageLocation = buildURL(request.getBaseUrl(),
appendPath("temp/wcs", coverageFile.name()), null, URLType.RESOURCE);
// build the response
WCSInfo wcs = geoServer.getService(WCSInfo.class);
CoveragesTransformer tx = new CoveragesTransformer(wcs, request, coverageLocation);
try {
tx.transform(coverageInfo, output);
} catch (TransformerException e) {
throw new WcsException("Failure trying to encode Coverages response", e);
}
}
}