Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
12 : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : * it under the terms of the GNU Lesser General Public License version 3
14 : * only, as published by the Free Software Foundation.
15 : *
16 : * OpenOffice.org is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU Lesser General Public License version 3 for more details
20 : * (a copy is included in the LICENSE file that accompanied this code).
21 : *
22 : * You should have received a copy of the GNU Lesser General Public License
23 : * version 3 along with OpenOffice.org. If not, see
24 : * <http://www.openoffice.org/license.html>
25 : * for a copy of the LGPLv3 License.
26 : *
27 : ************************************************************************/
28 :
29 :
30 : /**************************************************************************
31 : TODO
32 : **************************************************************************
33 :
34 : *************************************************************************/
35 : #include <boost/ptr_container/ptr_vector.hpp>
36 : #include <boost/shared_ptr.hpp>
37 : #include <osl/diagnose.h>
38 : #include <com/sun/star/ucb/OpenMode.hpp>
39 : #include <ucbhelper/contentidentifier.hxx>
40 : #include <ucbhelper/providerhelper.hxx>
41 : #include "webdavdatasupplier.hxx"
42 : #include "webdavcontent.hxx"
43 : #include "ContentProperties.hxx"
44 : #include "DAVSession.hxx"
45 : #include "NeonUri.hxx"
46 :
47 : using namespace com::sun::star;
48 : using namespace webdav_ucp;
49 :
50 : namespace webdav_ucp
51 : {
52 :
53 :
54 :
55 : // struct ResultListEntry.
56 :
57 :
58 :
59 0 : struct ResultListEntry
60 : {
61 : OUString aId;
62 : uno::Reference< ucb::XContentIdentifier > xId;
63 : uno::Reference< ucb::XContent > xContent;
64 : uno::Reference< sdbc::XRow > xRow;
65 : boost::shared_ptr<ContentProperties> const pData;
66 :
67 0 : explicit ResultListEntry(boost::shared_ptr<ContentProperties> const& pEntry)
68 0 : : pData(pEntry)
69 0 : {}
70 : };
71 :
72 :
73 :
74 : // ResultList.
75 :
76 :
77 :
78 : typedef boost::ptr_vector<ResultListEntry> ResultList;
79 :
80 :
81 :
82 : // struct DataSupplier_Impl.
83 :
84 :
85 :
86 0 : struct DataSupplier_Impl
87 : {
88 : osl::Mutex m_aMutex;
89 : ResultList m_aResults;
90 : rtl::Reference< Content > m_xContent;
91 : uno::Reference< uno::XComponentContext > m_xContext;
92 : sal_Int32 m_nOpenMode;
93 : bool m_bCountFinal;
94 : bool m_bThrowException;
95 :
96 0 : DataSupplier_Impl(
97 : const uno::Reference< uno::XComponentContext >& rxContext,
98 : const rtl::Reference< Content >& rContent,
99 : sal_Int32 nOpenMode )
100 : : m_xContent( rContent ), m_xContext( rxContext ), m_nOpenMode( nOpenMode ),
101 0 : m_bCountFinal( false ), m_bThrowException( false ) {}
102 : };
103 :
104 : }
105 :
106 :
107 :
108 :
109 : // DataSupplier Implementation.
110 :
111 :
112 :
113 :
114 0 : DataSupplier::DataSupplier(
115 : const uno::Reference< uno::XComponentContext >& rxContext,
116 : const rtl::Reference< Content >& rContent,
117 : sal_Int32 nOpenMode )
118 0 : : m_pImpl( new DataSupplier_Impl( rxContext, rContent, nOpenMode ) )
119 : {
120 0 : }
121 :
122 :
123 : // virtual
124 0 : DataSupplier::~DataSupplier()
125 : {
126 0 : }
127 :
128 :
129 : // virtual
130 0 : OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
131 : {
132 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
133 :
134 0 : if ( nIndex < m_pImpl->m_aResults.size() )
135 : {
136 0 : OUString aId = m_pImpl->m_aResults[ nIndex ].aId;
137 0 : if ( !aId.isEmpty() )
138 : {
139 : // Already cached.
140 0 : return aId;
141 0 : }
142 : }
143 :
144 0 : if ( getResult( nIndex ) )
145 : {
146 0 : OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
147 :
148 : const ContentProperties& props
149 0 : = *( m_pImpl->m_aResults[ nIndex ].pData );
150 :
151 0 : if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
152 0 : aId += "/";
153 :
154 0 : aId += props.getEscapedTitle();
155 :
156 0 : if ( props.isTrailingSlash() )
157 0 : aId += "/";
158 :
159 0 : m_pImpl->m_aResults[ nIndex ].aId = aId;
160 0 : return aId;
161 : }
162 0 : return OUString();
163 : }
164 :
165 :
166 : // virtual
167 : uno::Reference< ucb::XContentIdentifier >
168 0 : DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
169 : {
170 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
171 :
172 0 : if ( nIndex < m_pImpl->m_aResults.size() )
173 : {
174 : uno::Reference< ucb::XContentIdentifier > xId
175 0 : = m_pImpl->m_aResults[ nIndex ].xId;
176 0 : if ( xId.is() )
177 : {
178 : // Already cached.
179 0 : return xId;
180 0 : }
181 : }
182 :
183 0 : OUString aId = queryContentIdentifierString( nIndex );
184 0 : if ( !aId.isEmpty() )
185 : {
186 : uno::Reference< ucb::XContentIdentifier > xId
187 0 : = new ::ucbhelper::ContentIdentifier( aId );
188 0 : m_pImpl->m_aResults[ nIndex ].xId = xId;
189 0 : return xId;
190 : }
191 0 : return uno::Reference< ucb::XContentIdentifier >();
192 : }
193 :
194 :
195 : // virtual
196 : uno::Reference< ucb::XContent >
197 0 : DataSupplier::queryContent( sal_uInt32 nIndex )
198 : {
199 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
200 :
201 0 : if ( nIndex < m_pImpl->m_aResults.size() )
202 : {
203 : uno::Reference< ucb::XContent > xContent
204 0 : = m_pImpl->m_aResults[ nIndex ].xContent;
205 0 : if ( xContent.is() )
206 : {
207 : // Already cached.
208 0 : return xContent;
209 0 : }
210 : }
211 :
212 : uno::Reference< ucb::XContentIdentifier > xId
213 0 : = queryContentIdentifier( nIndex );
214 0 : if ( xId.is() )
215 : {
216 : try
217 : {
218 : uno::Reference< ucb::XContent > xContent
219 0 : = m_pImpl->m_xContent->getProvider()->queryContent( xId );
220 0 : m_pImpl->m_aResults[ nIndex ].xContent = xContent;
221 0 : return xContent;
222 :
223 : }
224 0 : catch ( ucb::IllegalIdentifierException& )
225 : {
226 : }
227 : }
228 0 : return uno::Reference< ucb::XContent >();
229 : }
230 :
231 :
232 : // virtual
233 0 : bool DataSupplier::getResult( sal_uInt32 nIndex )
234 : {
235 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
236 :
237 0 : if ( m_pImpl->m_aResults.size() > nIndex )
238 : {
239 : // Result already present.
240 0 : return true;
241 : }
242 :
243 : // Obtain values...
244 0 : if ( getData() )
245 : {
246 0 : if ( m_pImpl->m_aResults.size() > nIndex )
247 : {
248 : // Result already present.
249 0 : return true;
250 : }
251 : }
252 :
253 0 : return false;
254 : }
255 :
256 :
257 : // virtual
258 0 : sal_uInt32 DataSupplier::totalCount()
259 : {
260 : // Obtain values...
261 0 : getData();
262 :
263 0 : return m_pImpl->m_aResults.size();
264 : }
265 :
266 :
267 : // virtual
268 0 : sal_uInt32 DataSupplier::currentCount()
269 : {
270 0 : return m_pImpl->m_aResults.size();
271 : }
272 :
273 :
274 : // virtual
275 0 : bool DataSupplier::isCountFinal()
276 : {
277 0 : return m_pImpl->m_bCountFinal;
278 : }
279 :
280 :
281 : // virtual
282 0 : uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
283 : sal_uInt32 nIndex )
284 : {
285 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
286 :
287 0 : if ( nIndex < m_pImpl->m_aResults.size() )
288 : {
289 0 : uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ].xRow;
290 0 : if ( xRow.is() )
291 : {
292 : // Already cached.
293 0 : return xRow;
294 0 : }
295 : }
296 :
297 0 : if ( getResult( nIndex ) )
298 : {
299 : uno::Reference< sdbc::XRow > xRow
300 : = Content::getPropertyValues(
301 0 : m_pImpl->m_xContext,
302 0 : getResultSet()->getProperties(),
303 0 : *(m_pImpl->m_aResults[ nIndex ].pData),
304 : rtl::Reference< ::ucbhelper::ContentProviderImplHelper >(
305 0 : m_pImpl->m_xContent->getProvider().get() ),
306 0 : queryContentIdentifierString( nIndex ) );
307 0 : m_pImpl->m_aResults[ nIndex ].xRow = xRow;
308 0 : return xRow;
309 : }
310 :
311 0 : return uno::Reference< sdbc::XRow >();
312 : }
313 :
314 :
315 : // virtual
316 0 : void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
317 : {
318 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
319 :
320 0 : if ( nIndex < m_pImpl->m_aResults.size() )
321 0 : m_pImpl->m_aResults[ nIndex ].xRow = uno::Reference< sdbc::XRow >();
322 0 : }
323 :
324 :
325 : // virtual
326 0 : void DataSupplier::close()
327 : {
328 0 : }
329 :
330 :
331 : // virtual
332 0 : void DataSupplier::validate()
333 : throw( ucb::ResultSetException )
334 : {
335 0 : if ( m_pImpl->m_bThrowException )
336 0 : throw ucb::ResultSetException();
337 0 : }
338 :
339 :
340 0 : bool DataSupplier::getData()
341 : {
342 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
343 :
344 0 : if ( !m_pImpl->m_bCountFinal )
345 : {
346 0 : std::vector< OUString > propertyNames;
347 : ContentProperties::UCBNamesToDAVNames(
348 0 : getResultSet()->getProperties(), propertyNames );
349 :
350 : // Append "resourcetype", if not already present. It's value is
351 : // needed to get a valid ContentProperties::pIsFolder value, which
352 : // is needed for OpenMode handling.
353 :
354 : std::vector< OUString >::const_iterator it
355 0 : = propertyNames.begin();
356 : std::vector< OUString >::const_iterator end
357 0 : = propertyNames.end();
358 :
359 0 : while ( it != end )
360 : {
361 0 : if ( (*it).equals( DAVProperties::RESOURCETYPE ) )
362 0 : break;
363 :
364 0 : ++it;
365 : }
366 :
367 0 : if ( it == end )
368 0 : propertyNames.push_back( DAVProperties::RESOURCETYPE );
369 :
370 0 : std::vector< DAVResource > resources;
371 : try
372 : {
373 : // propfind depth 1, get property values for parent AND for each
374 : // child
375 0 : m_pImpl->m_xContent->getResourceAccess()
376 : .PROPFIND( DAVONE,
377 : propertyNames,
378 : resources,
379 0 : getResultSet()->getEnvironment() );
380 : }
381 0 : catch ( DAVException & )
382 : {
383 : // OSL_FAIL( "PROPFIND : DAVException" );
384 0 : m_pImpl->m_bThrowException = true;
385 : }
386 :
387 0 : if ( !m_pImpl->m_bThrowException )
388 : {
389 : try
390 : {
391 : NeonUri aURI(
392 0 : m_pImpl->m_xContent->getResourceAccess().getURL() );
393 0 : OUString aPath = aURI.GetPath();
394 :
395 0 : if ( aPath.endsWith("/") )
396 0 : aPath = aPath.copy( 0, aPath.getLength() - 1 );
397 :
398 0 : aPath = NeonUri::unescape( aPath );
399 0 : bool bFoundParent = false;
400 :
401 0 : for ( size_t n = 0; n < resources.size(); ++n )
402 : {
403 0 : const DAVResource & rRes = resources[ n ];
404 :
405 : // Filter parent, which is contained somewhere(!) in
406 : // the vector.
407 0 : if ( !bFoundParent )
408 : {
409 : try
410 : {
411 0 : NeonUri aCurrURI( rRes.uri );
412 0 : OUString aCurrPath = aCurrURI.GetPath();
413 0 : if ( aCurrPath.endsWith("/") )
414 : aCurrPath
415 0 : = aCurrPath.copy(
416 : 0,
417 0 : aCurrPath.getLength() - 1 );
418 :
419 0 : aCurrPath = NeonUri::unescape( aCurrPath );
420 0 : if ( aPath == aCurrPath )
421 : {
422 0 : bFoundParent = true;
423 0 : continue;
424 0 : }
425 : }
426 0 : catch ( DAVException const & )
427 : {
428 : // do nothing, ignore error. continue.
429 : }
430 : }
431 :
432 : boost::shared_ptr<ContentProperties> const
433 0 : pContentProperties(new ContentProperties(rRes));
434 :
435 : // Check resource against open mode.
436 0 : switch ( m_pImpl->m_nOpenMode )
437 : {
438 : case ucb::OpenMode::FOLDERS:
439 : {
440 0 : bool bFolder = false;
441 :
442 : const uno::Any & rValue
443 : = pContentProperties->getValue(
444 0 : OUString( "IsFolder" ) );
445 0 : rValue >>= bFolder;
446 :
447 0 : if ( !bFolder )
448 0 : continue;
449 :
450 0 : break;
451 : }
452 :
453 : case ucb::OpenMode::DOCUMENTS:
454 : {
455 0 : bool bDocument = false;
456 :
457 : const uno::Any & rValue
458 : = pContentProperties->getValue(
459 0 : OUString( "IsDocument" ) );
460 0 : rValue >>= bDocument;
461 :
462 0 : if ( !bDocument )
463 0 : continue;
464 :
465 0 : break;
466 : }
467 :
468 : case ucb::OpenMode::ALL:
469 : default:
470 0 : break;
471 : }
472 :
473 0 : m_pImpl->m_aResults.push_back(
474 0 : new ResultListEntry( pContentProperties ) );
475 0 : }
476 : }
477 0 : catch ( DAVException const & )
478 : {
479 : }
480 : }
481 :
482 0 : m_pImpl->m_bCountFinal = true;
483 :
484 : // Callback possible, because listeners may be informed!
485 0 : aGuard.clear();
486 0 : getResultSet()->rowCountFinal();
487 : }
488 0 : return !m_pImpl->m_bThrowException;
489 : }
490 :
491 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|