All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.ft2.coverage.remote.CdmrCoverageReader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */
package ucar.nc2.ft2.coverage.remote;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Formatter;
import java.util.List;
import java.util.Map;
import java.util.zip.InflaterInputStream;

import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;
import org.apache.http.Header;
import ucar.httpservices.HTTPFactory;
import ucar.httpservices.HTTPMethod;
import ucar.httpservices.HTTPSession;
import ucar.ma2.Array;
import ucar.nc2.ft2.coverage.CoordAxisReader;
import ucar.nc2.ft2.coverage.Coverage;
import ucar.nc2.ft2.coverage.CoverageCoordAxis;
import ucar.nc2.ft2.coverage.CoverageCoordSys;
import ucar.nc2.ft2.coverage.CoverageReader;
import ucar.nc2.ft2.coverage.GeoReferencedArray;
import ucar.nc2.ft2.coverage.SubsetParams;
import ucar.nc2.stream.NcStream;
import ucar.nc2.stream.NcStreamReader;

/**
 * Client side cdmrFeature interface to GridCoverage.
 * This class handles reading the data, or the coordinates when the values are deferred.
 *
 * @author caron
 * @since 5/5/2015
 */
public class CdmrCoverageReader implements CoverageReader, CoordAxisReader {
  private Escaper urlParamEscaper = UrlEscapers.urlFormParameterEscaper();

  String endpoint;
  HTTPSession httpClient;
  boolean showCompression = true;
  boolean showRequest = true;

  CdmrCoverageReader(String endpoint, HTTPSession httpClient) throws IOException {
    this.endpoint = endpoint;
    this.httpClient = httpClient;
  }

  @Override
  public void close() throws IOException {
    httpClient.close();
  }

  @Override
  public String getLocation() {
    return endpoint;
  }

  @Override
  public GeoReferencedArray readData(Coverage coverage, SubsetParams subset, boolean canonicalOrder) throws IOException {
    if (httpClient == null)
      httpClient = HTTPFactory.newSession(endpoint); // LOOK is this ok? no authentication...

    Formatter f = new Formatter();
    f.format("%s?", endpoint);
    subset.encodeForCdmrfDataRequest(f, coverage.getName());

    if (showRequest)
      System.out.printf("CdmrFeature data request for gridCoverage: %s%n url=%s", coverage.getName(), f);

    long start = System.currentTimeMillis();
    try (HTTPMethod method = HTTPFactory.Get(httpClient, f.toString())) {
      int statusCode = method.execute();

      if (statusCode == 404)
        throw new FileNotFoundException(getErrorMessage(method));

      if (statusCode >= 300)
        throw new IOException(getErrorMessage(method));

      int readLen = 0;
      Header h = method.getResponseHeader("Content-Length");
      if (h != null) {
        String s = h.getValue();
        readLen = Integer.parseInt(s);
      }

      CdmrfReader cdmrfReader = new CdmrfReader(endpoint);
      InputStream is = method.getResponseAsStream();
      if (!NcStream.readAndTest(is, NcStream.MAGIC_DATACOV))
        throw new IOException("Data transfer corrupted");

      // read Data message
      int psize = NcStream.readVInt(is);
      if (psize < 0 || (psize > readLen && readLen > 0))
        throw new IOException("Data transfer corrupted");

      byte[] dp = new byte[psize];
      NcStream.readFully(is, dp);
      CdmrFeatureProto.CoverageDataResponse dproto = CdmrFeatureProto.CoverageDataResponse.parseFrom(dp);
      CoverageDataResponse dataResponse = cdmrfReader.decodeDataResponse(dproto);

      List geoArrays = dataResponse.arrayResponse;
      assert geoArrays.size() == 1; // LOOK maybe need readData(List) returns List ?

      if (showRequest)
        System.out.printf(" took %d msecs%n", System.currentTimeMillis()-start);

      return geoArrays.get(0);
    }
  }

  public GeoReferencedArray readData(CoverageDataResponse dataResponse, GeoArrayResponse arrayResponse, InputStream is) throws IOException {
    int sizeIn  = NcStream.readVInt(is);  // not used ?

    if (arrayResponse.deflate) {
      is = new InflaterInputStream(is);
      float ratio = (sizeIn == 0) ? 0.0f : ((float) arrayResponse.uncompressedSize) / sizeIn;
      if (showCompression) System.out.printf("  readData data message compress= %d decompress=%d compress=%f%n", sizeIn, arrayResponse.uncompressedSize, ratio);
    }

    byte[] datab = new byte[(int) arrayResponse.uncompressedSize];
    NcStream.readFully(is, datab);
    Array data = Array.factory(arrayResponse.dataType, arrayResponse.shape, ByteBuffer.wrap(datab));

    CoverageCoordSys csys = dataResponse.findCoordSys( arrayResponse.coordSysName);
    if (csys == null) throw new IOException("Misformed response - no coordsys");
    return new GeoReferencedArray(arrayResponse.coverageName, arrayResponse.dataType, data, csys);
  }

  private static String getErrorMessage(HTTPMethod method) {
    String path = method.getURI().toString();
    String status = method.getStatusLine();
    String content = method.getResponseAsString();
    return (content == null) ? path+" "+status : path+" "+status +"\n "+content;
  }

  @Override
  public double[] readCoordValues(CoverageCoordAxis coordAxis) throws IOException {
    if (httpClient == null)
      httpClient = HTTPFactory.newSession(endpoint); // LOOK is this ok? no authentication...

    Formatter f = new Formatter();
    f.format("%s?req=coord&var=%s", endpoint, urlParamEscaper.escape(coordAxis.getName()));

    if (showRequest)
      System.out.printf("CdmrFeature data request for gridCoverage: %s%n url=%s", coordAxis.getName(), f);

    long start = System.currentTimeMillis();
    try (HTTPMethod method = HTTPFactory.Get(httpClient, f.toString())) {
      int statusCode = method.execute();

      if (statusCode == 404)
        throw new FileNotFoundException(getErrorMessage(method));

      if (statusCode >= 300)
        throw new IOException(getErrorMessage(method));

      InputStream is = method.getResponseAsStream();

      NcStreamReader reader = new NcStreamReader();
      NcStreamReader.DataResult result = reader.readData(is, null, endpoint);

      if (showRequest)
        System.out.printf(" took %d msecs%n", System.currentTimeMillis()-start);

      return (double []) result.data.getStorage();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy