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