1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26 /**************************************************************************
27                                TODO
28  **************************************************************************
29 
30  *************************************************************************/
31 
32 #include <set>
33 #include <com/sun/star/beans/Property.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 #include <com/sun/star/ucb/CommandInfo.hpp>
37 #include <com/sun/star/ucb/ContentInfo.hpp>
38 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
39 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
40 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
41 #include <com/sun/star/ucb/TransferInfo.hpp>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include <com/sun/star/util/DateTime.hpp>
44 #include <com/sun/star/ucb/Link.hpp>
45 #include <com/sun/star/ucb/Lock.hpp>
46 #include <com/sun/star/ucb/LockEntry.hpp>
47 #include "webdavcontent.hxx"
48 #include "webdavprovider.hxx"
49 #include "DAVSession.hxx"
50 #include "ContentProperties.hxx"
51 
52 using namespace com::sun::star;
53 using namespace webdav_ucp;
54 
55 //=========================================================================
56 //
57 // ContentProvider implementation.
58 //
59 //=========================================================================
60 
61 bool ContentProvider::getProperty(
62         const rtl::OUString & rPropName, beans::Property & rProp, bool bStrict )
63 {
64     if ( !m_pProps )
65     {
66         osl::MutexGuard aGuard( m_aMutex );
67         if ( !m_pProps )
68         {
69             m_pProps = new PropertyMap;
70 
71             //////////////////////////////////////////////////////////////
72             // Fill map of known properties...
73             //////////////////////////////////////////////////////////////
74 
75             // Mandatory UCB properties.
76             m_pProps->insert(
77                 beans::Property(
78                     rtl::OUString(
79                         RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ),
80                     -1,
81                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
82                     beans::PropertyAttribute::BOUND
83                         | beans::PropertyAttribute::READONLY ) );
84 
85             m_pProps->insert(
86                 beans::Property(
87                     rtl::OUString(
88                         RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
89                     -1,
90                     getCppuBooleanType(),
91                     beans::PropertyAttribute::BOUND
92                         | beans::PropertyAttribute::READONLY ) );
93 
94             m_pProps->insert(
95                 beans::Property(
96                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
97                     -1,
98                     getCppuBooleanType(),
99                     beans::PropertyAttribute::BOUND
100                         | beans::PropertyAttribute::READONLY ) );
101 
102             m_pProps->insert(
103                 beans::Property(
104                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
105                     -1,
106                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
107                     beans::PropertyAttribute::BOUND ) );
108 
109             // Optional UCB properties.
110 
111             m_pProps->insert(
112                 beans::Property(
113                     rtl::OUString(
114                         RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
115                     -1,
116                     getCppuType( static_cast< const util::DateTime * >( 0 ) ),
117                     beans::PropertyAttribute::BOUND
118                         | beans::PropertyAttribute::READONLY ) );
119 
120             m_pProps->insert(
121                 beans::Property(
122                     rtl::OUString(
123                         RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
124                     -1,
125                     getCppuType( static_cast< const util::DateTime * >( 0 ) ),
126                     beans::PropertyAttribute::BOUND
127                         | beans::PropertyAttribute::READONLY ) );
128 
129             m_pProps->insert(
130                 beans::Property(
131                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
132                     -1,
133                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
134                     beans::PropertyAttribute::BOUND
135                         | beans::PropertyAttribute::READONLY ) );
136 
137             m_pProps->insert(
138                 beans::Property(
139                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
140                     -1,
141                     getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
142                     beans::PropertyAttribute::BOUND
143                         | beans::PropertyAttribute::READONLY ) );
144 
145             m_pProps->insert(
146                 beans::Property(
147                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ),
148                     -1,
149                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
150                     beans::PropertyAttribute::BOUND
151                         | beans::PropertyAttribute::READONLY ) );
152 
153             m_pProps->insert(
154                 beans::Property(
155                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
156                         "CreatableContentsInfo" ) ),
157                     -1,
158                     getCppuType( static_cast<
159                         const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
160                     beans::PropertyAttribute::BOUND
161                         | beans::PropertyAttribute::READONLY ) );
162 
163             // Standard DAV properties.
164 
165             m_pProps->insert(
166                 beans::Property(
167                     DAVProperties::CREATIONDATE,
168                     -1,
169                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
170                     beans::PropertyAttribute::BOUND
171                         | beans::PropertyAttribute::READONLY ) );
172 
173             m_pProps->insert(
174                 beans::Property(
175                     DAVProperties::DISPLAYNAME,
176                     -1,
177                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
178                     beans::PropertyAttribute::BOUND ) );
179 
180             m_pProps->insert(
181                 beans::Property(
182                     DAVProperties::GETCONTENTLANGUAGE,
183                     -1,
184                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
185                     beans::PropertyAttribute::BOUND
186                         | beans::PropertyAttribute::READONLY ) );
187 
188             m_pProps->insert(
189                 beans::Property(
190                     DAVProperties::GETCONTENTLENGTH,
191                     -1,
192                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
193                     beans::PropertyAttribute::BOUND
194                         | beans::PropertyAttribute::READONLY ) );
195 
196             m_pProps->insert(
197                 beans::Property(
198                     DAVProperties::GETCONTENTTYPE ,
199                     -1,
200                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
201                     beans::PropertyAttribute::BOUND
202                         | beans::PropertyAttribute::READONLY ) );
203 
204             m_pProps->insert(
205                 beans::Property(
206                     DAVProperties::GETETAG,
207                     -1,
208                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
209                     beans::PropertyAttribute::BOUND
210                         | beans::PropertyAttribute::READONLY ) );
211 
212             m_pProps->insert(
213                 beans::Property(
214                     DAVProperties::GETLASTMODIFIED,
215                     -1,
216                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
217                     beans::PropertyAttribute::BOUND
218                         | beans::PropertyAttribute::READONLY ) );
219 
220             m_pProps->insert(
221                 beans::Property(
222                     DAVProperties::LOCKDISCOVERY,
223                     -1,
224                     getCppuType( static_cast<
225                                     const uno::Sequence< ucb::Lock > * >( 0 ) ),
226                     beans::PropertyAttribute::BOUND
227                         | beans::PropertyAttribute::READONLY ) );
228 
229             m_pProps->insert(
230                 beans::Property(
231                     DAVProperties::RESOURCETYPE,
232                     -1,
233                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
234                     beans::PropertyAttribute::BOUND
235                         | beans::PropertyAttribute::READONLY ) );
236 
237             m_pProps->insert(
238                 beans::Property(
239                     DAVProperties::SOURCE,
240                     -1,
241                     getCppuType( static_cast<
242                                     const uno::Sequence< ucb::Link > * >( 0 ) ),
243                     beans::PropertyAttribute::BOUND ) );
244 
245             m_pProps->insert(
246                 beans::Property(
247                     DAVProperties::SUPPORTEDLOCK,
248                     -1,
249                     getCppuType( static_cast<
250                                     const uno::Sequence<
251                                         ucb::LockEntry > * >( 0 ) ),
252                     beans::PropertyAttribute::BOUND
253                         | beans::PropertyAttribute::READONLY ) );
254 
255             m_pProps->insert(
256                 beans::Property(
257                     DAVProperties::EXECUTABLE,
258                     -1,
259                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
260                     beans::PropertyAttribute::BOUND ) );
261         }
262     }
263 
264     //////////////////////////////////////////////////////////////
265     // Lookup property.
266     //////////////////////////////////////////////////////////////
267 
268     beans::Property aProp;
269     aProp.Name = rPropName;
270     const PropertyMap::const_iterator it = m_pProps->find( aProp );
271     if ( it != m_pProps->end() )
272     {
273         rProp = (*it);
274     }
275     else
276     {
277         if ( bStrict )
278             return false;
279 
280         // All unknown props are treated as:
281         rProp = beans::Property(
282                     rPropName,
283                     - 1,
284                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
285                     beans::PropertyAttribute::BOUND );
286     }
287 
288     return true;
289 }
290 
291 //=========================================================================
292 //
293 // Content implementation.
294 //
295 //=========================================================================
296 
297 // virtual
298 uno::Sequence< beans::Property > Content::getProperties(
299     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
300 {
301     sal_Bool bTransient;
302     std::auto_ptr< DAVResourceAccess > xResAccess;
303     std::auto_ptr< ContentProperties > xCachedProps;
304     rtl::Reference< ContentProvider >  xProvider;
305 
306     {
307         osl::Guard< osl::Mutex > aGuard( m_aMutex );
308 
309         bTransient = m_bTransient;
310         xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
311         if ( m_xCachedProps.get() )
312             xCachedProps.reset(
313                 new ContentProperties( *m_xCachedProps.get() ) );
314         xProvider.set( m_pProvider );
315     }
316 
317     typedef std::set< rtl::OUString > StringSet;
318     StringSet aPropSet;
319 
320     // No server access for just created (not yet committed) objects.
321     // Only a minimal set of properties supported at this stage.
322     if ( !bTransient )
323     {
324         // Obtain all properties supported for this resource from server.
325         try
326         {
327             std::vector< DAVResourceInfo > props;
328             xResAccess->PROPFIND( DAVZERO, props, xEnv );
329 
330             // Note: vector always contains exactly one resource info, because
331             //       we used a depth of DAVZERO for PROPFIND.
332             aPropSet.insert( (*props.begin()).properties.begin(),
333                              (*props.begin()).properties.end() );
334         }
335         catch ( DAVException const & )
336         {
337         }
338     }
339 
340     // Add DAV properties, map DAV properties to UCB properties.
341     sal_Bool bHasCreationDate     = sal_False; // creationdate     <-> DateCreated
342     sal_Bool bHasGetLastModified  = sal_False; // getlastmodified  <-> DateModified
343     sal_Bool bHasGetContentType   = sal_False; // getcontenttype   <-> MediaType
344     sal_Bool bHasGetContentLength = sal_False; // getcontentlength <-> Size
345 
346     sal_Bool bHasContentType      = sal_False;
347     sal_Bool bHasIsDocument       = sal_False;
348     sal_Bool bHasIsFolder         = sal_False;
349     sal_Bool bHasTitle            = sal_False;
350     sal_Bool bHasBaseURI          = sal_False;
351     sal_Bool bHasDateCreated      = sal_False;
352     sal_Bool bHasDateModified     = sal_False;
353     sal_Bool bHasMediaType        = sal_False;
354     sal_Bool bHasSize             = sal_False;
355     sal_Bool bHasCreatableInfos   = sal_False;
356 
357     {
358         std::set< rtl::OUString >::const_iterator it  = aPropSet.begin();
359         std::set< rtl::OUString >::const_iterator end = aPropSet.end();
360         while ( it != end )
361         {
362             if ( !bHasCreationDate &&
363                  ( (*it) == DAVProperties::CREATIONDATE ) )
364             {
365                 bHasCreationDate = sal_True;
366             }
367             else if ( !bHasGetLastModified &&
368                       ( (*it) == DAVProperties::GETLASTMODIFIED ) )
369             {
370                 bHasGetLastModified = sal_True;
371             }
372             else if ( !bHasGetContentType &&
373                       ( (*it) == DAVProperties::GETCONTENTTYPE ) )
374             {
375                 bHasGetContentType = sal_True;
376             }
377             else if ( !bHasGetContentLength &&
378                       ( (*it) == DAVProperties::GETCONTENTLENGTH ) )
379             {
380                 bHasGetContentLength = sal_True;
381             }
382             else if ( !bHasContentType &&
383                       (*it).equalsAsciiL(
384                             RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
385             {
386                 bHasContentType = sal_True;
387             }
388             else if ( !bHasIsDocument &&
389                       (*it).equalsAsciiL(
390                             RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
391             {
392                 bHasIsDocument = sal_True;
393             }
394             else if ( !bHasIsFolder &&
395                       (*it).equalsAsciiL(
396                             RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
397             {
398                 bHasIsFolder = sal_True;
399             }
400             else if ( !bHasTitle &&
401                       (*it).equalsAsciiL(
402                             RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
403             {
404                 bHasTitle = sal_True;
405             }
406             else if ( !bHasBaseURI &&
407                       (*it).equalsAsciiL(
408                             RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) )
409             {
410                 bHasBaseURI = sal_True;
411             }
412             else if ( !bHasDateCreated &&
413                       (*it).equalsAsciiL(
414                             RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
415             {
416                 bHasDateCreated = sal_True;
417             }
418             else if ( !bHasDateModified &&
419                       (*it).equalsAsciiL(
420                             RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
421             {
422                 bHasDateModified = sal_True;
423             }
424             else if ( !bHasMediaType &&
425                       (*it).equalsAsciiL(
426                             RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
427             {
428                 bHasMediaType = sal_True;
429             }
430             else if ( !bHasSize &&
431                       (*it).equalsAsciiL(
432                             RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
433             {
434                 bHasSize = sal_True;
435             }
436             else if ( !bHasCreatableInfos &&
437                       (*it).equalsAsciiL(
438                             RTL_CONSTASCII_STRINGPARAM(
439                                 "CreatableContentsInfo" ) ) )
440             {
441                 bHasCreatableInfos = sal_True;
442             }
443             it++;
444         }
445     }
446 
447     // Add mandatory properties.
448     if ( !bHasContentType )
449         aPropSet.insert(
450             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ) );
451 
452     if ( !bHasIsDocument )
453         aPropSet.insert(
454             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ) );
455 
456     if ( !bHasIsFolder )
457         aPropSet.insert(
458             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) );
459 
460     if ( !bHasTitle )
461     {
462         // Always present since it can be calculated from content's URI.
463         aPropSet.insert(
464             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) );
465     }
466 
467     // Add optional properties.
468 
469     if ( !bHasBaseURI )
470     {
471         // Always present since it can be calculated from content's URI.
472         aPropSet.insert(
473             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ) );
474     }
475 
476     if ( !bHasDateCreated && bHasCreationDate )
477         aPropSet.insert(
478             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ) );
479 
480     if ( !bHasDateModified && bHasGetLastModified )
481         aPropSet.insert(
482             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ) );
483 
484     if ( !bHasMediaType && bHasGetContentType )
485         aPropSet.insert(
486             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) );
487 
488     if ( !bHasSize && bHasGetContentLength )
489         aPropSet.insert(
490             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ) );
491 
492     if ( !bHasCreatableInfos )
493         aPropSet.insert(
494             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
495                 "CreatableContentsInfo" ) ) );
496 
497     // Add cached properties, if present and still missing.
498     if ( xCachedProps.get() )
499     {
500         const std::set< rtl::OUString >::const_iterator set_end
501             = aPropSet.end();
502 
503         const std::auto_ptr< PropertyValueMap > & xProps
504             = xCachedProps->getProperties();
505 
506         PropertyValueMap::const_iterator       map_it  = xProps->begin();
507         const PropertyValueMap::const_iterator map_end = xProps->end();
508 
509         while ( map_it != map_end )
510         {
511             if ( aPropSet.find( (*map_it).first ) == set_end )
512                 aPropSet.insert( (*map_it).first );
513 
514             ++map_it;
515         }
516     }
517 
518     // std::set -> uno::Sequence
519     sal_Int32 nCount = aPropSet.size();
520     uno::Sequence< beans::Property > aProperties( nCount );
521 
522     std::set< rtl::OUString >::const_iterator it = aPropSet.begin();
523     beans::Property aProp;
524 
525     for ( sal_Int32 n = 0; n < nCount; ++n, ++it )
526     {
527         xProvider->getProperty( (*it), aProp );
528         aProperties[ n ] = aProp;
529     }
530 
531     return aProperties;
532 }
533 
534 //=========================================================================
535 // virtual
536 uno::Sequence< ucb::CommandInfo > Content::getCommands(
537     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
538 {
539     osl::Guard< osl::Mutex > aGuard( m_aMutex );
540 
541     uno::Sequence< ucb::CommandInfo > aCmdInfo( 8 );
542 
543     ///////////////////////////////////////////////////////////////
544     // Mandatory commands
545     ///////////////////////////////////////////////////////////////
546 
547     aCmdInfo[ 0 ] =
548             ucb::CommandInfo(
549                 rtl::OUString(
550                     RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
551                 -1,
552                 getCppuVoidType() );
553     aCmdInfo[ 1 ] =
554             ucb::CommandInfo(
555                 rtl::OUString(
556                     RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
557                 -1,
558                 getCppuVoidType() );
559     aCmdInfo[ 2 ] =
560             ucb::CommandInfo(
561                 rtl::OUString(
562                     RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
563                 -1,
564                 getCppuType( static_cast<
565                                 uno::Sequence< beans::Property > * >( 0 ) ) );
566     aCmdInfo[ 3 ] =
567             ucb::CommandInfo(
568                 rtl::OUString(
569                     RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
570                 -1,
571                 getCppuType( static_cast<
572                     uno::Sequence< beans::PropertyValue > * >( 0 ) ) );
573 
574     ///////////////////////////////////////////////////////////////
575     // Optional standard commands
576     ///////////////////////////////////////////////////////////////
577 
578     aCmdInfo[ 4 ] =
579             ucb::CommandInfo(
580                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
581                 -1,
582                 getCppuBooleanType() );
583     aCmdInfo[ 5 ] =
584             ucb::CommandInfo(
585                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
586                 -1,
587                 getCppuType( static_cast<
588                     ucb::InsertCommandArgument * >( 0 ) ) );
589     aCmdInfo[ 6 ] =
590             ucb::CommandInfo(
591                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
592                 -1,
593                 getCppuType( static_cast<
594                     ucb::OpenCommandArgument2 * >( 0 ) ) );
595 
596     ///////////////////////////////////////////////////////////////
597     // New commands
598     ///////////////////////////////////////////////////////////////
599 
600     aCmdInfo[ 7 ] =
601             ucb::CommandInfo(
602                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) ),
603                 -1,
604                 getCppuType( static_cast<
605                     ucb::PostCommandArgument2 * >( 0 ) ) );
606 
607     sal_Bool bFolder = sal_False;
608 
609     try
610     {
611         bFolder = isFolder( xEnv );
612     }
613     catch ( uno::Exception const & )
614     {
615         return aCmdInfo;
616     }
617 
618     sal_Bool bSupportsLocking = supportsExclusiveWriteLock( xEnv );
619 
620     sal_Int32 nPos = aCmdInfo.getLength();
621     sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 );
622     if ( nMoreCmds )
623         aCmdInfo.realloc( nPos + nMoreCmds );
624     else
625         return aCmdInfo;
626 
627     if ( bFolder )
628     {
629         ///////////////////////////////////////////////////////////////
630         // Optional standard commands
631         ///////////////////////////////////////////////////////////////
632 
633         aCmdInfo[ nPos ] =
634             ucb::CommandInfo(
635                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
636                 -1,
637                 getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) );
638         nPos++;
639         aCmdInfo[ nPos ] =
640             ucb::CommandInfo(
641                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
642                     "createNewContent" ) ),
643                 -1,
644                 getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) );
645         nPos++;
646     }
647     else
648     {
649         // no document-only commands at the moment.
650     }
651 
652     if ( bSupportsLocking )
653     {
654         aCmdInfo[ nPos ] =
655             ucb::CommandInfo(
656                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lock" ) ),
657                 -1,
658                 getCppuVoidType() );
659         nPos++;
660         aCmdInfo[ nPos ] =
661             ucb::CommandInfo(
662                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unlock" ) ),
663                 -1,
664                 getCppuVoidType() );
665         nPos++;
666     }
667     return aCmdInfo;
668 }
669