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 48340 : int RCMDatasetIdentify(GDALOpenInfo *poOpenInfo) 19 : { 20 : /* Check for the case where we're trying to read the calibrated data: */ 21 48340 : if (STARTS_WITH_CI(poOpenInfo->pszFilename, szLayerCalibration) && 22 12 : poOpenInfo->pszFilename[strlen(szLayerCalibration)] == chLayerSeparator) 23 : { 24 12 : return TRUE; 25 : } 26 : 27 48328 : if (poOpenInfo->bIsDirectory) 28 : { 29 4 : const auto IsRCM = [](const CPLString &osMDFilename) 30 : { 31 4 : CPLXMLNode *psProduct = CPLParseXMLFile(osMDFilename); 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 : CPLString osMDFilename = 61 198 : CPLFormCIFilename(poOpenInfo->pszFilename, "product.xml", nullptr); 62 : 63 : VSIStatBufL sStat; 64 99 : if (VSIStatL(osMDFilename, &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 : CPLString osMDFilenameMetadata = CPLFormCIFilename( 73 194 : poOpenInfo->pszFilename, GetMetadataProduct(), nullptr); 74 : 75 : VSIStatBufL sStatMetadata; 76 97 : if (VSIStatL(osMDFilenameMetadata, &sStatMetadata) == 0) 77 : { 78 2 : return IsRCM(osMDFilenameMetadata); 79 : } 80 : 81 95 : return FALSE; 82 : } 83 : 84 : /* otherwise, do our normal stuff */ 85 48229 : if (strlen(poOpenInfo->pszFilename) < 11 || 86 47283 : !EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 11, 87 : "product.xml")) 88 48224 : 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 1293 : void RCMDriverSetCommonMetadata(GDALDriver *poDriver) 104 : { 105 1293 : poDriver->SetDescription(RCM_DRIVER_NAME); 106 1293 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); 107 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 108 1293 : "Radarsat Constellation Mission XML Product"); 109 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rcm.html"); 110 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); 111 1293 : poDriver->pfnIdentify = RCMDatasetIdentify; 112 1293 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 113 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 114 1293 : } 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