Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: DRDC Ottawa GEOINT 4 : * Purpose: Radarsat Constellation Mission - XML Products (product.xml) driver 5 : * Author: Roberto Caron, MDA 6 : * on behalf of DRDC Ottawa 7 : * 8 : ****************************************************************************** 9 : * Copyright (c) 2020, DRDC Ottawa 10 : * 11 : * Based on the RS2 Dataset Class 12 : * 13 : * SPDX-License-Identifier: MIT 14 : ****************************************************************************/ 15 : 16 : #include "gdal_frmts.h" 17 : #include "gdalplugindriverproxy.h" 18 : 19 : #include "rcmdrivercore.h" 20 : 21 55689 : int RCMDatasetIdentify(GDALOpenInfo *poOpenInfo) 22 : { 23 : /* Check for the case where we're trying to read the calibrated data: */ 24 55689 : if (STARTS_WITH_CI(poOpenInfo->pszFilename, szLayerCalibration) && 25 12 : poOpenInfo->pszFilename[strlen(szLayerCalibration)] == chLayerSeparator) 26 : { 27 12 : return TRUE; 28 : } 29 : 30 55677 : if (poOpenInfo->bIsDirectory) 31 : { 32 4 : const auto IsRCM = [](const std::string &osMDFilename) 33 : { 34 4 : CPLXMLNode *psProduct = CPLParseXMLFile(osMDFilename.c_str()); 35 4 : if (psProduct == nullptr) 36 0 : return FALSE; 37 : 38 : CPLXMLNode *psProductAttributes = 39 4 : CPLGetXMLNode(psProduct, "=product"); 40 4 : if (psProductAttributes == nullptr) 41 : { 42 0 : CPLDestroyXMLNode(psProduct); 43 0 : return FALSE; 44 : } 45 : 46 : /* Check the namespace only, should be rcm */ 47 : const char *szNamespace = 48 4 : CPLGetXMLValue(psProductAttributes, "xmlns", ""); 49 : 50 4 : if (strstr(szNamespace, "rcm") == nullptr) 51 : { 52 : /* Invalid namespace */ 53 0 : CPLDestroyXMLNode(psProduct); 54 0 : return FALSE; 55 : } 56 : 57 4 : CPLDestroyXMLNode(psProduct); 58 4 : return TRUE; 59 : }; 60 : 61 : /* Check for directory access when there is a product.xml file in the 62 : directory. */ 63 : const std::string osMDFilename = CPLFormCIFilenameSafe( 64 560 : poOpenInfo->pszFilename, "product.xml", nullptr); 65 : 66 : VSIStatBufL sStat; 67 280 : if (VSIStatL(osMDFilename.c_str(), &sStat) == 0) 68 : { 69 2 : return IsRCM(osMDFilename); 70 : } 71 : 72 : /* If not, check for directory extra 'metadata' access when there is a 73 : product.xml file in the directory. */ 74 : 75 : const std::string osMDFilenameMetadata = CPLFormCIFilenameSafe( 76 556 : poOpenInfo->pszFilename, GetMetadataProduct(), nullptr); 77 : 78 : VSIStatBufL sStatMetadata; 79 278 : if (VSIStatL(osMDFilenameMetadata.c_str(), &sStatMetadata) == 0) 80 : { 81 2 : return IsRCM(osMDFilenameMetadata); 82 : } 83 : 84 276 : return FALSE; 85 : } 86 : 87 : /* otherwise, do our normal stuff */ 88 55397 : if (strlen(poOpenInfo->pszFilename) < 11 || 89 53581 : !EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 11, 90 : "product.xml")) 91 55394 : return FALSE; 92 : 93 3 : if (poOpenInfo->nHeaderBytes < 100) 94 0 : return FALSE; 95 : 96 : /* The RCM schema location is rcm_prod_product.xsd */ 97 3 : const char *pszHeader = 98 : reinterpret_cast<const char *>(poOpenInfo->pabyHeader); 99 3 : return strstr(pszHeader, "/rcm") && strstr(pszHeader, "<product"); 100 : } 101 : 102 : /************************************************************************/ 103 : /* RCMDriverSetCommonMetadata() */ 104 : /************************************************************************/ 105 : 106 1755 : void RCMDriverSetCommonMetadata(GDALDriver *poDriver) 107 : { 108 1755 : poDriver->SetDescription(RCM_DRIVER_NAME); 109 1755 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); 110 1755 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 111 1755 : "Radarsat Constellation Mission XML Product"); 112 1755 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rcm.html"); 113 1755 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); 114 1755 : poDriver->pfnIdentify = RCMDatasetIdentify; 115 1755 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 116 1755 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 117 1755 : } 118 : 119 : /************************************************************************/ 120 : /* DeclareDeferredRCMPlugin() */ 121 : /************************************************************************/ 122 : 123 : #ifdef PLUGIN_FILENAME 124 : void DeclareDeferredRCMPlugin() 125 : { 126 : if (GDALGetDriverByName(RCM_DRIVER_NAME) != nullptr) 127 : { 128 : return; 129 : } 130 : 131 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); 132 : #ifdef PLUGIN_INSTALLATION_MESSAGE 133 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, 134 : PLUGIN_INSTALLATION_MESSAGE); 135 : #endif 136 : RCMDriverSetCommonMetadata(poDriver); 137 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 138 : } 139 : #endif