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 #include <string.h> 25 #include <unistd.h> 26 #include <sys/types.h> 27 28 #include <osl/time.h> 29 30 #include <osl/diagnose.h> 31 #include <osl/doublecheckedlocking.h> 32 33 #include <com/sun/star/beans/PropertyValue.hpp> 34 #include <com/sun/star/beans/PropertyAttribute.hpp> 35 #include <com/sun/star/beans/PropertySetInfoChange.hpp> 36 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> 37 #include <com/sun/star/io/XActiveDataSink.hpp> 38 #include <com/sun/star/io/XOutputStream.hpp> 39 #include <com/sun/star/lang/IllegalAccessException.hpp> 40 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 41 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 42 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> 43 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 44 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> 45 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 46 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> 47 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> 48 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> 49 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> 50 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> 51 #include <com/sun/star/ucb/NameClash.hpp> 52 #include <com/sun/star/ucb/NameClashException.hpp> 53 #include <com/sun/star/ucb/OpenMode.hpp> 54 #include <com/sun/star/ucb/PostCommandArgument2.hpp> 55 #include <com/sun/star/ucb/XCommandInfo.hpp> 56 #include <com/sun/star/ucb/XPersistentPropertySet.hpp> 57 #include <com/sun/star/ucb/MissingInputStreamException.hpp> 58 #include <com/sun/star/ucb/MissingPropertiesException.hpp> 59 #include <com/sun/star/ucb/UnsupportedCommandException.hpp> 60 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> 61 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> 62 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> 63 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> 64 #include <com/sun/star/ucb/NameClashException.hpp> 65 #include <com/sun/star/ucb/XDynamicResultSet.hpp> 66 #include <com/sun/star/ucb/XContentCreator.hpp> 67 68 #include <ucbhelper/contentidentifier.hxx> 69 #include <ucbhelper/propertyvalueset.hxx> 70 #include <ucbhelper/interactionrequest.hxx> 71 #include <ucbhelper/cancelcommandexecution.hxx> 72 73 #include <osl/conditn.hxx> 74 75 #include "gio_content.hxx" 76 #include "gio_provider.hxx" 77 #include "gio_resultset.hxx" 78 #include "gio_inputstream.hxx" 79 #include "gio_outputstream.hxx" 80 #include "gio_mount.hxx" 81 82 #include <stdio.h> 83 84 using namespace com::sun::star; 85 86 namespace gio 87 { 88 89 Content::Content( 90 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 91 ContentProvider* pProvider, 92 const uno::Reference< ucb::XContentIdentifier >& Identifier) 93 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 94 m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(false) 95 { 96 #ifdef DEBUG 97 fprintf(stderr, "New Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); 98 #endif 99 } 100 101 Content::Content( 102 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 103 ContentProvider* pProvider, 104 const uno::Reference< ucb::XContentIdentifier >& Identifier, 105 sal_Bool bIsFolder) 106 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 107 m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(true) 108 { 109 #ifdef DEBUG 110 fprintf(stderr, "Create Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); 111 #endif 112 mpInfo = g_file_info_new(); 113 g_file_info_set_file_type(mpInfo, bIsFolder ? G_FILE_TYPE_DIRECTORY : G_FILE_TYPE_REGULAR); 114 } 115 116 Content::~Content() 117 { 118 if (mpInfo) g_object_unref(mpInfo); 119 if (mpFile) g_object_unref(mpFile); 120 } 121 122 rtl::OUString Content::getParentURL() 123 { 124 rtl::OUString sURL; 125 if (GFile* pFile = g_file_get_parent(getGFile())) 126 { 127 char* pPath = g_file_get_uri(pFile); 128 g_object_unref(pFile); 129 sURL = rtl::OUString::createFromAscii(pPath); 130 g_free(pPath); 131 } 132 return sURL; 133 } 134 135 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) 136 { 137 //TODO 138 //stick a map from each CommandId to a new GCancellable and propagate 139 //it throughout the g_file_* calls 140 } 141 142 rtl::OUString SAL_CALL Content::getContentType() 143 { 144 return isFolder(uno::Reference< ucb::XCommandEnvironment >()) 145 ? rtl::OUString::createFromAscii( GIO_FOLDER_TYPE ) 146 : rtl::OUString::createFromAscii( GIO_FILE_TYPE ); 147 } 148 149 #define EXCEPT(aExcept) \ 150 do { \ 151 if (bThrow) throw aExcept;\ 152 aRet = uno::makeAny( aExcept );\ 153 } while(0) 154 155 uno::Any convertToException(GError *pError, const uno::Reference< uno::XInterface >& rContext, bool bThrow) 156 { 157 uno::Any aRet; 158 159 gint eCode = pError->code; 160 rtl::OUString sMessage(pError->message, strlen(pError->message), RTL_TEXTENCODING_UTF8); 161 g_error_free(pError); 162 163 rtl::OUString sName; 164 rtl::OUString sHost; 165 166 uno::Sequence< uno::Any > aArgs( 1 ); 167 aArgs[ 0 ] <<= sName; 168 169 switch (eCode) 170 { 171 case G_IO_ERROR_FAILED: 172 { io::IOException aExcept(sMessage, rContext); 173 EXCEPT(aExcept); } 174 break; 175 case G_IO_ERROR_NOT_MOUNTED: 176 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 177 task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING_PATH, aArgs); 178 EXCEPT(aExcept); } 179 break; 180 case G_IO_ERROR_NOT_FOUND: 181 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 182 task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING, aArgs); 183 EXCEPT(aExcept); } 184 break; 185 case G_IO_ERROR_EXISTS: 186 { ucb::NameClashException aExcept(sMessage, rContext, 187 task::InteractionClassification_ERROR, sName); 188 EXCEPT(aExcept); } 189 break; 190 case G_IO_ERROR_INVALID_ARGUMENT: 191 { lang::IllegalArgumentException aExcept(sMessage, rContext, -1 ); 192 EXCEPT(aExcept); } 193 break; 194 case G_IO_ERROR_PERMISSION_DENIED: 195 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 196 task::InteractionClassification_ERROR, ucb::IOErrorCode_ACCESS_DENIED, aArgs); 197 EXCEPT(aExcept); } 198 break; 199 case G_IO_ERROR_IS_DIRECTORY: 200 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 201 task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs); 202 EXCEPT(aExcept); } 203 break; 204 case G_IO_ERROR_NOT_REGULAR_FILE: 205 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 206 task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs); 207 EXCEPT(aExcept); } 208 break; 209 case G_IO_ERROR_NOT_DIRECTORY: 210 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 211 task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_DIRECTORY, aArgs); 212 EXCEPT(aExcept); } 213 break; 214 case G_IO_ERROR_FILENAME_TOO_LONG: 215 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 216 task::InteractionClassification_ERROR, ucb::IOErrorCode_NAME_TOO_LONG, aArgs); 217 EXCEPT(aExcept); } 218 break; 219 case G_IO_ERROR_PENDING: 220 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 221 task::InteractionClassification_ERROR, ucb::IOErrorCode_PENDING, aArgs); 222 EXCEPT(aExcept); } 223 break; 224 case G_IO_ERROR_CLOSED: 225 case G_IO_ERROR_CANCELLED: 226 case G_IO_ERROR_TOO_MANY_LINKS: 227 case G_IO_ERROR_WRONG_ETAG: 228 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 229 task::InteractionClassification_ERROR, ucb::IOErrorCode_GENERAL, aArgs); 230 EXCEPT(aExcept); } 231 break; 232 case G_IO_ERROR_NOT_SUPPORTED: 233 case G_IO_ERROR_CANT_CREATE_BACKUP: 234 case G_IO_ERROR_WOULD_MERGE: 235 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 236 task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_SUPPORTED, aArgs); 237 EXCEPT(aExcept); } 238 break; 239 case G_IO_ERROR_NO_SPACE: 240 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 241 task::InteractionClassification_ERROR, ucb::IOErrorCode_OUT_OF_DISK_SPACE, aArgs); 242 EXCEPT(aExcept); } 243 break; 244 case G_IO_ERROR_INVALID_FILENAME: 245 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 246 task::InteractionClassification_ERROR, ucb::IOErrorCode_INVALID_CHARACTER, aArgs); 247 EXCEPT(aExcept); } 248 break; 249 case G_IO_ERROR_READ_ONLY: 250 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 251 task::InteractionClassification_ERROR, ucb::IOErrorCode_WRITE_PROTECTED, aArgs); 252 EXCEPT(aExcept); } 253 break; 254 case G_IO_ERROR_TIMED_OUT: 255 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 256 task::InteractionClassification_ERROR, ucb::IOErrorCode_DEVICE_NOT_READY, aArgs); 257 EXCEPT(aExcept); } 258 break; 259 case G_IO_ERROR_WOULD_RECURSE: 260 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 261 task::InteractionClassification_ERROR, ucb::IOErrorCode_RECURSIVE, aArgs); 262 EXCEPT(aExcept); } 263 break; 264 case G_IO_ERROR_BUSY: 265 case G_IO_ERROR_WOULD_BLOCK: 266 { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, 267 task::InteractionClassification_ERROR, ucb::IOErrorCode_LOCKING_VIOLATION, aArgs); 268 EXCEPT(aExcept); } 269 break; 270 case G_IO_ERROR_HOST_NOT_FOUND: 271 { ucb::InteractiveNetworkResolveNameException aExcept(sMessage, rContext, 272 task::InteractionClassification_ERROR, sHost); 273 EXCEPT(aExcept);} 274 break; 275 default: 276 case G_IO_ERROR_ALREADY_MOUNTED: 277 case G_IO_ERROR_NOT_EMPTY: 278 case G_IO_ERROR_NOT_SYMBOLIC_LINK: 279 case G_IO_ERROR_NOT_MOUNTABLE_FILE: 280 case G_IO_ERROR_FAILED_HANDLED: 281 { ucb::InteractiveNetworkGeneralException aExcept(sMessage, rContext, 282 task::InteractionClassification_ERROR); 283 EXCEPT(aExcept);} 284 break; 285 } 286 return aRet; 287 } 288 289 uno::Any Content::mapGIOError( GError *pError ) 290 { 291 if (!pError) 292 return getBadArgExcept(); 293 294 return convertToException(pError, static_cast< cppu::OWeakObject * >(this), false); 295 } 296 297 uno::Any Content::getBadArgExcept() 298 { 299 return uno::makeAny( lang::IllegalArgumentException( 300 rtl::OUString::createFromAscii( "Wrong argument type!" ), 301 static_cast< cppu::OWeakObject * >( this ), -1) ); 302 } 303 304 class MountOperation 305 { 306 GMainLoop *mpLoop; 307 GMountOperation *mpAuthentication; 308 GError *mpError; 309 static void Completed(GObject *source, GAsyncResult *res, gpointer user_data); 310 public: 311 MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv); 312 ~MountOperation(); 313 GError *Mount(GFile *pFile); 314 }; 315 316 MountOperation::MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv) : mpError(NULL) 317 { 318 mpLoop = g_main_loop_new(NULL, FALSE); 319 mpAuthentication = ooo_mount_operation_new(xEnv); 320 } 321 322 void MountOperation::Completed(GObject *source, GAsyncResult *res, gpointer user_data) 323 { 324 MountOperation *pThis = (MountOperation*)user_data; 325 g_file_mount_enclosing_volume_finish(G_FILE(source), res, &(pThis->mpError)); 326 g_main_loop_quit(pThis->mpLoop); 327 } 328 329 GError *MountOperation::Mount(GFile *pFile) 330 { 331 g_file_mount_enclosing_volume(pFile, G_MOUNT_MOUNT_NONE, mpAuthentication, NULL, MountOperation::Completed, this); 332 g_main_loop_run(mpLoop); 333 return mpError; 334 } 335 336 MountOperation::~MountOperation() 337 { 338 g_object_unref(mpAuthentication); 339 g_main_loop_unref(mpLoop); 340 } 341 342 GFileInfo* Content::getGFileInfo(const uno::Reference< ucb::XCommandEnvironment >& xEnv, GError **ppError) 343 { 344 /*If we don't have it already, and we're not a "pre-creation" content then query for the info"*/ 345 if (!mpInfo && !mbTransient) 346 { 347 if (!(mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError))) 348 { 349 //Try and mount if unmounted 350 if (ppError && (*ppError)->code == G_IO_ERROR_NOT_MOUNTED) 351 { 352 g_error_free(*ppError); 353 354 MountOperation aMounter(xEnv); 355 *ppError = aMounter.Mount(getGFile()); 356 357 //No Mount error, reattempt query 358 if (!*ppError) 359 mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError); 360 } 361 } 362 } 363 return mpInfo; 364 } 365 366 GFile* Content::getGFile() 367 { 368 if (!mpFile) 369 mpFile = g_file_new_for_uri(rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); 370 return mpFile; 371 } 372 373 bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv) 374 { 375 GFileInfo *pInfo = getGFileInfo(xEnv); 376 return pInfo && (g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY); 377 } 378 379 static util::DateTime getDateFromUnix (time_t t) 380 { 381 TimeValue tv; 382 tv.Nanosec = 0; 383 tv.Seconds = t; 384 oslDateTime dt; 385 386 if ( osl_getDateTimeFromTimeValue( &tv, &dt ) ) 387 return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours, 388 dt.Day, dt.Month, dt.Year); 389 else 390 return util::DateTime(); 391 } 392 393 uno::Reference< sdbc::XRow > Content::getPropertyValuesFromGFileInfo(GFileInfo *pInfo, 394 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 395 const uno::Reference< ucb::XCommandEnvironment > & xEnv, 396 const uno::Sequence< beans::Property >& rProperties) 397 { 398 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rSMgr ); 399 400 sal_Int32 nProps; 401 const beans::Property* pProps; 402 403 nProps = rProperties.getLength(); 404 pProps = rProperties.getConstArray(); 405 406 for( sal_Int32 n = 0; n < nProps; ++n ) 407 { 408 const beans::Property& rProp = pProps[ n ]; 409 410 if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 411 { 412 if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE)) 413 xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_REGULAR || 414 g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_UNKNOWN ) ); 415 else 416 xRow->appendVoid( rProp ); 417 } 418 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 419 { 420 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) ) 421 xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_DIRECTORY )); 422 else 423 xRow->appendVoid( rProp ); 424 } 425 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 426 { 427 if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)) 428 { 429 const char *pName = g_file_info_get_display_name(pInfo); 430 xRow->appendString( rProp, rtl::OUString(pName, strlen(pName), RTL_TEXTENCODING_UTF8) ); 431 } 432 else 433 xRow->appendVoid( rProp ); 434 } 435 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) 436 { 437 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE ) ) 438 xRow->appendBoolean( rProp, !g_file_info_get_attribute_boolean( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) ); 439 else 440 xRow->appendVoid( rProp ); 441 } 442 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) 443 { 444 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CREATED ) ) 445 xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CREATED)) ); 446 else 447 xRow->appendVoid( rProp ); 448 } 449 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) 450 { 451 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED ) ) 452 xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED)) ); 453 else 454 xRow->appendVoid( rProp ); 455 } 456 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) 457 { 458 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE) ) 459 xRow->appendLong( rProp, ( g_file_info_get_size( pInfo ) )); 460 else 461 xRow->appendVoid( rProp ); 462 } 463 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) ) 464 { 465 //What do we use this for ? 466 xRow->appendBoolean( rProp, sal_False ); 467 } 468 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisc" ) ) ) 469 { 470 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT ) ) 471 xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT) ); 472 else 473 xRow->appendVoid( rProp ); 474 } 475 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsRemoveable" ) ) ) 476 { 477 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) ) 478 xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) ); 479 else 480 xRow->appendVoid( rProp ); 481 } 482 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFloppy" ) ) ) 483 { 484 xRow->appendBoolean( rProp, sal_False ); 485 } 486 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsHidden" ) ) ) 487 { 488 if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) ) 489 xRow->appendBoolean( rProp, ( g_file_info_get_is_hidden ( pInfo ) ) ); 490 else 491 xRow->appendVoid( rProp ); 492 } 493 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 494 { 495 xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) ); 496 } 497 #ifdef DEBUG 498 else 499 { 500 fprintf(stderr, "Looking for unsupported property %s\n", 501 rtl::OUStringToOString(rProp.Name, RTL_TEXTENCODING_UTF8).getStr()); 502 } 503 #endif 504 } 505 506 return uno::Reference< sdbc::XRow >( xRow.get() ); 507 } 508 509 uno::Reference< sdbc::XRow > Content::getPropertyValues( 510 const uno::Sequence< beans::Property >& rProperties, 511 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 512 { 513 GError *pError = NULL; 514 GFileInfo *pInfo = getGFileInfo(xEnv, &pError); 515 if (!pInfo) 516 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 517 518 return getPropertyValuesFromGFileInfo(pInfo, m_xSMgr, xEnv, rProperties); 519 } 520 521 static lang::IllegalAccessException 522 getReadOnlyException( const uno::Reference< uno::XInterface >& rContext ) 523 { 524 return lang::IllegalAccessException ( rtl::OUString::createFromAscii( "Property is read-only!" ), rContext ); 525 } 526 527 void Content::queryChildren( ContentRefList& rChildren ) 528 { 529 // Obtain a list with a snapshot of all currently instantiated contents 530 // from provider and extract the contents which are direct children 531 // of this content. 532 533 ucbhelper::ContentRefList aAllContents; 534 m_xProvider->queryExistingContents( aAllContents ); 535 536 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 537 sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); 538 539 if ( nURLPos != ( aURL.getLength() - 1 ) ) 540 aURL += rtl::OUString::createFromAscii( "/" ); 541 542 sal_Int32 nLen = aURL.getLength(); 543 544 ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 545 ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 546 547 while ( it != end ) 548 { 549 ucbhelper::ContentImplHelperRef xChild = (*it); 550 rtl::OUString aChildURL = xChild->getIdentifier()->getContentIdentifier(); 551 552 // Is aURL a prefix of aChildURL? 553 if ( ( aChildURL.getLength() > nLen ) && ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 554 { 555 sal_Int32 nPos = nLen; 556 nPos = aChildURL.indexOf( '/', nPos ); 557 558 if ( ( nPos == -1 ) || ( nPos == ( aChildURL.getLength() - 1 ) ) ) 559 { 560 // No further slashes / only a final slash. It's a child! 561 rChildren.push_back( ::gio::Content::ContentRef (static_cast< ::gio::Content * >(xChild.get() ) ) ); 562 } 563 } 564 ++it; 565 } 566 } 567 568 sal_Bool Content::exchangeIdentity( const uno::Reference< ucb::XContentIdentifier >& xNewId ) 569 { 570 if ( !xNewId.is() ) 571 return sal_False; 572 573 uno::Reference< ucb::XContent > xThis = this; 574 575 if ( mbTransient ) 576 { 577 m_xIdentifier = xNewId; 578 return sal_False; 579 } 580 581 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); 582 583 // Exchange own identitity. 584 if ( exchange( xNewId ) ) 585 { 586 // Process instantiated children... 587 ContentRefList aChildren; 588 queryChildren( aChildren ); 589 590 ContentRefList::const_iterator it = aChildren.begin(); 591 ContentRefList::const_iterator end = aChildren.end(); 592 593 while ( it != end ) 594 { 595 ContentRef xChild = (*it); 596 597 // Create new content identifier for the child... 598 uno::Reference< ucb::XContentIdentifier > xOldChildId = xChild->getIdentifier(); 599 rtl::OUString aOldChildURL = xOldChildId->getContentIdentifier(); 600 rtl::OUString aNewChildURL = aOldChildURL.replaceAt( 601 0, aOldURL.getLength(), xNewId->getContentIdentifier() ); 602 603 uno::Reference< ucb::XContentIdentifier > xNewChildId 604 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL ); 605 606 if ( !xChild->exchangeIdentity( xNewChildId ) ) 607 return sal_False; 608 609 ++it; 610 } 611 return sal_True; 612 } 613 614 return sal_False; 615 } 616 617 uno::Sequence< uno::Any > Content::setPropertyValues( 618 const uno::Sequence< beans::PropertyValue >& rValues, 619 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 620 { 621 GError *pError=NULL; 622 GFileInfo *pNewInfo=NULL; 623 GFileInfo *pInfo = getGFileInfo(xEnv, &pError); 624 if (pInfo) 625 pNewInfo = g_file_info_dup(pInfo); 626 else 627 { 628 if (!mbTransient) 629 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 630 else 631 { 632 if (pError) 633 g_error_free(pError); 634 pNewInfo = g_file_info_new(); 635 } 636 } 637 638 sal_Int32 nCount = rValues.getLength(); 639 640 beans::PropertyChangeEvent aEvent; 641 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 642 aEvent.Further = sal_False; 643 aEvent.PropertyHandle = -1; 644 645 sal_Int32 nChanged = 0, nTitlePos = -1; 646 const char *newName = NULL; 647 uno::Sequence< beans::PropertyChangeEvent > aChanges(nCount); 648 649 uno::Sequence< uno::Any > aRet( nCount ); 650 const beans::PropertyValue* pValues = rValues.getConstArray(); 651 for ( sal_Int32 n = 0; n < nCount; ++n ) 652 { 653 const beans::PropertyValue& rValue = pValues[ n ]; 654 #ifdef DEBUG 655 g_warning("Set prop '%s'", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr()); 656 #endif 657 if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || 658 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) || 659 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || 660 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || 661 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) || 662 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 663 { 664 aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) ); 665 } 666 else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 667 { 668 rtl::OUString aNewTitle; 669 if (!( rValue.Value >>= aNewTitle )) 670 { 671 aRet[ n ] <<= beans::IllegalTypeException 672 ( rtl::OUString::createFromAscii( "Property value has wrong type!" ), 673 static_cast< cppu::OWeakObject * >( this ) ); 674 continue; 675 } 676 677 if ( aNewTitle.getLength() <= 0 ) 678 { 679 aRet[ n ] <<= lang::IllegalArgumentException 680 ( rtl::OUString::createFromAscii( "Empty title not allowed!" ), 681 static_cast< cppu::OWeakObject * >( this ), -1 ); 682 continue; 683 684 } 685 686 rtl::OString sNewTitle = OUStringToOString(aNewTitle, RTL_TEXTENCODING_UTF8); 687 newName = sNewTitle.getStr(); 688 const char *oldName = g_file_info_get_name( pInfo); 689 690 if (!newName || !oldName || strcmp(newName, oldName)) 691 { 692 #ifdef DEBUG 693 g_warning ("Set new name to '%s'", newName); 694 #endif 695 696 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); 697 if (oldName) 698 aEvent.OldValue = uno::makeAny(rtl::OUString(oldName, strlen(oldName), RTL_TEXTENCODING_UTF8)); 699 aEvent.NewValue = uno::makeAny(aNewTitle); 700 aChanges.getArray()[ nChanged ] = aEvent; 701 nTitlePos = nChanged++; 702 703 g_file_info_set_name(pNewInfo, newName); 704 } 705 } 706 else 707 { 708 #ifdef DEBUG 709 fprintf(stderr, "Unknown property %s\n", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr()); 710 #endif 711 aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) ); 712 //TODO 713 } 714 } 715 716 if (nChanged) 717 { 718 bool bOk = true; 719 if (!mbTransient) 720 { 721 if ((bOk = doSetFileInfo(pNewInfo))) 722 { 723 for (sal_Int32 i = 0; i < nChanged; ++i) 724 aRet[ i ] <<= getBadArgExcept(); 725 } 726 } 727 728 if (bOk) 729 { 730 if (nTitlePos > -1) 731 { 732 rtl::OUString aNewURL = getParentURL(); 733 aNewURL += rtl::OUString( newName, strlen(newName), RTL_TEXTENCODING_UTF8 ); 734 uno::Reference< ucb::XContentIdentifier > xNewId 735 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); 736 737 if (!exchangeIdentity( xNewId ) ) 738 { 739 aRet[ nTitlePos ] <<= uno::Exception 740 ( rtl::OUString::createFromAscii( "Exchange failed!" ), 741 static_cast< cppu::OWeakObject * >( this ) ); 742 } 743 } 744 745 if (!mbTransient) //Discard and refetch 746 { 747 g_object_unref(mpInfo); 748 mpInfo = NULL; 749 } 750 751 if (mpInfo) 752 { 753 g_file_info_copy_into(pNewInfo, mpInfo); 754 g_object_unref(pNewInfo); 755 } 756 else 757 mpInfo = pNewInfo; 758 759 if (mpFile) //Discard and refetch 760 { 761 g_object_unref(mpFile); 762 mpFile = NULL; 763 } 764 } 765 766 aChanges.realloc( nChanged ); 767 notifyPropertiesChange( aChanges ); 768 } 769 770 return aRet; 771 } 772 773 bool Content::doSetFileInfo(GFileInfo *pNewInfo) 774 { 775 g_assert (!mbTransient); 776 777 bool bOk = true; 778 GFile *pFile = getGFile(); 779 if(!g_file_set_attributes_from_info(pFile, pNewInfo, G_FILE_QUERY_INFO_NONE, NULL, NULL)) 780 bOk = false; 781 return bOk; 782 } 783 784 const int TRANSFER_BUFFER_SIZE = 65536; 785 786 void Content::copyData( uno::Reference< io::XInputStream > xIn, 787 uno::Reference< io::XOutputStream > xOut ) 788 { 789 uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE ); 790 791 g_return_if_fail( xIn.is() && xOut.is() ); 792 793 while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 ) 794 xOut->writeBytes( theData ); 795 796 xOut->closeOutput(); 797 } 798 799 sal_Bool Content::feedSink( uno::Reference< uno::XInterface > xSink, 800 const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) 801 { 802 if ( !xSink.is() ) 803 return sal_False; 804 805 uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY ); 806 uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY ); 807 808 if ( !xOut.is() && !xDataSink.is() ) 809 return sal_False; 810 811 GError *pError=NULL; 812 GFileInputStream *pStream = g_file_read(getGFile(), NULL, &pError); 813 if (!pStream) 814 convertToException(pError, static_cast< cppu::OWeakObject * >(this)); 815 816 uno::Reference< io::XInputStream > xIn = new ::gio::InputStream(pStream); 817 if ( !xIn.is() ) 818 return sal_False; 819 820 if ( xOut.is() ) 821 copyData( xIn, xOut ); 822 823 if ( xDataSink.is() ) 824 xDataSink->setInputStream( xIn ); 825 826 return sal_True; 827 } 828 829 uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand, 830 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 831 { 832 bool bIsFolder = isFolder(xEnv); 833 834 if (!g_file_query_exists(getGFile(), NULL)) 835 { 836 uno::Sequence< uno::Any > aArgs( 1 ); 837 aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier(); 838 uno::Any aErr = uno::makeAny( 839 ucb::InteractiveAugmentedIOException(rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), 840 task::InteractionClassification_ERROR, 841 bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs) 842 ); 843 844 ucbhelper::cancelCommandExecution(aErr, xEnv); 845 } 846 847 uno::Any aRet; 848 849 sal_Bool bOpenFolder = ( 850 ( rOpenCommand.Mode == ucb::OpenMode::ALL ) || 851 ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || 852 ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) 853 ); 854 855 if ( bOpenFolder && bIsFolder ) 856 { 857 uno::Reference< ucb::XDynamicResultSet > xSet 858 = new DynamicResultSet(m_xSMgr, this, rOpenCommand, xEnv ); 859 aRet <<= xSet; 860 } 861 else if ( rOpenCommand.Sink.is() ) 862 { 863 if ( 864 ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 865 ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) 866 ) 867 { 868 ucbhelper::cancelCommandExecution( 869 uno::makeAny ( ucb::UnsupportedOpenModeException 870 ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), 871 sal_Int16( rOpenCommand.Mode ) ) ), 872 xEnv ); 873 } 874 875 if ( !feedSink( rOpenCommand.Sink, xEnv ) ) 876 { 877 // Note: rOpenCommand.Sink may contain an XStream 878 // implementation. Support for this type of 879 // sink is optional... 880 #ifdef DEBUG 881 g_warning ("Failed to load data from '%s'", 882 rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); 883 #endif 884 885 ucbhelper::cancelCommandExecution( 886 uno::makeAny (ucb::UnsupportedDataSinkException 887 ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), 888 rOpenCommand.Sink ) ), 889 xEnv ); 890 } 891 } 892 else 893 g_warning ("Open falling through ..."); 894 return aRet; 895 } 896 897 uno::Any SAL_CALL Content::execute( 898 const ucb::Command& aCommand, 899 sal_Int32 /*CommandId*/, 900 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 901 { 902 #ifdef DEBUG 903 fprintf(stderr, "Content::execute %s\n", rtl::OUStringToOString(aCommand.Name, RTL_TEXTENCODING_UTF8).getStr()); 904 #endif 905 uno::Any aRet; 906 907 if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) )) 908 { 909 uno::Sequence< beans::Property > Properties; 910 if ( !( aCommand.Argument >>= Properties ) ) 911 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 912 aRet <<= getPropertyValues( Properties, xEnv ); 913 } 914 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) )) 915 aRet <<= getPropertySetInfo( xEnv, sal_False ); 916 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) )) 917 aRet <<= getCommandInfo( xEnv, sal_False ); 918 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "open" ) )) 919 { 920 ucb::OpenCommandArgument2 aOpenCommand; 921 if ( !( aCommand.Argument >>= aOpenCommand ) ) 922 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 923 aRet = open( aOpenCommand, xEnv ); 924 } 925 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "transfer" ) )) 926 { 927 ucb::TransferInfo transferArgs; 928 if ( !( aCommand.Argument >>= transferArgs ) ) 929 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 930 transfer( transferArgs, xEnv ); 931 } 932 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) )) 933 { 934 uno::Sequence< beans::PropertyValue > aProperties; 935 if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() ) 936 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 937 aRet <<= setPropertyValues( aProperties, xEnv ); 938 } 939 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) 940 && isFolder( xEnv ) ) 941 { 942 ucb::ContentInfo arg; 943 if ( !( aCommand.Argument >>= arg ) ) 944 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 945 aRet <<= createNewContent( arg ); 946 } 947 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "insert" ) )) 948 { 949 ucb::InsertCommandArgument arg; 950 if ( !( aCommand.Argument >>= arg ) ) 951 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); 952 insert( arg.Data, arg.ReplaceExisting, xEnv ); 953 } 954 else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) )) 955 { 956 sal_Bool bDeletePhysical = sal_False; 957 aCommand.Argument >>= bDeletePhysical; 958 959 //If no delete physical, try and trashcan it, if that doesn't work go 960 //ahead and try and delete it anyway 961 if (!bDeletePhysical && !g_file_trash(getGFile(), NULL, NULL)) 962 bDeletePhysical = true; 963 964 if (bDeletePhysical) 965 { 966 GError *pError = NULL; 967 if (!g_file_delete( getGFile(), NULL, &pError)) 968 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 969 } 970 971 destroy( bDeletePhysical ); 972 } 973 else 974 { 975 #ifdef DEBUG 976 fprintf(stderr, "UNKNOWN COMMAND\n"); 977 //TODO 978 #endif 979 980 ucbhelper::cancelCommandExecution 981 ( uno::makeAny( ucb::UnsupportedCommandException 982 ( rtl::OUString(), 983 static_cast< cppu::OWeakObject * >( this ) ) ), 984 xEnv ); 985 } 986 987 return aRet; 988 } 989 990 void Content::destroy( sal_Bool bDeletePhysical ) 991 { 992 uno::Reference< ucb::XContent > xThis = this; 993 994 deleted(); 995 996 ::gio::Content::ContentRefList aChildren; 997 queryChildren( aChildren ); 998 999 ContentRefList::const_iterator it = aChildren.begin(); 1000 ContentRefList::const_iterator end = aChildren.end(); 1001 1002 while ( it != end ) 1003 { 1004 (*it)->destroy( bDeletePhysical ); 1005 ++it; 1006 } 1007 } 1008 1009 void Content::insert(const uno::Reference< io::XInputStream > &xInputStream, 1010 sal_Bool bReplaceExisting, const uno::Reference< ucb::XCommandEnvironment > &xEnv ) 1011 { 1012 GError *pError = NULL; 1013 GFileInfo *pInfo = getGFileInfo(xEnv); 1014 1015 if ( g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) && 1016 g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY ) 1017 { 1018 #ifdef DEBUG 1019 g_warning ("Make directory"); 1020 #endif 1021 if( !g_file_make_directory( getGFile(), NULL, &pError)) 1022 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 1023 return; 1024 } 1025 1026 if ( !xInputStream.is() ) 1027 { 1028 ucbhelper::cancelCommandExecution( uno::makeAny 1029 ( ucb::MissingInputStreamException 1030 ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ) ) ), 1031 xEnv ); 1032 } 1033 1034 GFileOutputStream* pOutStream = NULL; 1035 if ( bReplaceExisting ) 1036 { 1037 if (!(pOutStream = g_file_replace(getGFile(), NULL, false, G_FILE_CREATE_PRIVATE, NULL, &pError))) 1038 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 1039 } 1040 else 1041 { 1042 if (!(pOutStream = g_file_create (getGFile(), G_FILE_CREATE_PRIVATE, NULL, &pError))) 1043 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 1044 } 1045 1046 uno::Reference < io::XOutputStream > xOutput = new ::gio::OutputStream(pOutStream); 1047 copyData( xInputStream, xOutput ); 1048 1049 if (mbTransient) 1050 { 1051 mbTransient = sal_False; 1052 inserted(); 1053 } 1054 } 1055 1056 void Content::transfer( const ucb::TransferInfo& aTransferInfo, const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1057 { 1058 rtl::OUString sDest = m_xIdentifier->getContentIdentifier(); 1059 if (aTransferInfo.NewTitle.getLength()) 1060 sDest += aTransferInfo.NewTitle; 1061 else 1062 sDest += rtl::OUString::createFromAscii(g_file_get_basename(getGFile())); 1063 1064 GFile *pDest = g_file_new_for_uri(rtl::OUStringToOString(sDest, RTL_TEXTENCODING_UTF8).getStr()); 1065 GFile *pSource = g_file_new_for_uri(rtl::OUStringToOString(aTransferInfo.SourceURL, RTL_TEXTENCODING_UTF8).getStr()); 1066 1067 gboolean bSuccess = false; 1068 GError *pError = NULL; 1069 if (aTransferInfo.MoveData) 1070 bSuccess = g_file_move(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError); 1071 else 1072 bSuccess = g_file_copy(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError); 1073 g_object_unref(pSource); 1074 g_object_unref(pDest); 1075 if (!bSuccess) 1076 ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); 1077 } 1078 1079 uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo( 1080 const uno::Reference< ucb::XCommandEnvironment >& xEnv) 1081 { 1082 if ( isFolder( xEnv ) ) 1083 { 1084 uno::Sequence< ucb::ContentInfo > seq(2); 1085 1086 // Minimum set of props we really need 1087 uno::Sequence< beans::Property > props( 1 ); 1088 props[0] = beans::Property( 1089 rtl::OUString::createFromAscii( "Title" ), 1090 -1, 1091 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 1092 beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); 1093 1094 // file 1095 seq[0].Type = rtl::OUString::createFromAscii( GIO_FILE_TYPE ); 1096 seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | 1097 ucb::ContentInfoAttribute::KIND_DOCUMENT ); 1098 seq[0].Properties = props; 1099 1100 // folder 1101 seq[1].Type = rtl::OUString::createFromAscii( GIO_FOLDER_TYPE ); 1102 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; 1103 seq[1].Properties = props; 1104 1105 return seq; 1106 } 1107 else 1108 { 1109 return uno::Sequence< ucb::ContentInfo >(); 1110 } 1111 } 1112 1113 uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo() 1114 { 1115 return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() ); 1116 } 1117 1118 uno::Reference< ucb::XContent > 1119 SAL_CALL Content::createNewContent( const ucb::ContentInfo& Info ) 1120 { 1121 bool create_document; 1122 const char *name; 1123 1124 if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FILE_TYPE ) ) ) 1125 create_document = true; 1126 else if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FOLDER_TYPE ) ) ) 1127 create_document = false; 1128 else 1129 { 1130 #ifdef DEBUG 1131 g_warning( "Failed to create new content '%s'", rtl::OUStringToOString(Info.Type, 1132 RTL_TEXTENCODING_UTF8).getStr() ); 1133 #endif 1134 return uno::Reference< ucb::XContent >(); 1135 } 1136 1137 #ifdef DEBUG 1138 g_warning( "createNewContent (%d)", (int) create_document ); 1139 #endif 1140 1141 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 1142 1143 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) 1144 aURL += rtl::OUString::createFromAscii( "/" ); 1145 1146 name = create_document ? "[New_Content]" : "[New_Collection]"; 1147 aURL += rtl::OUString::createFromAscii( name ); 1148 1149 uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(m_xSMgr, aURL)); 1150 1151 try 1152 { 1153 return new ::gio::Content( m_xSMgr, m_pProvider, xId, !create_document ); 1154 } catch ( ucb::ContentCreationException & ) 1155 { 1156 return uno::Reference< ucb::XContent >(); 1157 } 1158 } 1159 1160 uno::Sequence< uno::Type > SAL_CALL Content::getTypes() 1161 { 1162 if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) ) 1163 { 1164 static cppu::OTypeCollection aFolderCollection 1165 (CPPU_TYPE_REF( lang::XTypeProvider ), 1166 CPPU_TYPE_REF( lang::XServiceInfo ), 1167 CPPU_TYPE_REF( lang::XComponent ), 1168 CPPU_TYPE_REF( ucb::XContent ), 1169 CPPU_TYPE_REF( ucb::XCommandProcessor ), 1170 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 1171 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 1172 CPPU_TYPE_REF( beans::XPropertyContainer ), 1173 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 1174 CPPU_TYPE_REF( container::XChild ), 1175 CPPU_TYPE_REF( ucb::XContentCreator ) ); 1176 return aFolderCollection.getTypes(); 1177 } 1178 else 1179 { 1180 static cppu::OTypeCollection aFileCollection 1181 (CPPU_TYPE_REF( lang::XTypeProvider ), 1182 CPPU_TYPE_REF( lang::XServiceInfo ), 1183 CPPU_TYPE_REF( lang::XComponent ), 1184 CPPU_TYPE_REF( ucb::XContent ), 1185 CPPU_TYPE_REF( ucb::XCommandProcessor ), 1186 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 1187 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 1188 CPPU_TYPE_REF( beans::XPropertyContainer ), 1189 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 1190 CPPU_TYPE_REF( container::XChild ) ); 1191 1192 return aFileCollection.getTypes(); 1193 } 1194 } 1195 1196 uno::Sequence< beans::Property > Content::getProperties( 1197 const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) 1198 { 1199 static const beans::Property aGenericProperties[] = 1200 { 1201 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), 1202 -1, getCppuBooleanType(), 1203 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1204 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), 1205 -1, getCppuBooleanType(), 1206 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1207 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), 1208 -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1209 beans::PropertyAttribute::BOUND ), 1210 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), 1211 -1, getCppuBooleanType(), 1212 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1213 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), 1214 -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), 1215 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1216 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ), 1217 -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), 1218 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1219 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), 1220 -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ), 1221 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1222 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVolume" ) ), 1223 -1, getCppuBooleanType(), 1224 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1225 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCompactDisc" ) ), 1226 -1, getCppuBooleanType(), 1227 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1228 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsRemoveable" ) ), 1229 -1, getCppuBooleanType(), 1230 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1231 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), 1232 -1, getCppuBooleanType(), 1233 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), 1234 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), 1235 -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), 1236 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) 1237 }; 1238 1239 const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]); 1240 return uno::Sequence< beans::Property > ( aGenericProperties, nProps ); 1241 } 1242 1243 uno::Sequence< ucb::CommandInfo > Content::getCommands( const uno::Reference< ucb::XCommandEnvironment > & xEnv) 1244 { 1245 static ucb::CommandInfo aCommandInfoTable[] = 1246 { 1247 // Required commands 1248 ucb::CommandInfo 1249 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), 1250 -1, getCppuVoidType() ), 1251 ucb::CommandInfo 1252 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), 1253 -1, getCppuVoidType() ), 1254 ucb::CommandInfo 1255 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), 1256 -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ), 1257 ucb::CommandInfo 1258 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), 1259 -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ), 1260 1261 // Optional standard commands 1262 ucb::CommandInfo 1263 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), 1264 -1, getCppuBooleanType() ), 1265 ucb::CommandInfo 1266 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), 1267 -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ), 1268 ucb::CommandInfo 1269 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), 1270 -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ), 1271 1272 // Folder Only, omitted if not a folder 1273 ucb::CommandInfo 1274 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), 1275 -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ), 1276 ucb::CommandInfo 1277 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), 1278 -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) ) 1279 }; 1280 1281 const int nProps = sizeof (aCommandInfoTable) / sizeof (aCommandInfoTable[0]); 1282 return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder(xEnv) ? nProps : nProps - 2); 1283 } 1284 1285 XTYPEPROVIDER_COMMON_IMPL( Content ); 1286 1287 void SAL_CALL Content::acquire() throw() 1288 { 1289 ContentImplHelper::acquire(); 1290 } 1291 1292 void SAL_CALL Content::release() throw() 1293 { 1294 ContentImplHelper::release(); 1295 } 1296 1297 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) 1298 { 1299 uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) ); 1300 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType); 1301 } 1302 1303 rtl::OUString SAL_CALL Content::getImplementationName() 1304 { 1305 return rtl::OUString::createFromAscii("com.sun.star.comp.GIOContent" ); 1306 } 1307 1308 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() 1309 { 1310 uno::Sequence< rtl::OUString > aSNS( 1 ); 1311 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii("com.sun.star.ucb.GIOContent" ); 1312 return aSNS; 1313 } 1314 1315 } 1316