Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  *  DESCRIPTION:
     19  *      The dm_tree_plugin_util.cc file contains helper functions
     20  *      for plug-in support
     21  */
     22 
     23 #include "xpl_Logger.h"
     24 #include "dmtTreeImpl.hpp"
     25 #include "dm_tree_plugin_root_node_class.H"
     26 #include "dm_tree_plugin_util.H"
     27 #include "dm_tree_util.h"
     28 #include "SyncML_DM_WBXMLArchive.H"
     29 #include "SyncML_PlugIn_WBXMLLog.H"
     30 #include "dm_uri_utils.h"
     31 
     32 #ifndef min
     33 #define min(a,b) (((a) < (b)) ? (a) : (b))
     34 #endif
     35 
     36 SYNCML_DM_RET_STATUS_T
     37 DmCheckNodeConstraint(const PDMPlugin & pPlugin) ;
     38 
     39 SYNCML_DM_RET_STATUS_T
     40 DmCheckMultiNodeConstraint(const PDMPlugin & pPlugin, CPCHAR path, CPCHAR remain, const PDmtTree & tree);
     41 
     42 SYNCML_DM_RET_STATUS_T DmRemoveTempfile(DMString &dirName)
     43 {
     44 
     45     SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS;
     46     XPL_FS_SHANDLE_T search_handle;
     47     DMString strFileNameBuffer;
     48     char *file_name = strFileNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
     49 
     50     if (file_name == NULL)
     51       return SYNCML_DM_DEVICE_FULL;
     52 
     53     search_handle = XPL_FS_StartSearch(dirName, DMFileHandler::MIDDLE_FILE_EXTENSION, TRUE, NULL);
     54     if ( search_handle == XPL_FS_SHANDLE_INVALID)
     55         return SYNCML_DM_IO_FAILURE;
     56 
     57    //Loop through all .temp files in the directory
     58     memset(file_name,0,XPL_FS_MAX_FILE_NAME_LENGTH);
     59     while ( XPL_FS_GetSearchResult(search_handle,file_name) != XPL_FS_RET_NOT_FOUND )
     60     {
     61 
     62 	DMFileHandler fileHandler(file_name);
     63 	ret_code = fileHandler.open(XPL_FS_FILE_RDWR);
     64 	// Remove temporary ESN file
     65 	if(ret_code == SYNCML_DM_SUCCESS)
     66 		fileHandler.deleteFile();
     67      }
     68      XPL_FS_EndSearch(search_handle);
     69     return ret_code;
     70 }
     71 
     72 SYNCML_DM_RET_STATUS_T DMTree::ReadCommandFromFile( DMFileHandler    *fileHandle,
     73                                                     DMBuffer&        cmdURI )
     74 {
     75   SYNCML_DM_RET_STATUS_T  ret_code = SYNCML_DM_FAIL;
     76   SyncML_DM_WBXMLReader*  reader = new SyncML_DM_WBXMLReader( fileHandle );
     77 
     78   if( reader ) for( ; ; )
     79   {
     80     ret_code = SYNCML_DM_IO_FAILURE;
     81     if(fileHandle->seek(XPL_FS_SEEK_SET, sizeof(INT32) + 2) != XPL_FS_RET_SUCCESS) break;
     82 
     83     // Read URI
     84     ret_code = reader->readOpaque( &cmdURI );
     85     if( SYNCML_DM_SUCCESS != ret_code ) break;
     86 
     87     //Read END_TAG
     88     UINT8  bYte = 0;
     89     ret_code = reader->readByte( &bYte );
     90     if( SYNCML_DM_SUCCESS != ret_code ) break;
     91 
     92     ret_code = SYNCML_DM_IO_FAILURE;
     93     if( bYte != SyncML_DM_WBXMLArchive::END_TAG ) break;
     94 
     95     ret_code = SYNCML_DM_SUCCESS;
     96     break;
     97   }
     98 
     99   if( reader )
    100   {
    101     delete reader;
    102     reader = NULL;
    103   }
    104 
    105   return ret_code;
    106 }
    107 
    108 SYNCML_DM_RET_STATUS_T DMTree::RecoverPluginFromFile( const DMString&  file_bak_name )
    109 {
    110   SYNCML_DM_RET_STATUS_T  ret_code = SYNCML_DM_FAIL;
    111   DMFileHandler           *fileHandle = new DMFileHandler( file_bak_name );
    112 
    113   if( fileHandle )
    114   {
    115     BOOLEAN delete_file = FALSE;
    116 
    117     if(fileHandle->open(XPL_FS_FILE_RDWR) != SYNCML_DM_SUCCESS)
    118     {
    119       // DM: Ignore files that cannot be opened ?
    120       ret_code = SYNCML_DM_SUCCESS;
    121     }
    122     else
    123     {
    124       delete_file = TRUE;
    125 
    126       DMBuffer cmdURI;
    127       ret_code = ReadCommandFromFile( fileHandle, cmdURI );
    128 
    129       if( ret_code == SYNCML_DM_SUCCESS )
    130       {
    131         PDMPlugin pPlugin = m_oPluginManager.FindPlugin(SYNCML_DM_DATA_PLUGIN, (CPCHAR)cmdURI.getBuffer());
    132 
    133         if (pPlugin != NULL)
    134         {
    135           PDmtAPIPluginTree  pluginTree;
    136           ret_code=pPlugin->GetTree((CPCHAR) cmdURI.getBuffer(), pluginTree);
    137 
    138           if(ret_code == SYNCML_DM_SUCCESS)
    139           {
    140             PDmtRWPluginTree ptrRWTree = (DmtRWPluginTree *) ((DmtTree *)pluginTree);
    141             ret_code = ptrRWTree->setLogFileHandle(fileHandle);
    142 
    143             if( ret_code == SYNCML_DM_SUCCESS)
    144             {
    145               ret_code = ptrRWTree->Rollback();
    146 
    147               // DM: hands-off from file
    148               fileHandle = NULL;
    149             }
    150           }
    151         }
    152       }
    153     }
    154 
    155     if( fileHandle )
    156     {
    157       if( delete_file )
    158       {
    159         fileHandle->deleteFile();
    160       }
    161 
    162       delete fileHandle;
    163       fileHandle = NULL;
    164     }
    165   }
    166 
    167   return ret_code;
    168 }
    169 
    170 SYNCML_DM_RET_STATUS_T DMTree::RecoverPlugin()
    171 {
    172 
    173   SYNCML_DM_RET_STATUS_T  ret_code = SYNCML_DM_SUCCESS;
    174   DMString                strFileNameBuffer;
    175   DMString                strFileBakNameBuffer;
    176 
    177   char                    *file_name = strFileNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    178   char                    *file_bak_name = strFileBakNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    179 
    180   if ( !file_name || !file_bak_name )
    181     return SYNCML_DM_DEVICE_FULL;
    182 
    183   DMString logtdir;
    184   m_oEnv.GetWFSFullPath( NULL, logtdir );
    185 
    186   XPL_FS_SHANDLE_T search_handle = XPL_FS_StartSearch(logtdir, DMFileHandler::LOG_FILE_EXTENSION, TRUE, NULL);
    187   if ( search_handle == XPL_FS_SHANDLE_INVALID)
    188       return SYNCML_DM_IO_FAILURE;
    189 
    190  //Loop through all .log files in the directory
    191   memset(file_name, 0, XPL_FS_MAX_FILE_NAME_LENGTH );
    192   memset(file_bak_name, 0, XPL_FS_MAX_FILE_NAME_LENGTH );
    193 
    194   int nExtLength = DmStrlen( DMFileHandler::LOG_FILE_EXTENSION );
    195 
    196   while ( XPL_FS_GetSearchResult(search_handle, file_name) != XPL_FS_RET_NOT_FOUND )
    197   {
    198     int nFileNameLen = DmStrlen(file_name);
    199 
    200     if ( file_name[0] == 0 || nFileNameLen < 5 ) continue;
    201 
    202     DmStrncpy(file_bak_name, file_name, nFileNameLen - nExtLength );
    203     DmStrcat(file_bak_name, DMFileHandler::MIDDLE_FILE_EXTENSION);
    204 
    205     if( XPL_FS_RET_SUCCESS != XPL_FS_Rename( file_name, file_bak_name ) )
    206     {
    207       ret_code = SYNCML_DM_IO_FAILURE;
    208       continue;
    209     }
    210 
    211     ret_code = RecoverPluginFromFile( file_bak_name );
    212     // DM: continue even if there is an error ( exactly as in original version of code )
    213   }
    214 
    215   XPL_FS_EndSearch(search_handle);
    216   return ret_code;
    217 
    218 }
    219 
    220 SYNCML_DM_RET_STATUS_T
    221 DmExecutePlugin(CPCHAR path,
    222                                 CPCHAR args,
    223                                 CPCHAR szCorrelator,
    224                                 DMString & oResult)
    225 {
    226    SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_FAIL;
    227    DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager();
    228 
    229    XPL_LOG_DM_TMN_Debug((" DmExecutePlugin find plugin\n"));
    230    PDMPlugin pPlugin = oPluginManager.FindPlugin(SYNCML_DM_EXECUTE_PLUGIN, path);
    231 
    232    if (pPlugin == NULL)
    233    {
    234         XPL_LOG_DM_TMN_Debug((" DmExecutePlugin plugin not found\n"));
    235         return SYNCML_DM_FEATURE_NOT_SUPPORTED;
    236    }
    237 
    238    PDmtTree ptrTree( new DmtTreeImpl(FALSE) ); // readonly version of the tree
    239 
    240    XPL_LOG_DM_TMN_Debug((" DmExecutePlugin plugin being executed...\n"));
    241    return pPlugin->Execute(path,args,szCorrelator,ptrTree,oResult);
    242 }
    243 
    244 SYNCML_DM_RET_STATUS_T
    245 DmCallPluginFunction(CPCHAR szSessionRootURI,
    246                                         FILESETTYPE nFileSet,
    247                                         SYNCML_DM_COMMAND_T type)
    248 {
    249     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    250     DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager();
    251 
    252     DMPluginVector  plugins;
    253     PDmtAPIPluginTree  pluginTree;
    254 
    255     oPluginManager.GetPlugins(szSessionRootURI, SYNCML_DM_DATA_PLUGIN, plugins);
    256 
    257     INT32 size = plugins.size();
    258     for ( INT32 i=0; i<size; i++ )
    259     {
    260         PDMPlugin  plugin = plugins[i];
    261         if(plugin->IsTreeEmpty())
    262             continue;
    263 
    264         dm_stat=plugin->GetTree(plugin->GetPath(), pluginTree);
    265         if(dm_stat == SYNCML_DM_SUCCESS)
    266         {
    267             switch(type)
    268             {
    269                 case SYNCML_DM_RELEASE:
    270                     dm_stat = pluginTree->Flush();
    271                     break;
    272 
    273                 case SYNCML_DM_ROLLBACK:
    274                 {
    275                     FILESETTYPE sets = 0;
    276 
    277                     SyncML_DM_Archiver&  archiver = dmTreeObj.GetArchiver();
    278                     sets = archiver.getArchivesByURI(plugin->GetPath());
    279                     sets &= nFileSet;
    280 
    281                     if ( sets != 0 )
    282                     {
    283                         dm_stat = pluginTree->Rollback();
    284                     }
    285                 }
    286                     break;
    287 
    288                 case SYNCML_DM_COMMIT:
    289                     dm_stat = pluginTree->Commit();
    290                     break;
    291 
    292                 case SYNCML_DM_ATOMIC:
    293                     dm_stat = pluginTree->Begin();
    294                     break;
    295            }
    296          }
    297 
    298          if (dm_stat != SYNCML_DM_SUCCESS)
    299          {
    300             if((dm_stat == SYNCML_DM_FEATURE_NOT_SUPPORTED)&&(type == SYNCML_DM_ATOMIC))
    301                 return dm_stat;
    302             else
    303                dm_stat = SYNCML_DM_SUCCESS;
    304         }
    305      }
    306 
    307    XPL_LOG_DM_TMN_Debug((" DmCallPluginFunction retStat=%d\n", dm_stat));
    308    return dm_stat;
    309 }
    310 
    311 SYNCML_DM_RET_STATUS_T
    312 DmCheckConstraint(CPCHAR szSessionRootURI,
    313                                  FILESETTYPE * pFileSet,
    314                                  FILESETTYPE * pFileSetToRollback)
    315 {
    316     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    317     SYNCML_DM_RET_STATUS_T dm_const_stat = SYNCML_DM_SUCCESS;
    318 
    319     SyncML_DM_Archiver&  archiver = dmTreeObj.GetArchiver();
    320     FILESETTYPE  numArchives = archiver.getNumArchives();
    321     FILESETTYPE  i = 0;
    322     FILESETTYPE  set = 1;
    323 
    324 
    325     if ( pFileSet == NULL || pFileSetToRollback == NULL )
    326         return SYNCML_DM_FAIL;
    327 
    328     XPL_LOG_DM_TMN_Debug(("--- DmCheckConstraint for %s, pFileSet=0x%x, numArchives=%d\n", szSessionRootURI, *pFileSet, numArchives));
    329 
    330     if ( !archiver.IsDirty(pFileSet) )
    331     {
    332         XPL_LOG_DM_TMN_Debug(("No archives are dirty\n"));
    333         return dm_stat;
    334     }
    335 
    336     DMPluginVector  aSessionPlugins;
    337 
    338     DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager();
    339     oPluginManager.GetPlugins(szSessionRootURI, SYNCML_DM_CONSTRAINT_PLUGIN, aSessionPlugins);
    340 
    341     INT32 size = aSessionPlugins.size();
    342     for (INT32 index=0; index< size; index++)
    343     {
    344         FILESETTYPE sets = 0;
    345 
    346         CPCHAR strRootPath=(aSessionPlugins[index])->GetPath();
    347 
    348         sets = archiver.getArchivesByURI(strRootPath);
    349         sets = sets & (*pFileSet);
    350         if ( sets )
    351         {
    352             dm_stat = DmCheckNodeConstraint(aSessionPlugins[index]);
    353             if ( dm_stat != SYNCML_DM_SUCCESS )
    354             {
    355                 for (i=0, set=1; i< numArchives;  i++, set = set <<1)
    356                 {
    357                     if ( (sets & set) != 0 && ((*pFileSetToRollback) & set) == 0 )
    358                     {
    359                         (*pFileSetToRollback) |= set;
    360                         (*pFileSet) &= ~ set;
    361                     }
    362                 }
    363                 dm_const_stat = dm_stat;
    364             }
    365         }
    366     }
    367 
    368     if ( dm_const_stat != SYNCML_DM_SUCCESS )
    369         dm_stat = dm_const_stat;
    370 
    371     XPL_LOG_DM_TMN_Debug((" DmCheckConstraint retStat=%d\n", dm_stat));
    372     return dm_stat;
    373 }
    374 
    375 
    376 
    377 SYNCML_DM_RET_STATUS_T
    378 DmCheckNodeConstraint(const PDMPlugin & pPlugin)
    379 {
    380       SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    381       PDmtTree tree( new DmtTreeImpl(true) );
    382 
    383       CPCHAR strPluginPath=pPlugin->GetPath();
    384 
    385       if (  (DmStrchr(strPluginPath, '*')) == NULL)
    386       {
    387             dm_stat = (pPlugin)->CheckConstraint(strPluginPath,tree);
    388       }
    389       else
    390       {
    391             dm_stat = DmCheckMultiNodeConstraint(pPlugin,"",strPluginPath,tree);
    392       }
    393 
    394       if (dm_stat != SYNCML_DM_SUCCESS)
    395             dm_stat = SYNCML_DM_CONSTRAINT_FAIL;
    396 
    397      return dm_stat;
    398 
    399 }
    400 
    401 
    402 SYNCML_DM_RET_STATUS_T
    403 DmCheckMultiNodeConstraint(const PDMPlugin & pPlugin,
    404                                   CPCHAR path,
    405                                   CPCHAR remain,
    406                                   const PDmtTree & tree)
    407 {
    408     SYNCML_DM_RET_STATUS_T dm_stat;
    409     const char * ptr;    //point to remaining stuff after *
    410 
    411     XPL_LOG_DM_TMN_Debug(("CheckMultiNode %s:%s\n", path, remain));
    412 
    413     ptr=remain;
    414     while ( * ptr != '*' && * ptr != '\0')
    415         ptr ++;
    416 
    417     if ( *ptr == '*' )
    418     {
    419         DMString strPath=path;
    420         strPath += DMString(remain, (int) ptr - (int)remain -1);
    421 
    422         ptr++;
    423 
    424         DMStringVector mapNodeNames;
    425         dm_stat = tree->GetChildNodeNames(strPath.c_str(),mapNodeNames);
    426         if ( dm_stat != SYNCML_DM_SUCCESS )
    427             return dm_stat;
    428 
    429         for (INT32 i=0; i<mapNodeNames.size(); i++)
    430         {
    431             DMString childPath;
    432             childPath =strPath;
    433             childPath += "/";
    434             childPath += mapNodeNames[i];
    435 
    436             dm_stat = DmCheckMultiNodeConstraint(pPlugin,childPath.c_str(),ptr,tree);
    437             if ( dm_stat != SYNCML_DM_SUCCESS)
    438                 return dm_stat;
    439         }
    440     }
    441     else
    442     {
    443         DMString strPath=path;
    444         strPath += remain;
    445         dm_stat=(pPlugin)->CheckConstraint(strPath.c_str(),tree);
    446     }
    447 
    448 
    449    return dm_stat;
    450 }
    451