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