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 * This file pinched from webdavdatasupplier (etc.) 28 * cut & paste + new getData impl. & collate ResultSet code. 29 */ 30 #include <vector> 31 #include <osl/diagnose.h> 32 #include <com/sun/star/ucb/OpenMode.hpp> 33 #include <ucbhelper/contentidentifier.hxx> 34 #include <ucbhelper/providerhelper.hxx> 35 36 #include "gvfs_directory.hxx" 37 38 #include <libgnomevfs/gnome-vfs-utils.h> 39 #include <libgnomevfs/gnome-vfs-directory.h> 40 41 using namespace com::sun::star; 42 using namespace gvfs; 43 44 // DynamicResultSet Implementation. 45 46 DynamicResultSet::DynamicResultSet( 47 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 48 const rtl::Reference< Content >& rxContent, 49 const ucb::OpenCommandArgument2& rCommand, 50 const uno::Reference< ucb::XCommandEnvironment >& rxEnv ) 51 : ResultSetImplHelper( rxSMgr, rCommand ), 52 m_xContent( rxContent ), 53 m_xEnv( rxEnv ) 54 { 55 } 56 void DynamicResultSet::initStatic() 57 { 58 m_xResultSet1 59 = new ::ucbhelper::ResultSet( m_xSMgr, 60 m_aCommand.Properties, 61 new DataSupplier( m_xSMgr, 62 m_xContent, 63 m_aCommand.Mode ), 64 m_xEnv ); 65 } 66 void DynamicResultSet::initDynamic() 67 { 68 initStatic(); 69 m_xResultSet2 = m_xResultSet1; 70 } 71 72 //========================================================================= 73 74 75 // DataSupplier Implementation. 76 77 78 79 struct ResultListEntry 80 { 81 rtl::OUString aId; 82 uno::Reference< ucb::XContentIdentifier > xId; 83 uno::Reference< ucb::XContent > xContent; 84 uno::Reference< sdbc::XRow > xRow; 85 GnomeVFSFileInfo aInfo; 86 87 ResultListEntry( const GnomeVFSFileInfo *fileInfo) 88 { 89 gnome_vfs_file_info_copy (&aInfo, fileInfo); 90 } 91 92 ~ResultListEntry() 93 { 94 gnome_vfs_file_info_clear (&aInfo); 95 } 96 }; 97 98 //========================================================================= 99 // 100 // ResultList. 101 // 102 //========================================================================= 103 104 typedef std::vector< ResultListEntry* > ResultList; 105 106 //========================================================================= 107 // 108 // struct DataSupplier_Impl. 109 // 110 //========================================================================= 111 112 struct gvfs::DataSupplier_Impl 113 { 114 osl::Mutex m_aMutex; 115 ResultList m_aResults; 116 rtl::Reference< Content > m_xContent; 117 uno::Reference< lang::XMultiServiceFactory > m_xSMgr; 118 sal_Int32 m_nOpenMode; 119 sal_Bool m_bCountFinal; 120 121 DataSupplier_Impl( 122 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 123 const rtl::Reference< Content >& rContent, 124 sal_Int32 nOpenMode ) 125 : m_xContent( rContent ), m_xSMgr( rxSMgr ), 126 m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} 127 ~DataSupplier_Impl() 128 { 129 ResultList::const_iterator it = m_aResults.begin(); 130 ResultList::const_iterator end = m_aResults.end(); 131 132 while ( it != end ) 133 { 134 delete (*it); 135 it++; 136 } 137 } 138 }; 139 140 DataSupplier::DataSupplier( 141 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 142 const rtl::Reference< Content >& rContent, 143 sal_Int32 nOpenMode ) 144 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) 145 { 146 } 147 148 //========================================================================= 149 // virtual 150 DataSupplier::~DataSupplier() 151 { 152 delete m_pImpl; 153 } 154 155 // virtual 156 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) 157 { 158 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 159 160 if ( nIndex < m_pImpl->m_aResults.size() ) { 161 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; 162 if ( aId.getLength() ) // cached 163 return aId; 164 } 165 166 if ( getResult( nIndex ) ) { 167 rtl::OUString aId = m_pImpl->m_xContent->getOUURI(); 168 169 char *escaped_name; 170 escaped_name = gnome_vfs_escape_string( m_pImpl->m_aResults[ nIndex ]->aInfo.name ); 171 172 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) 173 aId += rtl::OUString::createFromAscii( "/" ); 174 175 aId += rtl::OUString::createFromAscii( escaped_name ); 176 177 g_free( escaped_name ); 178 179 m_pImpl->m_aResults[ nIndex ]->aId = aId; 180 return aId; 181 } 182 183 return rtl::OUString(); 184 } 185 186 // virtual 187 uno::Reference< ucb::XContentIdentifier > 188 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) 189 { 190 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 191 192 if ( nIndex < m_pImpl->m_aResults.size() ) { 193 uno::Reference< ucb::XContentIdentifier > xId 194 = m_pImpl->m_aResults[ nIndex ]->xId; 195 if ( xId.is() ) // Already cached. 196 return xId; 197 } 198 199 rtl::OUString aId = queryContentIdentifierString( nIndex ); 200 if ( aId.getLength() ) { 201 uno::Reference< ucb::XContentIdentifier > xId 202 = new ::ucbhelper::ContentIdentifier( aId ); 203 m_pImpl->m_aResults[ nIndex ]->xId = xId; 204 return xId; 205 } 206 207 return uno::Reference< ucb::XContentIdentifier >(); 208 } 209 210 // virtual 211 uno::Reference< ucb::XContent > 212 DataSupplier::queryContent( sal_uInt32 nIndex ) 213 { 214 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 215 216 if ( nIndex < m_pImpl->m_aResults.size() ) { 217 uno::Reference< ucb::XContent > xContent 218 = m_pImpl->m_aResults[ nIndex ]->xContent; 219 if ( xContent.is() ) // Already cached. 220 return xContent; 221 } 222 223 uno::Reference< ucb::XContentIdentifier > xId 224 = queryContentIdentifier( nIndex ); 225 if ( xId.is() ) { 226 try 227 { 228 // FIXME: 229 // It would be really nice to propagate this information 230 // to the Content, but we can't then register it with the 231 // ContentProvider, and the ucbhelper hinders here. 232 uno::Reference< ucb::XContent > xContent 233 = m_pImpl->m_xContent->getProvider()->queryContent( xId ); 234 m_pImpl->m_aResults[ nIndex ]->xContent = xContent; 235 return xContent; 236 237 } 238 catch ( ucb::IllegalIdentifierException& ) { 239 } 240 } 241 return uno::Reference< ucb::XContent >(); 242 } 243 244 // virtual 245 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) 246 { 247 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 248 249 if ( m_pImpl->m_aResults.size() > nIndex ) // Result already present. 250 return sal_True; 251 252 if ( getData() && m_pImpl->m_aResults.size() > nIndex ) 253 return sal_True; 254 255 return sal_False; 256 } 257 258 // virtual 259 sal_uInt32 DataSupplier::totalCount() 260 { 261 getData(); 262 263 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 264 265 return m_pImpl->m_aResults.size(); 266 } 267 268 // virtual 269 sal_uInt32 DataSupplier::currentCount() 270 { 271 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 272 return m_pImpl->m_aResults.size(); 273 } 274 275 // virtual 276 sal_Bool DataSupplier::isCountFinal() 277 { 278 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 279 return m_pImpl->m_bCountFinal; 280 } 281 282 // virtual 283 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex ) 284 { 285 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 286 287 if ( nIndex < m_pImpl->m_aResults.size() ) { 288 uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; 289 if ( xRow.is() ) // Already cached. 290 return xRow; 291 } 292 293 if ( getResult( nIndex ) ) { 294 // Inefficient - but we can't create xContent's sensibly 295 // nor can we do the property code sensibly cleanly staticaly. 296 Content *pContent = static_cast< ::gvfs::Content * >(queryContent( nIndex ).get()); 297 298 uno::Reference< sdbc::XRow > xRow = 299 pContent->getPropertyValues( getResultSet()->getProperties(), 300 getResultSet()->getEnvironment() ); 301 302 m_pImpl->m_aResults[ nIndex ]->xRow = xRow; 303 304 return xRow; 305 } 306 307 return uno::Reference< sdbc::XRow >(); 308 } 309 310 // virtual 311 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) 312 { 313 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 314 315 if ( nIndex < m_pImpl->m_aResults.size() ) 316 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); 317 } 318 319 // virtual 320 void DataSupplier::close() 321 { 322 } 323 324 // virtual 325 void DataSupplier::validate() 326 throw( ucb::ResultSetException ) 327 { 328 } 329 330 sal_Bool DataSupplier::getData() 331 { 332 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 333 334 if ( !m_pImpl->m_bCountFinal ) { 335 GnomeVFSResult result; 336 GnomeVFSDirectoryHandle *dirHandle = NULL; 337 338 { 339 Authentication aAuth( getResultSet()->getEnvironment() ); 340 char *uri = m_pImpl->m_xContent->getURI(); 341 result = gnome_vfs_directory_open 342 ( &dirHandle, uri, GNOME_VFS_FILE_INFO_DEFAULT ); 343 344 if (result != GNOME_VFS_OK) { 345 #ifdef DEBUG 346 g_warning ("Failed open of '%s' with '%s'", 347 uri, gnome_vfs_result_to_string( result )); 348 #endif 349 g_free( uri ); 350 return sal_False; 351 } 352 353 g_free( uri ); 354 } 355 356 GnomeVFSFileInfo* fileInfo = gnome_vfs_file_info_new (); 357 358 while ((result = gnome_vfs_directory_read_next (dirHandle, fileInfo)) == GNOME_VFS_OK) { 359 if( fileInfo->name && fileInfo->name[0] == '.' && 360 ( fileInfo->name[1] == '\0' || 361 ( fileInfo->name[1] == '.' && fileInfo->name[2] == '\0' ) ) ) 362 continue; 363 364 switch ( m_pImpl->m_nOpenMode ) { 365 case ucb::OpenMode::FOLDERS: 366 if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) || 367 fileInfo->type != GNOME_VFS_FILE_TYPE_DIRECTORY ) 368 continue; 369 break; 370 371 case ucb::OpenMode::DOCUMENTS: 372 if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) || 373 fileInfo->type != GNOME_VFS_FILE_TYPE_REGULAR ) 374 continue; 375 break; 376 377 case ucb::OpenMode::ALL: 378 default: 379 break; 380 } 381 382 m_pImpl->m_aResults.push_back( new ResultListEntry( fileInfo ) ); 383 } 384 385 gnome_vfs_file_info_unref (fileInfo); 386 387 #ifdef DEBUG 388 g_warning ("Got %d directory entries", result); 389 #endif 390 391 m_pImpl->m_bCountFinal = sal_True; 392 393 // Callback possible, because listeners may be informed! 394 aGuard.clear(); 395 getResultSet()->rowCountFinal(); 396 397 if (result != GNOME_VFS_ERROR_EOF) { 398 #ifdef DEBUG 399 g_warning( "Failed read_next '%s'", 400 gnome_vfs_result_to_string( result ) ); 401 #endif 402 return sal_False; 403 } 404 405 result = gnome_vfs_directory_close (dirHandle); 406 if (result != GNOME_VFS_OK) { 407 #ifdef DEBUG 408 g_warning( "Failed close '%s'", 409 gnome_vfs_result_to_string( result ) ); 410 #endif 411 return sal_False; 412 } 413 } 414 415 return sal_True; 416 } 417 418 419 420