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
19    Name: dmtNode.cc
20
21    General Description: Implementation of the DmtTreeImpl class
22
23==================================================================================================*/
24
25#include "dmt.hpp"
26#include "dmtTreeImpl.hpp"
27#include "dmtNodeImpl.hpp"
28#include "dm_tree_util.h"
29#include "dm_tree_plugin_util.H"
30#include "dmLockingHelper.h"
31
32DmtNodeImpl::~DmtNodeImpl()
33{
34}
35#ifdef LOB_SUPPORT
36DmtNodeImpl::DmtNodeImpl( BOOLEAN bLeaf,BOOLEAN bESN, DmtTree *ptrTree, CPCHAR oPath, CPCHAR strName )
37{
38  m_bLeaf = bLeaf;
39  m_ptrTree = ptrTree;
40  m_oPath = DmtGetSafeStrPtr( oPath );
41  m_strName = strName;
42 m_bESN = bESN;
43 m_chunkOffset = 0L;         // offset
44 chunkData = NULL;
45}
46#else
47DmtNodeImpl::DmtNodeImpl( BOOLEAN bLeaf, DmtTree *ptrTree, CPCHAR oPath, CPCHAR strName )
48{
49  m_bLeaf = bLeaf;
50  m_ptrTree = ptrTree;
51  m_oPath = DmtGetSafeStrPtr( oPath );
52  m_strName = strName;
53}
54#endif
55SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetTree( PDmtTree& ptrTree ) const
56{
57  ptrTree = m_ptrTree;
58  return SYNCML_DM_SUCCESS;
59}
60
61
62SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetPath(DMString & path) const
63{
64    path = m_oPath;
65    if ( m_oPath != NULL && path == NULL )
66        return SYNCML_DM_DEVICE_FULL;
67    return SYNCML_DM_SUCCESS;
68}
69
70
71SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetNodeName(DMString & name) const
72{
73    name = m_strName;
74    if ( m_strName != NULL && name == NULL )
75        return SYNCML_DM_DEVICE_FULL;
76    return SYNCML_DM_SUCCESS;
77}
78
79SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetAttributes( DmtAttributes& oAttr ) const
80{
81   DMLockingHelper oLock( GetTree(), GetTree()->m_nLockType );
82
83  if ( !oLock.IsLockedSuccessfully() )
84    return oLock.GetError();
85
86  return dmTreeObj.GetAttributes(m_oPath.c_str(), oAttr, SYNCML_DM_REQUEST_TYPE_API);
87
88}
89
90SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetTitle( CPCHAR szTitle )
91{
92  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
93    return SYNCML_DM_TREE_READONLY;
94
95  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
96
97  if ( !oLock.IsLockedSuccessfully() )
98    return oLock.GetError();
99
100  return GetTree()->SetNodeStringProp( m_oPath.c_str(), "Title", szTitle );
101}
102
103SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetAcl( const DmtAcl& oAcl )
104{
105  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
106    return SYNCML_DM_TREE_READONLY;
107
108  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
109
110  if ( !oLock.IsLockedSuccessfully() )
111    return oLock.GetError();
112
113  return GetTree()->SetNodeStringProp( m_oPath.c_str(), "ACL", oAcl.toString().c_str());
114}
115
116SYNCML_DM_RET_STATUS_T DmtNodeImpl::Rename( CPCHAR szNewName )
117{
118  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
119    return SYNCML_DM_TREE_READONLY;
120
121  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
122
123  if ( !oLock.IsLockedSuccessfully() )
124    return oLock.GetError();
125
126  return GetTree()->SetNodeStringProp( m_oPath.c_str(), "Name", szNewName );
127}
128
129SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetValue( DmtData& oData ) const
130{
131#ifdef LOB_SUPPORT
132if (m_bESN)
133       return SYNCML_DM_RESULTS_TOO_LARGE;
134#endif
135
136  DMLockingHelper oLock( GetTree(), GetTree()->m_nLockType );
137
138  if ( !oLock.IsLockedSuccessfully() )
139    return oLock.GetError();
140
141  SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
142  DMGetData getData;
143
144  dm_stat = dmTreeObj.Get(m_oPath.c_str(),getData,SYNCML_DM_REQUEST_TYPE_API);
145
146  if ( dm_stat != SYNCML_DM_SUCCESS )
147    return dm_stat;
148
149  if (getData.m_nFormat == SYNCML_DM_FORMAT_NODE )
150  {
151     DMStringVector aChildren;
152     DMURI ptr(FALSE,getData.getCharData());
153     CPCHAR pSegment = NULL;
154
155     oData = DmtData( aChildren );  // set type to "node" for case of empty parent
156
157     // we got list of nodes, divided by '/'
158     while ( (pSegment = ptr.nextSegment()) != NULL )
159     {
160       dm_stat = oData.AddNodeValue(pSegment);
161       if ( dm_stat != SYNCML_DM_SUCCESS )
162           return dm_stat;
163     }
164  }
165  else
166      dm_stat =  dmBuildData(getData.m_nFormat, getData.m_oData, oData);
167
168  return dm_stat;
169}
170
171SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetValue( const DmtData& value )
172{
173#ifdef LOB_SUPPORT
174if (m_bESN)
175       return SYNCML_DM_RESULTS_TOO_LARGE;
176#endif
177
178  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
179    return SYNCML_DM_TREE_READONLY;
180
181  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
182
183  if ( !oLock.IsLockedSuccessfully() )
184    return oLock.GetError();
185
186  SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
187  DMAddData oReplace;
188
189  dm_stat = oReplace.set(m_oPath.c_str(),value,"text/plain");
190
191  if ( dm_stat != SYNCML_DM_SUCCESS )
192    return dm_stat;
193
194  return dmTreeObj.Replace(oReplace,SYNCML_DM_REQUEST_TYPE_API);
195}
196
197SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetChildNodes( DMVector<PDmtNode>& oChildren ) const
198{
199  DMStringVector  aChildren;
200  return GetChildNodes( oChildren, aChildren );
201}
202
203SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetChildNodes( DMVector<PDmtNode>& oChildren, DMStringVector& aChildren ) const
204{
205  // cache current time for last access time updates
206  DMTreeCacheCurrentTime cacheTime(&dmTreeObj);
207
208  oChildren.clear(); // remove all previous items from array
209
210  if ( m_bLeaf )
211    return SYNCML_DM_FAIL;
212
213  DmtData oData;
214
215  SYNCML_DM_RET_STATUS_T dm_stat = GetValue( oData );
216
217  if ( dm_stat != SYNCML_DM_SUCCESS )
218    return dm_stat;
219
220  dm_stat = oData.GetNodeValue( aChildren );
221
222  if ( dm_stat != SYNCML_DM_SUCCESS )
223    return dm_stat;
224
225  for ( int i = 0; i < aChildren.size(); i++ )
226  {
227    DMString oPath = m_oPath;
228
229    oPath += "/";
230    oPath += aChildren[i];
231
232    PDmtNode ptrNode;
233
234    dm_stat = GetTree()->GetNodeByFullPath( oPath.c_str(), ptrNode );
235    if ( dm_stat != SYNCML_DM_SUCCESS )
236        return dm_stat;
237
238    oChildren.push_back( ptrNode );
239  }
240
241  return SYNCML_DM_SUCCESS;
242}
243
244
245
246BOOLEAN DmtNodeImpl::IsLeaf() const
247{
248  return m_bLeaf;
249}
250
251SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetChildNode( CPCHAR szPath, PDmtNode& ptrNode  )
252{
253  DMString oPath = m_oPath;
254
255  oPath += "/";
256  oPath += DmtGetSafeStrPtr( szPath );
257
258  return GetTree()->GetNodeByFullPath( oPath.c_str(), ptrNode );
259}
260
261
262SYNCML_DM_RET_STATUS_T DmtNodeImpl::Execute( CPCHAR strData, DMString& result )
263{
264
265    if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
266        return SYNCML_DM_TREE_READONLY;
267
268    return dmTreeObj.Exec(m_oPath.c_str(),strData,result);
269}
270
271// implementation helpers
272DmtTreeImpl* DmtNodeImpl::GetTree() const
273{
274  return (DmtTreeImpl*)m_ptrTree.GetPtr();
275}
276#ifdef LOB_SUPPORT
277 SYNCML_DM_RET_STATUS_T DmtNodeImpl:: GetEngineChunkData(void)
278{
279   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
280  DMGetData getData;
281
282  retStatus = getData.set(chunkData, m_chunkOffset);
283
284  if ( retStatus != SYNCML_DM_SUCCESS )
285    return retStatus;
286
287  retStatus = dmTreeObj.Get(m_oPath.c_str(),getData,SYNCML_DM_REQUEST_TYPE_API);
288
289  if ( retStatus != SYNCML_DM_SUCCESS )
290    return retStatus;
291
292  UINT32 returnLen;
293  retStatus = chunkData->GetReturnLen(returnLen);
294  m_chunkOffset += returnLen;
295
296  return retStatus;
297}
298  SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetFirstChunk(DmtDataChunk&  dmtChunkData)
299  {
300   DMLockingHelper oLock( GetTree(), GetTree()->m_nLockType );
301
302  if ( !oLock.IsLockedSuccessfully() )
303    return oLock.GetError();
304
305   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
306   if (!m_bESN)
307       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
308
309  if( chunkData != NULL)
310  {
311      if(chunkData != &dmtChunkData)
312      {    retStatus = chunkData->FreeChunkBuffer();
313        if(retStatus!= SYNCML_DM_SUCCESS)
314                return retStatus;
315      }
316  }
317  retStatus = dmtChunkData.AllocateChunkBuffer();
318  if(retStatus!= SYNCML_DM_SUCCESS)
319        return retStatus;
320  chunkData = &dmtChunkData;
321  m_chunkOffset = 0L;
322
323  retStatus =  GetEngineChunkData();
324  return retStatus;
325 }
326  SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetNextChunk(DmtDataChunk& dmtChunkData)
327  {
328   DMLockingHelper oLock( GetTree(), GetTree()->m_nLockType );
329
330  if ( !oLock.IsLockedSuccessfully() )
331    return oLock.GetError();
332
333   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
334   if (!m_bESN)
335       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
336
337     if(( chunkData == NULL) ||(chunkData != &dmtChunkData))
338    return SYNCML_DM_INVALID_PARAMETER;
339
340  retStatus =  GetEngineChunkData();
341  return retStatus;
342 }
343
344  SYNCML_DM_RET_STATUS_T DmtNodeImpl:: SetEngineChunkData(BOOLEAN isLastChunk)
345  {
346   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
347  DMAddData oReplace;
348
349  retStatus = oReplace.set(m_oPath.c_str(), chunkData, m_chunkOffset, isLastChunk);
350
351  if ( retStatus != SYNCML_DM_SUCCESS )
352    return retStatus;
353
354  retStatus =  dmTreeObj.Replace(oReplace,SYNCML_DM_REQUEST_TYPE_API);
355  if ( retStatus != SYNCML_DM_SUCCESS )
356    return retStatus;
357
358  UINT32 dataLen;
359  retStatus = chunkData->GetChunkDataSize(dataLen);
360  m_chunkOffset += dataLen;
361   return retStatus;
362  }
363
364  SYNCML_DM_RET_STATUS_T DmtNodeImpl:: SetFirstChunk(DmtDataChunk& dmtChunkData)
365  {
366   if (!m_bESN)
367       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
368
369  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
370    return SYNCML_DM_TREE_READONLY;
371
372  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
373
374  if ( !oLock.IsLockedSuccessfully() )
375    return oLock.GetError();
376
377   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
378   if (!m_bESN)
379       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
380
381
382  if (chunkData != NULL)
383  {
384      if(chunkData != &dmtChunkData)
385      {    retStatus = chunkData->FreeChunkBuffer();
386        if(retStatus!= SYNCML_DM_SUCCESS)
387                return retStatus;
388      }
389  }
390  retStatus = dmtChunkData.AllocateChunkBuffer();
391  if(retStatus!= SYNCML_DM_SUCCESS)
392        return retStatus;
393  chunkData = &dmtChunkData;
394  m_chunkOffset = 0L;
395
396   retStatus =  SetEngineChunkData(FALSE);
397   return retStatus;
398
399  }
400
401  SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetNextChunk(DmtDataChunk& dmtChunkData)
402  {
403   if (!m_bESN)
404       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
405
406  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
407    return SYNCML_DM_TREE_READONLY;
408
409  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
410
411  if ( !oLock.IsLockedSuccessfully() )
412    return oLock.GetError();
413   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
414   if (!m_bESN)
415       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
416     if(( chunkData == NULL) ||(chunkData != &dmtChunkData))
417    return SYNCML_DM_INVALID_PARAMETER;
418
419   retStatus =  SetEngineChunkData(FALSE);
420
421   return retStatus;
422
423  }
424 SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetLastChunk(DmtDataChunk& dmtChunkData)
425 {
426   if (!m_bESN)
427       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
428
429  if ( GetTree()->m_nLockType == SYNCML_DM_LOCK_TYPE_SHARED )
430    return SYNCML_DM_TREE_READONLY;
431
432  DMLockingHelper oLock( GetTree(), SYNCML_DM_LOCK_TYPE_EXCLUSIVE );
433
434  if ( !oLock.IsLockedSuccessfully() )
435    return oLock.GetError();
436   SYNCML_DM_RET_STATUS_T retStatus =  SYNCML_DM_SUCCESS;
437   if (!m_bESN)
438       return SYNCML_DM_UNSUPPORTED_MEDIATYPE_FORMAT;
439     if(( chunkData == NULL) ||(chunkData != &dmtChunkData))
440    return SYNCML_DM_INVALID_PARAMETER;
441
442   retStatus =  SetEngineChunkData(TRUE);
443   return retStatus;
444
445}
446boolean DmtNodeImpl::IsExternalStorageNode(void) const
447{ return m_bESN;
448}
449
450#else
451SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetFirstChunk(DmtDataChunk&  dmtChunkData)
452{
453 return SYNCML_DM_FEATURE_NOT_SUPPORTED;
454}
455SYNCML_DM_RET_STATUS_T DmtNodeImpl::GetNextChunk(DmtDataChunk& dmtChunkData)
456{
457    return SYNCML_DM_FEATURE_NOT_SUPPORTED;
458}
459SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetFirstChunk(DmtDataChunk& dmtChunkData)
460{
461    return SYNCML_DM_FEATURE_NOT_SUPPORTED;
462}
463SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetNextChunk(DmtDataChunk& dmtChunkData)
464{
465    return SYNCML_DM_FEATURE_NOT_SUPPORTED;
466}
467SYNCML_DM_RET_STATUS_T DmtNodeImpl::SetLastChunk(DmtDataChunk& dmtChunkData)
468{
469    return SYNCML_DM_FEATURE_NOT_SUPPORTED;
470}
471boolean DmtNodeImpl::IsExternalStorageNode(void) const { return FALSE;}
472
473#endif
474