xref: /trunk/main/ucb/source/ucp/webdav/webdavdatasupplier.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 /**************************************************************************
32                                 TODO
33  **************************************************************************
34 
35  *************************************************************************/
36 #include <osl/diagnose.h>
37 #include <com/sun/star/ucb/OpenMode.hpp>
38 #include <ucbhelper/contentidentifier.hxx>
39 #include <ucbhelper/providerhelper.hxx>
40 #include "webdavdatasupplier.hxx"
41 #include "webdavcontent.hxx"
42 #include "ContentProperties.hxx"
43 #ifndef _WEBDAV_SESSION_HXX
44 #include "DAVSession.hxx"
45 #endif
46 #include "NeonUri.hxx"
47 
48 using namespace com::sun::star;
49 using namespace webdav_ucp;
50 
51 namespace webdav_ucp
52 {
53 
54 //=========================================================================
55 //
56 // struct ResultListEntry.
57 //
58 //=========================================================================
59 
60 struct ResultListEntry
61 {
62     rtl::OUString                             aId;
63     uno::Reference< ucb::XContentIdentifier > xId;
64     uno::Reference< ucb::XContent >           xContent;
65     uno::Reference< sdbc::XRow >              xRow;
66     const ContentProperties*                  pData;
67 
68     ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {};
69     ~ResultListEntry() { delete pData; }
70 };
71 
72 //=========================================================================
73 //
74 // ResultList.
75 //
76 //=========================================================================
77 
78 typedef std::vector< ResultListEntry* > ResultList;
79 
80 //=========================================================================
81 //
82 // struct DataSupplier_Impl.
83 //
84 //=========================================================================
85 
86 struct DataSupplier_Impl
87 {
88     osl::Mutex                                   m_aMutex;
89     ResultList                                   m_aResults;
90     rtl::Reference< Content >                    m_xContent;
91     uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
92     sal_Int32                                    m_nOpenMode;
93     sal_Bool                                     m_bCountFinal;
94     sal_Bool                                     m_bThrowException;
95 
96     DataSupplier_Impl(
97                 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
98                 const rtl::Reference< Content >& rContent,
99                 sal_Int32 nOpenMode )
100     : m_xContent( rContent ), m_xSMgr( rxSMgr ), m_nOpenMode( nOpenMode ),
101       m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {}
102     ~DataSupplier_Impl();
103 };
104 
105 //=========================================================================
106 DataSupplier_Impl::~DataSupplier_Impl()
107 {
108     ResultList::const_iterator it  = m_aResults.begin();
109     ResultList::const_iterator end = m_aResults.end();
110 
111     while ( it != end )
112     {
113         delete (*it);
114         it++;
115     }
116 }
117 
118 }
119 
120 //=========================================================================
121 //=========================================================================
122 //
123 // DataSupplier Implementation.
124 //
125 //=========================================================================
126 //=========================================================================
127 
128 DataSupplier::DataSupplier(
129             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
130             const rtl::Reference< Content >& rContent,
131             sal_Int32 nOpenMode )
132 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
133 {
134 }
135 
136 //=========================================================================
137 // virtual
138 DataSupplier::~DataSupplier()
139 {
140     delete m_pImpl;
141 }
142 
143 //=========================================================================
144 // virtual
145 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
146 {
147     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
148 
149     if ( nIndex < m_pImpl->m_aResults.size() )
150     {
151         rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
152         if ( aId.getLength() )
153         {
154             // Already cached.
155             return aId;
156         }
157     }
158 
159     if ( getResult( nIndex ) )
160     {
161         rtl::OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
162 
163         const ContentProperties& props
164                             = *( m_pImpl->m_aResults[ nIndex ]->pData );
165 
166         if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
167             aId += rtl::OUString::createFromAscii( "/" );
168 
169         aId += props.getEscapedTitle();
170 
171         if ( props.isTrailingSlash() )
172             aId += rtl::OUString::createFromAscii( "/" );
173 
174         m_pImpl->m_aResults[ nIndex ]->aId = aId;
175         return aId;
176     }
177     return rtl::OUString();
178 }
179 
180 //=========================================================================
181 // virtual
182 uno::Reference< ucb::XContentIdentifier >
183 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
184 {
185     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
186 
187     if ( nIndex < m_pImpl->m_aResults.size() )
188     {
189         uno::Reference< ucb::XContentIdentifier > xId
190             = m_pImpl->m_aResults[ nIndex ]->xId;
191         if ( xId.is() )
192         {
193             // Already cached.
194             return xId;
195         }
196     }
197 
198     rtl::OUString aId = queryContentIdentifierString( nIndex );
199     if ( aId.getLength() )
200     {
201         uno::Reference< ucb::XContentIdentifier > xId
202             = new ::ucbhelper::ContentIdentifier( aId );
203         m_pImpl->m_aResults[ nIndex ]->xId = xId;
204         return xId;
205     }
206     return uno::Reference< ucb::XContentIdentifier >();
207 }
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     {
218         uno::Reference< ucb::XContent > xContent
219             = m_pImpl->m_aResults[ nIndex ]->xContent;
220         if ( xContent.is() )
221         {
222             // Already cached.
223             return xContent;
224         }
225     }
226 
227     uno::Reference< ucb::XContentIdentifier > xId
228         = queryContentIdentifier( nIndex );
229     if ( xId.is() )
230     {
231         try
232         {
233             uno::Reference< ucb::XContent > xContent
234                 = m_pImpl->m_xContent->getProvider()->queryContent( xId );
235             m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
236             return xContent;
237 
238         }
239         catch ( ucb::IllegalIdentifierException& )
240         {
241         }
242     }
243     return uno::Reference< ucb::XContent >();
244 }
245 
246 //=========================================================================
247 // virtual
248 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
249 {
250     osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
251 
252     if ( m_pImpl->m_aResults.size() > nIndex )
253     {
254         // Result already present.
255         return sal_True;
256     }
257 
258     // Obtain values...
259     if ( getData() )
260     {
261         if ( m_pImpl->m_aResults.size() > nIndex )
262         {
263             // Result already present.
264             return sal_True;
265         }
266     }
267 
268     return sal_False;
269 }
270 
271 //=========================================================================
272 // virtual
273 sal_uInt32 DataSupplier::totalCount()
274 {
275   // Obtain values...
276   getData();
277 
278   return m_pImpl->m_aResults.size();
279 }
280 
281 //=========================================================================
282 // virtual
283 sal_uInt32 DataSupplier::currentCount()
284 {
285     return m_pImpl->m_aResults.size();
286 }
287 
288 //=========================================================================
289 // virtual
290 sal_Bool DataSupplier::isCountFinal()
291 {
292     return m_pImpl->m_bCountFinal;
293 }
294 
295 //=========================================================================
296 // virtual
297 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
298                                                     sal_uInt32 nIndex  )
299 {
300     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
301 
302     if ( nIndex < m_pImpl->m_aResults.size() )
303     {
304         uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
305         if ( xRow.is() )
306         {
307             // Already cached.
308             return xRow;
309         }
310     }
311 
312     if ( getResult( nIndex ) )
313     {
314         uno::Reference< sdbc::XRow > xRow
315             = Content::getPropertyValues(
316                 m_pImpl->m_xSMgr,
317                 getResultSet()->getProperties(),
318                 *(m_pImpl->m_aResults[ nIndex ]->pData),
319                 rtl::Reference< ::ucbhelper::ContentProviderImplHelper >(
320                     m_pImpl->m_xContent->getProvider().get() ),
321                 queryContentIdentifierString( nIndex ) );
322         m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
323         return xRow;
324     }
325 
326     return uno::Reference< sdbc::XRow >();
327 }
328 
329 //=========================================================================
330 // virtual
331 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
332 {
333     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
334 
335     if ( nIndex < m_pImpl->m_aResults.size() )
336         m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
337 }
338 
339 //=========================================================================
340 // virtual
341 void DataSupplier::close()
342 {
343 }
344 
345 //=========================================================================
346 // virtual
347 void DataSupplier::validate()
348     throw( ucb::ResultSetException )
349 {
350     if ( m_pImpl->m_bThrowException )
351         throw ucb::ResultSetException();
352 }
353 
354 //=========================================================================
355 sal_Bool DataSupplier::getData()
356 {
357     osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
358 
359     if ( !m_pImpl->m_bCountFinal )
360     {
361         std::vector< rtl::OUString > propertyNames;
362         ContentProperties::UCBNamesToDAVNames(
363                         getResultSet()->getProperties(), propertyNames );
364 
365         // Append "resourcetype", if not already present. It's value is
366         // needed to get a valid ContentProperties::pIsFolder value, which
367         // is needed for OpenMode handling.
368 
369         std::vector< rtl::OUString >::const_iterator it
370             = propertyNames.begin();
371         std::vector< rtl::OUString >::const_iterator end
372             = propertyNames.end();
373 
374         while ( it != end )
375         {
376             if ( (*it).equals( DAVProperties::RESOURCETYPE ) )
377                 break;
378 
379             it++;
380         }
381 
382         if ( it == end )
383             propertyNames.push_back( DAVProperties::RESOURCETYPE );
384 
385         std::vector< DAVResource > resources;
386         try
387         {
388             // propfind depth 1, get property values for parent AND for each
389             // child
390             m_pImpl->m_xContent->getResourceAccess()
391                 .PROPFIND( DAVONE,
392                            propertyNames,
393                            resources,
394                            getResultSet()->getEnvironment() );
395         }
396         catch ( DAVException & )
397         {
398 //          OSL_ENSURE( sal_False, "PROPFIND : DAVException" );
399             m_pImpl->m_bThrowException = sal_True;
400         }
401 
402         if ( !m_pImpl->m_bThrowException )
403         {
404             try
405             {
406                 NeonUri aURI(
407                     m_pImpl->m_xContent->getResourceAccess().getURL() );
408                 rtl::OUString aPath = aURI.GetPath();
409 
410                 if ( aPath.getStr()[ aPath.getLength() - 1 ]
411                      == sal_Unicode( '/' ) )
412                     aPath = aPath.copy( 0, aPath.getLength() - 1 );
413 
414                 aPath = NeonUri::unescape( aPath );
415                 bool bFoundParent = false;
416 
417                 for ( sal_uInt32 n = 0; n < resources.size(); ++n )
418                 {
419                     const DAVResource & rRes = resources[ n ];
420 
421                     // Filter parent, which is contained somewhere(!) in
422                     // the vector.
423                     if ( !bFoundParent )
424                     {
425                         try
426                         {
427                             NeonUri aCurrURI( rRes.uri );
428                             rtl::OUString aCurrPath = aCurrURI.GetPath();
429                             if ( aCurrPath.getStr()[
430                                      aCurrPath.getLength() - 1 ]
431                                  == sal_Unicode( '/' ) )
432                                 aCurrPath
433                                     = aCurrPath.copy(
434                                         0,
435                                         aCurrPath.getLength() - 1 );
436 
437                             aCurrPath = NeonUri::unescape( aCurrPath );
438                             if ( aPath == aCurrPath )
439                             {
440                                 bFoundParent = true;
441                                 continue;
442                             }
443                         }
444                         catch ( DAVException const & )
445                         {
446                             // do nothing, ignore error. continue.
447                         }
448                     }
449 
450                     ContentProperties* pContentProperties
451                         = new ContentProperties( rRes );
452 
453                     // Check resource against open mode.
454                     switch ( m_pImpl->m_nOpenMode )
455                     {
456                     case ucb::OpenMode::FOLDERS:
457                         {
458                             sal_Bool bFolder = sal_False;
459 
460                             const uno::Any & rValue
461                                 = pContentProperties->getValue(
462                                     rtl::OUString(
463                                         RTL_CONSTASCII_USTRINGPARAM(
464                                             "IsFolder" ) ) );
465                             rValue >>= bFolder;
466 
467                             if ( !bFolder )
468                                 continue;
469 
470                             break;
471                         }
472 
473                     case ucb::OpenMode::DOCUMENTS:
474                         {
475                             sal_Bool bDocument = sal_False;
476 
477                             const uno::Any & rValue
478                                 = pContentProperties->getValue(
479                                     rtl::OUString(
480                                         RTL_CONSTASCII_USTRINGPARAM(
481                                             "IsDocument" ) ) );
482                             rValue >>= bDocument;
483 
484                             if ( !bDocument )
485                                 continue;
486 
487                             break;
488                         }
489 
490                     case ucb::OpenMode::ALL:
491                     default:
492                         break;
493                     }
494 
495                     m_pImpl->m_aResults.push_back(
496                         new ResultListEntry( pContentProperties ) );
497                 }
498             }
499             catch ( DAVException const & )
500             {
501             }
502         }
503 
504         m_pImpl->m_bCountFinal = sal_True;
505 
506         // Callback possible, because listeners may be informed!
507         aGuard.clear();
508         getResultSet()->rowCountFinal();
509     }
510     return !m_pImpl->m_bThrowException;
511 }
512 
513