예제 #1
0
const char *GDALPamDataset::BuildPamFilename()

{
    if( psPam == NULL )
        return NULL;

/* -------------------------------------------------------------------- */
/*      What is the name of the physical file we are referencing?       */
/*      We allow an override via the psPam->pszPhysicalFile item.       */
/* -------------------------------------------------------------------- */
    if( psPam->pszPamFilename != NULL )
        return psPam->pszPamFilename;

    const char *pszPhysicalFile = psPam->osPhysicalFilename;

    if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL )
        pszPhysicalFile = GetDescription();

    if( strlen(pszPhysicalFile) == 0 )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Try a proxy lookup, otherwise just add .aux.xml.                */
/* -------------------------------------------------------------------- */
    const char *pszProxyPam = PamGetProxy( pszPhysicalFile );
    if( pszProxyPam != NULL )
        psPam->pszPamFilename = CPLStrdup(pszProxyPam);
    else
    {
        psPam->pszPamFilename = (char*) CPLMalloc(strlen(pszPhysicalFile)+10);
        strcpy( psPam->pszPamFilename, pszPhysicalFile );
        strcat( psPam->pszPamFilename, ".aux.xml" );
    }

    return psPam->pszPamFilename;
}
예제 #2
0
const char *PamAllocateProxy( const char *pszOriginal )

{
    InitProxyDB();

    if( poProxyDB == NULL )
        return NULL;

    CPLMutexHolderD( &hProxyDBLock );

    poProxyDB->CheckLoadDB();

/* -------------------------------------------------------------------- */
/*      Form the proxy filename based on the original path if           */
/*      possible, but dummy out any questionable characters, path       */
/*      delimiters and such.  This is intended to make the proxy        */
/*      name be identifiable by folks digging around in the proxy       */
/*      database directory.                                             */
/*                                                                      */
/*      We also need to be careful about length.                        */
/* -------------------------------------------------------------------- */
    CPLString osRevProxyFile;
    int   i;

    i = strlen(pszOriginal) - 1;
    while( i >= 0 && osRevProxyFile.size() < 220 )
    {
        if( i > 6 && EQUALN(pszOriginal+i-5,":::OVR",6) )
            i -= 6;

        // make some effort to break long names at path delimiters.
        if( (pszOriginal[i] == '/' || pszOriginal[i] == '\\') 
            && osRevProxyFile.size() > 200 )
            break;

        if( (pszOriginal[i] >= 'A' && pszOriginal[i] <= 'Z') 
            || (pszOriginal[i] >= 'a' && pszOriginal[i] <= 'z') 
            || (pszOriginal[i] >= '0' && pszOriginal[i] <= '9') 
            || pszOriginal[i] == '.' )
            osRevProxyFile += pszOriginal[i];
        else
            osRevProxyFile += '_';

        i--;
    }
    
    CPLString osOriginal = pszOriginal;
    CPLString osProxy;
    CPLString osCounter;

    osProxy = poProxyDB->osProxyDBDir + "/";

    osCounter.Printf( "%06d_", poProxyDB->nUpdateCounter++ );
    osProxy += osCounter;

    for( i = osRevProxyFile.size()-1; i >= 0; i-- )
        osProxy += osRevProxyFile[i];

    if( osOriginal.find(":::OVR") != CPLString::npos )
        osProxy += ".ovr";
    else
        osProxy += ".aux.xml";

/* -------------------------------------------------------------------- */
/*      Add the proxy and the original to the proxy list and resave     */
/*      the database.                                                   */
/* -------------------------------------------------------------------- */
    poProxyDB->aosOriginalFiles.push_back( osOriginal );
    poProxyDB->aosProxyFiles.push_back( osProxy );

    poProxyDB->SaveDB();

    return PamGetProxy( pszOriginal );
}
예제 #3
0
CPLErr GDALPamDataset::TrySaveXML()

{
    CPLXMLNode *psTree;
    CPLErr eErr = CE_None;

    nPamFlags &= ~GPF_DIRTY;

    if( psPam == NULL || (nPamFlags & GPF_NOSAVE) )
        return CE_None;

/* -------------------------------------------------------------------- */
/*      Make sure we know the filename we want to store in.             */
/* -------------------------------------------------------------------- */
    if( !BuildPamFilename() )
        return CE_None;

/* -------------------------------------------------------------------- */
/*      Build the XML representation of the auxilary metadata.          */
/* -------------------------------------------------------------------- */
    CPLString osVRTPath = CPLGetPath(psPam->pszPamFilename);

    psTree = SerializeToXML( osVRTPath );

    if( psTree == NULL )
        return CE_None;

/* -------------------------------------------------------------------- */
/*      If we are working with a subdataset, we need to integrate       */
/*      the subdataset tree within the whole existing pam tree,         */
/*      after removing any old version of the same subdataset.          */
/* -------------------------------------------------------------------- */
    if( psPam->osSubdatasetName.size() != 0 )
    {
        CPLXMLNode *psOldTree, *psSubTree;

        CPLErrorReset();
        CPLPushErrorHandler( CPLQuietErrorHandler );
        psOldTree = CPLParseXMLFile( psPam->pszPamFilename );
        CPLPopErrorHandler();

        if( psOldTree == NULL )
            psOldTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );

        for( psSubTree = psTree->psChild; 
             psSubTree != NULL;
             psSubTree = psSubTree->psNext )
        {
            if( psSubTree->eType != CXT_Element
                || !EQUAL(psSubTree->pszValue,"Subdataset") )
                continue;

            if( !EQUAL(CPLGetXMLValue( psSubTree, "name", "" ),
                       psPam->osSubdatasetName) )
                continue;

            break;
        }

        if( psSubTree == NULL )
        {
            psSubTree = CPLCreateXMLNode( psOldTree, CXT_Element, 
                                          "Subdataset" );
            CPLCreateXMLNode( 
                CPLCreateXMLNode( psSubTree, CXT_Attribute, "name" ),
                CXT_Text, psPam->osSubdatasetName );
        }
        
        CPLXMLNode *psOldPamDataset = CPLGetXMLNode( psSubTree, "PAMDataset");
        if( psOldPamDataset != NULL )
        {
            CPLRemoveXMLChild( psSubTree, psOldPamDataset );
            CPLDestroyXMLNode( psOldPamDataset );
        }

        CPLAddXMLChild( psSubTree, psTree );
        psTree = psOldTree;
    }

/* -------------------------------------------------------------------- */
/*      Try saving the auxilary metadata.                               */
/* -------------------------------------------------------------------- */
    const char *pszNewPam;
    int bSaved;
    
    CPLPushErrorHandler( CPLQuietErrorHandler );
    bSaved = CPLSerializeXMLTreeToFile( psTree, psPam->pszPamFilename );
    CPLPopErrorHandler();

/* -------------------------------------------------------------------- */
/*      If it fails, check if we have a proxy directory for auxilary    */
/*      metadata to be stored in, and try to save there.                */
/* -------------------------------------------------------------------- */
    if( bSaved )
        eErr = CE_None;
    else if( PamGetProxy(GetDescription()) == NULL 
             && ((pszNewPam = PamAllocateProxy(GetDescription())) != NULL))
    {
        CPLErrorReset();
        CPLFree( psPam->pszPamFilename );
        psPam->pszPamFilename = CPLStrdup(pszNewPam);
        eErr = TrySaveXML();
    }
    else
    {
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Unable to save auxilary information in %s.",
                  psPam->pszPamFilename );
        eErr = CE_Warning;
    }
    
/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    CPLDestroyXMLNode( psTree );

    return eErr;
}