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