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 :
36 : #include <comphelper/processfactory.hxx>
37 : #include <osl/diagnose.h>
38 : #include "osl/doublecheckedlocking.h"
39 : #include <rtl/uri.hxx>
40 : #include <rtl/ustrbuf.hxx>
41 : #include <ucbhelper/contentidentifier.hxx>
42 : #include <ucbhelper/propertyvalueset.hxx>
43 : #include <ucbhelper/simpleinteractionrequest.hxx>
44 : #include <ucbhelper/cancelcommandexecution.hxx>
45 :
46 : #include <com/sun/star/beans/PropertyAttribute.hpp>
47 : #include <com/sun/star/beans/PropertySetInfoChange.hpp>
48 : #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
49 : #include <com/sun/star/beans/PropertyValue.hpp>
50 : #include <com/sun/star/io/XActiveDataSink.hpp>
51 : #include <com/sun/star/io/XOutputStream.hpp>
52 : #include <com/sun/star/lang/IllegalAccessException.hpp>
53 : #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
54 : #include <com/sun/star/ucb/CommandEnvironment.hpp>
55 : #include <com/sun/star/ucb/CommandFailedException.hpp>
56 : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
57 : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
58 : #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
59 : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
60 : #include "com/sun/star/ucb/InteractiveLockingLockedException.hpp"
61 : #include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp"
62 : #include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp"
63 : #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
64 : #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
65 : #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
66 : #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
67 : #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
68 : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
69 : #include <com/sun/star/ucb/MissingPropertiesException.hpp>
70 : #include <com/sun/star/ucb/NameClash.hpp>
71 : #include <com/sun/star/ucb/NameClashException.hpp>
72 : #include <com/sun/star/ucb/OpenCommandArgument3.hpp>
73 : #include <com/sun/star/ucb/OpenMode.hpp>
74 : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
75 : #include <com/sun/star/ucb/PropertyCommandArgument.hpp>
76 : #include <com/sun/star/ucb/TransferInfo.hpp>
77 : #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
78 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
79 : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
80 : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
81 : #include <com/sun/star/ucb/XCommandInfo.hpp>
82 : #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
83 : #include <com/sun/star/uno/XComponentContext.hpp>
84 :
85 : #include "webdavcontent.hxx"
86 : #include "webdavprovider.hxx"
87 : #include "webdavresultset.hxx"
88 : #include "ContentProperties.hxx"
89 : #include "NeonUri.hxx"
90 : #include "UCBDeadPropertyValue.hxx"
91 :
92 : using namespace com::sun::star;
93 : using namespace webdav_ucp;
94 :
95 :
96 :
97 :
98 : // Content Implementation.
99 :
100 :
101 :
102 :
103 :
104 : // ctr for content on an existing webdav resource
105 2 : Content::Content(
106 : const uno::Reference< uno::XComponentContext >& rxContext,
107 : ContentProvider* pProvider,
108 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
109 : rtl::Reference< DAVSessionFactory > const & rSessionFactory )
110 : throw ( ucb::ContentCreationException )
111 : : ContentImplHelper( rxContext, pProvider, Identifier ),
112 : m_eResourceType( UNKNOWN ),
113 : m_pProvider( pProvider ),
114 : m_bTransient( false ),
115 : m_bLocked( false ),
116 : m_bCollection( false ),
117 2 : m_bDidGetOrHead( false )
118 : {
119 : try
120 : {
121 : m_xResAccess.reset( new DAVResourceAccess(
122 : rxContext,
123 : rSessionFactory,
124 2 : Identifier->getContentIdentifier() ) );
125 :
126 2 : NeonUri aURI( Identifier->getContentIdentifier() );
127 2 : m_aEscapedTitle = aURI.GetPathBaseName();
128 : }
129 0 : catch ( DAVException const & )
130 : {
131 0 : throw ucb::ContentCreationException();
132 : }
133 2 : }
134 :
135 :
136 : // ctr for content on an non-existing webdav resource
137 0 : Content::Content(
138 : const uno::Reference< uno::XComponentContext >& rxContext,
139 : ContentProvider* pProvider,
140 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
141 : rtl::Reference< DAVSessionFactory > const & rSessionFactory,
142 : bool isCollection )
143 : throw ( ucb::ContentCreationException )
144 : : ContentImplHelper( rxContext, pProvider, Identifier ),
145 : m_eResourceType( UNKNOWN ),
146 : m_pProvider( pProvider ),
147 : m_bTransient( true ),
148 : m_bLocked( false ),
149 : m_bCollection( isCollection ),
150 0 : m_bDidGetOrHead( false )
151 : {
152 : try
153 : {
154 : m_xResAccess.reset( new DAVResourceAccess(
155 0 : rxContext, rSessionFactory, Identifier->getContentIdentifier() ) );
156 : }
157 0 : catch ( DAVException const & )
158 : {
159 0 : throw ucb::ContentCreationException();
160 : }
161 :
162 : // Do not set m_aEscapedTitle here! Content::insert relays on this!!!
163 0 : }
164 :
165 :
166 : // virtual
167 6 : Content::~Content()
168 : {
169 2 : if (m_bLocked)
170 0 : unlock(uno::Reference< ucb::XCommandEnvironment >());
171 4 : }
172 :
173 :
174 :
175 : // XInterface methods.
176 :
177 :
178 :
179 : // virtual
180 30 : void SAL_CALL Content::acquire()
181 : throw( )
182 : {
183 30 : ContentImplHelper::acquire();
184 30 : }
185 :
186 :
187 : // virtual
188 30 : void SAL_CALL Content::release()
189 : throw( )
190 : {
191 30 : ContentImplHelper::release();
192 30 : }
193 :
194 :
195 : // virtual
196 8 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
197 : throw ( uno::RuntimeException, std::exception )
198 : {
199 : // Note: isFolder may require network activities! So call it only
200 : // if it is really necessary!!!
201 : uno::Any aRet = cppu::queryInterface(
202 : rType,
203 8 : static_cast< ucb::XContentCreator * >( this ) );
204 8 : if ( aRet.hasValue() )
205 : {
206 : try
207 : {
208 : uno::Reference< task::XInteractionHandler > xIH(
209 0 : task::PasswordContainerInteractionHandler::create( m_xContext ) );
210 :
211 : // Supply a command env to isFolder() that contains an interaction
212 : // handler that uses the password container service to obtain
213 : // credentials without displaying a password gui.
214 :
215 : uno::Reference< ucb::XCommandEnvironment > xCmdEnv(
216 : ucb::CommandEnvironment::create(
217 : m_xContext,
218 : xIH,
219 0 : uno::Reference< ucb::XProgressHandler >() ) );
220 :
221 0 : return isFolder( xCmdEnv ) ? aRet : uno::Any();
222 : }
223 0 : catch ( uno::RuntimeException const & )
224 : {
225 0 : throw;
226 : }
227 0 : catch ( uno::Exception const & )
228 : {
229 0 : return uno::Any();
230 : }
231 : }
232 8 : return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
233 : }
234 :
235 :
236 :
237 : // XTypeProvider methods.
238 :
239 :
240 :
241 0 : XTYPEPROVIDER_COMMON_IMPL( Content );
242 :
243 :
244 : // virtual
245 0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
246 : throw( uno::RuntimeException, std::exception )
247 : {
248 0 : bool bFolder = false;
249 : try
250 : {
251 : bFolder
252 0 : = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
253 : }
254 0 : catch ( uno::RuntimeException const & )
255 : {
256 0 : throw;
257 : }
258 0 : catch ( uno::Exception const & )
259 : {
260 : }
261 :
262 0 : cppu::OTypeCollection * pCollection = 0;
263 :
264 0 : if ( bFolder )
265 : {
266 : static cppu::OTypeCollection* pFolderTypes = 0;
267 :
268 0 : pCollection = pFolderTypes;
269 0 : if ( !pCollection )
270 : {
271 0 : osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
272 :
273 0 : pCollection = pFolderTypes;
274 0 : if ( !pCollection )
275 : {
276 : static cppu::OTypeCollection aCollection(
277 0 : CPPU_TYPE_REF( lang::XTypeProvider ),
278 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
279 0 : CPPU_TYPE_REF( lang::XComponent ),
280 0 : CPPU_TYPE_REF( ucb::XContent ),
281 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
282 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
283 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
284 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
285 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
286 0 : CPPU_TYPE_REF( container::XChild ),
287 0 : CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
288 0 : pCollection = &aCollection;
289 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
290 0 : pFolderTypes = pCollection;
291 0 : }
292 : }
293 : else {
294 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
295 : }
296 : }
297 : else
298 : {
299 : static cppu::OTypeCollection* pDocumentTypes = 0;
300 :
301 0 : pCollection = pDocumentTypes;
302 0 : if ( !pCollection )
303 : {
304 0 : osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
305 :
306 0 : pCollection = pDocumentTypes;
307 0 : if ( !pCollection )
308 : {
309 : static cppu::OTypeCollection aCollection(
310 0 : CPPU_TYPE_REF( lang::XTypeProvider ),
311 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
312 0 : CPPU_TYPE_REF( lang::XComponent ),
313 0 : CPPU_TYPE_REF( ucb::XContent ),
314 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
315 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
316 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
317 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
318 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
319 0 : CPPU_TYPE_REF( container::XChild ) );
320 0 : pCollection = &aCollection;
321 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
322 0 : pDocumentTypes = pCollection;
323 0 : }
324 : }
325 : else {
326 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
327 : }
328 : }
329 :
330 0 : return (*pCollection).getTypes();
331 : }
332 :
333 :
334 :
335 : // XServiceInfo methods.
336 :
337 :
338 :
339 : // virtual
340 0 : OUString SAL_CALL Content::getImplementationName()
341 : throw( uno::RuntimeException, std::exception )
342 : {
343 0 : return OUString( "com.sun.star.comp.ucb.WebDAVContent" );
344 : }
345 :
346 :
347 : // virtual
348 0 : uno::Sequence< OUString > SAL_CALL Content::getSupportedServiceNames()
349 : throw( uno::RuntimeException, std::exception )
350 : {
351 0 : uno::Sequence< OUString > aSNS( 1 );
352 0 : aSNS[ 0 ] = WEBDAV_CONTENT_SERVICE_NAME;
353 0 : return aSNS;
354 : }
355 :
356 :
357 :
358 : // XContent methods.
359 :
360 :
361 :
362 : // virtual
363 0 : OUString SAL_CALL Content::getContentType()
364 : throw( uno::RuntimeException, std::exception )
365 : {
366 0 : bool bFolder = false;
367 : try
368 : {
369 : bFolder
370 0 : = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
371 : }
372 0 : catch ( uno::RuntimeException const & )
373 : {
374 0 : throw;
375 : }
376 0 : catch ( uno::Exception const & )
377 : {
378 : }
379 :
380 0 : if ( bFolder )
381 0 : return OUString( WEBDAV_COLLECTION_TYPE );
382 :
383 0 : return OUString( WEBDAV_CONTENT_TYPE );
384 : }
385 :
386 :
387 :
388 : // XCommandProcessor methods.
389 :
390 :
391 :
392 : // virtual
393 0 : uno::Any SAL_CALL Content::execute(
394 : const ucb::Command& aCommand,
395 : sal_Int32 /*CommandId*/,
396 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
397 : throw( uno::Exception,
398 : ucb::CommandAbortedException,
399 : uno::RuntimeException, std::exception )
400 : {
401 : SAL_INFO( "ucb.ucp.webdav", "Content::execute: start: command: " <<
402 : aCommand.Name << ", env: " <<
403 : (Environment.is() ? "present" : "missing") );
404 :
405 0 : uno::Any aRet;
406 :
407 0 : if ( aCommand.Name == "getPropertyValues" )
408 : {
409 :
410 : // getPropertyValues
411 :
412 :
413 0 : uno::Sequence< beans::Property > Properties;
414 0 : if ( !( aCommand.Argument >>= Properties ) )
415 : {
416 : ucbhelper::cancelCommandExecution(
417 : uno::makeAny( lang::IllegalArgumentException(
418 : OUString( "Wrong argument type!" ),
419 : static_cast< cppu::OWeakObject * >( this ),
420 : -1 ) ),
421 0 : Environment );
422 : // Unreachable
423 : }
424 :
425 0 : aRet <<= getPropertyValues( Properties, Environment );
426 : }
427 0 : else if ( aCommand.Name == "setPropertyValues" )
428 : {
429 :
430 : // setPropertyValues
431 :
432 :
433 0 : uno::Sequence< beans::PropertyValue > aProperties;
434 0 : if ( !( aCommand.Argument >>= aProperties ) )
435 : {
436 : ucbhelper::cancelCommandExecution(
437 : uno::makeAny( lang::IllegalArgumentException(
438 : OUString( "Wrong argument type!" ),
439 : static_cast< cppu::OWeakObject * >( this ),
440 : -1 ) ),
441 0 : Environment );
442 : // Unreachable
443 : }
444 :
445 0 : if ( !aProperties.getLength() )
446 : {
447 : ucbhelper::cancelCommandExecution(
448 : uno::makeAny( lang::IllegalArgumentException(
449 : OUString( "No properties!" ),
450 : static_cast< cppu::OWeakObject * >( this ),
451 : -1 ) ),
452 0 : Environment );
453 : // Unreachable
454 : }
455 :
456 0 : aRet <<= setPropertyValues( aProperties, Environment );
457 : }
458 0 : else if ( aCommand.Name == "getPropertySetInfo" )
459 : {
460 :
461 : // getPropertySetInfo
462 :
463 :
464 : // Note: Implemented by base class.
465 0 : aRet <<= getPropertySetInfo( Environment,
466 0 : false /* don't cache data */ );
467 : }
468 0 : else if ( aCommand.Name == "getCommandInfo" )
469 : {
470 :
471 : // getCommandInfo
472 :
473 :
474 : // Note: Implemented by base class.
475 0 : aRet <<= getCommandInfo( Environment, false );
476 : }
477 0 : else if ( aCommand.Name == "open" )
478 : {
479 :
480 : // open
481 :
482 :
483 0 : ucb::OpenCommandArgument3 aOpenCommand;
484 0 : ucb::OpenCommandArgument2 aTmp;
485 0 : if ( !( aCommand.Argument >>= aTmp ) )
486 : {
487 : ucbhelper::cancelCommandExecution(
488 : uno::makeAny( lang::IllegalArgumentException(
489 : OUString( "Wrong argument type!" ),
490 : static_cast< cppu::OWeakObject * >( this ),
491 : -1 ) ),
492 0 : Environment );
493 : // Unreachable
494 : }
495 0 : if ( !( aCommand.Argument >>= aOpenCommand ) )
496 : {
497 : // compat mode, extract Arg2 info into newer structure
498 0 : aOpenCommand.Mode = aTmp.Mode;
499 0 : aOpenCommand.Priority = aTmp.Priority;
500 0 : aOpenCommand.Sink = aTmp.Sink;
501 0 : aOpenCommand.Properties = aTmp.Properties;
502 0 : aOpenCommand.SortingInfo = aTmp.SortingInfo;
503 : }
504 :
505 0 : aRet = open( aOpenCommand, Environment );
506 :
507 0 : if ( (aOpenCommand.Mode == ucb::OpenMode::DOCUMENT ||
508 0 : aOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE) &&
509 0 : supportsExclusiveWriteLock( Environment ) )
510 0 : lock( Environment );
511 : }
512 0 : else if ( aCommand.Name == "insert" )
513 : {
514 :
515 : // insert
516 :
517 :
518 0 : ucb::InsertCommandArgument arg;
519 0 : if ( !( aCommand.Argument >>= arg ) )
520 : {
521 : ucbhelper::cancelCommandExecution(
522 : uno::makeAny( lang::IllegalArgumentException(
523 : OUString( "Wrong argument type!" ),
524 : static_cast< cppu::OWeakObject * >( this ),
525 : -1 ) ),
526 0 : Environment );
527 : // Unreachable
528 : }
529 :
530 0 : insert( arg.Data, arg.ReplaceExisting, Environment );
531 : }
532 0 : else if ( aCommand.Name == "delete" )
533 : {
534 :
535 : // delete
536 :
537 :
538 0 : bool bDeletePhysical = false;
539 0 : aCommand.Argument >>= bDeletePhysical;
540 :
541 : // KSO: Ignore parameter and destroy the content, if you don't support
542 : // putting objects into trashcan. ( Since we do not have a trash can
543 : // service yet (src603), you actually have no other choice. )
544 : // if ( bDeletePhysical )
545 : // {
546 : try
547 : {
548 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
549 : {
550 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
551 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
552 : }
553 0 : xResAccess->DESTROY( Environment );
554 : {
555 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
556 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
557 0 : }
558 : }
559 0 : catch ( DAVException const & e )
560 : {
561 0 : cancelCommandExecution( e, Environment, true );
562 : // Unreachable
563 : }
564 : // }
565 :
566 : // Propagate destruction.
567 0 : destroy( bDeletePhysical );
568 :
569 : // Remove own and all children's Additional Core Properties.
570 0 : removeAdditionalPropertySet( true );
571 : }
572 0 : else if ( aCommand.Name == "transfer" && isFolder( Environment ) )
573 : {
574 :
575 : // transfer
576 : // ( Not available at documents )
577 :
578 :
579 0 : ucb::TransferInfo transferArgs;
580 0 : if ( !( aCommand.Argument >>= transferArgs ) )
581 : {
582 : ucbhelper::cancelCommandExecution(
583 : uno::makeAny( lang::IllegalArgumentException(
584 : OUString( "Wrong argument type!" ),
585 : static_cast< cppu::OWeakObject * >( this ),
586 : -1 ) ),
587 0 : Environment );
588 : // Unreachable
589 : }
590 :
591 0 : transfer( transferArgs, Environment );
592 : }
593 0 : else if ( aCommand.Name == "post" )
594 : {
595 :
596 : // post
597 :
598 :
599 0 : ucb::PostCommandArgument2 aArg;
600 0 : if ( !( aCommand.Argument >>= aArg ) )
601 : {
602 : ucbhelper::cancelCommandExecution(
603 : uno::makeAny( lang::IllegalArgumentException(
604 : OUString( "Wrong argument type!" ),
605 : static_cast< cppu::OWeakObject * >( this ),
606 : -1 ) ),
607 0 : Environment );
608 : // Unreachable
609 : }
610 :
611 0 : post( aArg, Environment );
612 : }
613 0 : else if ( aCommand.Name == "lock" && supportsExclusiveWriteLock( Environment ) )
614 : {
615 :
616 : // lock
617 :
618 :
619 0 : lock( Environment );
620 : }
621 0 : else if ( aCommand.Name == "unlock" && supportsExclusiveWriteLock( Environment ) )
622 : {
623 :
624 : // unlock
625 :
626 :
627 0 : unlock( Environment );
628 : }
629 0 : else if ( aCommand.Name == "createNewContent" && isFolder( Environment ) )
630 : {
631 :
632 : // createNewContent
633 :
634 :
635 0 : ucb::ContentInfo aArg;
636 0 : if ( !( aCommand.Argument >>= aArg ) )
637 : {
638 : ucbhelper::cancelCommandExecution(
639 : uno::makeAny( lang::IllegalArgumentException(
640 : OUString( "Wrong argument type!" ),
641 : static_cast< cppu::OWeakObject * >( this ),
642 : -1 ) ),
643 0 : Environment );
644 : // Unreachable
645 : }
646 :
647 0 : aRet = uno::makeAny( createNewContent( aArg ) );
648 : }
649 0 : else if ( aCommand.Name == "addProperty" )
650 : {
651 0 : ucb::PropertyCommandArgument aPropArg;
652 0 : if ( !( aCommand.Argument >>= aPropArg ))
653 : {
654 : ucbhelper::cancelCommandExecution(
655 : uno::makeAny( lang::IllegalArgumentException(
656 : "Wrong argument type!",
657 : static_cast< cppu::OWeakObject * >( this ),
658 : -1 ) ),
659 0 : Environment );
660 : }
661 :
662 : // TODO when/if XPropertyContainer is removed,
663 : // the command execution can be canceled in addProperty
664 : try
665 : {
666 0 : addProperty( aPropArg, Environment );
667 : }
668 0 : catch ( const beans::PropertyExistException &e )
669 : {
670 0 : ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment );
671 : }
672 0 : catch ( const beans::IllegalTypeException&e )
673 : {
674 0 : ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment );
675 : }
676 0 : catch ( const lang::IllegalArgumentException&e )
677 : {
678 0 : ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment );
679 0 : }
680 : }
681 0 : else if ( aCommand.Name == "removeProperty" )
682 : {
683 0 : OUString sPropName;
684 0 : if ( !( aCommand.Argument >>= sPropName ) )
685 : {
686 : ucbhelper::cancelCommandExecution(
687 : uno::makeAny( lang::IllegalArgumentException(
688 : "Wrong argument type!",
689 : static_cast< cppu::OWeakObject * >( this ),
690 : -1 ) ),
691 0 : Environment );
692 : }
693 :
694 : // TODO when/if XPropertyContainer is removed,
695 : // the command execution can be canceled in removeProperty
696 : try
697 : {
698 0 : removeProperty( sPropName, Environment );
699 : }
700 0 : catch( const beans::UnknownPropertyException &e )
701 : {
702 0 : ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment );
703 : }
704 0 : catch( const beans::NotRemoveableException &e )
705 : {
706 0 : ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment );
707 0 : }
708 : }
709 : else
710 : {
711 :
712 : // Unsupported command
713 :
714 :
715 : ucbhelper::cancelCommandExecution(
716 : uno::makeAny( ucb::UnsupportedCommandException(
717 : aCommand.Name,
718 : static_cast< cppu::OWeakObject * >( this ) ) ),
719 0 : Environment );
720 : // Unreachable
721 : }
722 :
723 : OSL_TRACE( "<<<<< Content::execute: end: command: %s",
724 : OUStringToOString( aCommand.Name,
725 : RTL_TEXTENCODING_UTF8 ).getStr() );
726 :
727 0 : return aRet;
728 : }
729 :
730 :
731 : // virtual
732 0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
733 : throw( uno::RuntimeException, std::exception )
734 : {
735 : try
736 : {
737 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
738 : {
739 0 : osl::MutexGuard aGuard( m_aMutex );
740 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
741 : }
742 0 : xResAccess->abort();
743 : {
744 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
745 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
746 0 : }
747 : }
748 0 : catch ( DAVException const & )
749 : {
750 : // abort failed!
751 : }
752 0 : }
753 :
754 :
755 :
756 : // XPropertyContainer methods.
757 :
758 :
759 :
760 0 : void Content::addProperty( const ucb::PropertyCommandArgument& aCmdArg,
761 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
762 : throw( beans::PropertyExistException,
763 : beans::IllegalTypeException,
764 : lang::IllegalArgumentException,
765 : uno::RuntimeException,
766 : std::exception )
767 : {
768 : // if ( m_bTransient )
769 : // @@@ ???
770 :
771 0 : if ( aCmdArg.Property.Name.isEmpty() )
772 : throw lang::IllegalArgumentException(
773 : "\"addProperty\" with empty Property.Name",
774 : static_cast< cppu::OWeakObject * >( this ),
775 0 : -1 );
776 :
777 : // Check property type.
778 0 : if ( !UCBDeadPropertyValue::supportsType( aCmdArg.Property.Type ) )
779 : {
780 : throw beans::IllegalTypeException(
781 : "\"addProperty\" unsupported Property.Type",
782 0 : static_cast< cppu::OWeakObject * >( this ) );
783 : }
784 :
785 0 : if ( aCmdArg.DefaultValue.hasValue()
786 0 : && aCmdArg.DefaultValue.getValueType() != aCmdArg.Property.Type )
787 : {
788 : throw beans::IllegalTypeException(
789 : "\"addProperty\" DefaultValue does not match Property.Type",
790 0 : static_cast< ::cppu::OWeakObject * >( this ) );
791 : }
792 :
793 :
794 : // Make sure a property with the requested name does not already
795 : // exist in dynamic and static(!) properties.
796 :
797 :
798 : // Take into account special properties with custom namespace
799 : // using <prop:the_propname xmlns:prop="the_namespace">
800 0 : OUString aSpecialName;
801 : bool bIsSpecial = DAVProperties::isUCBSpecialProperty(
802 0 : aCmdArg.Property.Name, aSpecialName );
803 :
804 : // Note: This requires network access!
805 0 : if ( getPropertySetInfo( xEnv, false /* don't cache data */ )
806 0 : ->hasPropertyByName(
807 0 : bIsSpecial ? aSpecialName : aCmdArg.Property.Name ) )
808 : {
809 : // Property does already exist.
810 0 : throw beans::PropertyExistException();
811 : }
812 :
813 :
814 : // Add a new dynamic property.
815 :
816 :
817 : ProppatchValue aValue(
818 0 : PROPSET, aCmdArg.Property.Name, aCmdArg.DefaultValue );
819 :
820 0 : std::vector< ProppatchValue > aProppatchValues;
821 0 : aProppatchValues.push_back( aValue );
822 :
823 : try
824 : {
825 : // Set property value at server.
826 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
827 : {
828 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
829 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
830 : }
831 0 : xResAccess->PROPPATCH( aProppatchValues, xEnv );
832 : {
833 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
834 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
835 : }
836 :
837 : // Notify propertyset info change listeners.
838 : beans::PropertySetInfoChangeEvent evt(
839 : static_cast< cppu::OWeakObject * >( this ),
840 : bIsSpecial ? aSpecialName : aCmdArg.Property.Name,
841 : -1, // No handle available
842 0 : beans::PropertySetInfoChange::PROPERTY_INSERTED );
843 0 : notifyPropertySetInfoChange( evt );
844 : }
845 0 : catch ( DAVException const & e )
846 : {
847 0 : if ( e.getStatus() == SC_FORBIDDEN )
848 : {
849 : // Support for setting arbitrary dead properties is optional!
850 :
851 : // Store property locally.
852 : ContentImplHelper::addProperty(
853 : bIsSpecial ? aSpecialName : aCmdArg.Property.Name,
854 0 : aCmdArg.Property.Attributes, aCmdArg.DefaultValue );
855 : }
856 : else
857 : {
858 0 : if ( shouldAccessNetworkAfterException( e ) )
859 : {
860 : try
861 : {
862 0 : ResourceType eType = getResourceType( xEnv );
863 0 : switch ( eType )
864 : {
865 : case UNKNOWN:
866 : case DAV:
867 0 : throw lang::IllegalArgumentException();
868 :
869 : case FTP:
870 : case NON_DAV:
871 : // Store property locally.
872 : ContentImplHelper::addProperty(
873 : bIsSpecial ? aSpecialName : aCmdArg.Property.Name,
874 0 : aCmdArg.Property.Attributes, aCmdArg.DefaultValue );
875 0 : break;
876 :
877 : default:
878 : OSL_FAIL( "Content::addProperty - "
879 : "Unsupported resource type!" );
880 0 : break;
881 : }
882 : }
883 0 : catch ( uno::Exception const & )
884 : {
885 : OSL_FAIL( "Content::addProperty - "
886 : "Unable to determine resource type!" );
887 : }
888 : }
889 : else
890 : {
891 : OSL_FAIL( "Content::addProperty - "
892 : "Unable to determine resource type!" );
893 : }
894 : }
895 0 : }
896 0 : }
897 :
898 0 : void Content::removeProperty( const OUString& Name,
899 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
900 : throw( beans::UnknownPropertyException,
901 : beans::NotRemoveableException,
902 : uno::RuntimeException,
903 : std::exception )
904 : {
905 :
906 : // Try to remove property from server.
907 :
908 :
909 : try
910 : {
911 0 : std::vector< ProppatchValue > aProppatchValues;
912 0 : ProppatchValue aValue( PROPREMOVE, Name, uno::Any() );
913 0 : aProppatchValues.push_back( aValue );
914 :
915 : // Remove property value from server.
916 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
917 : {
918 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
919 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
920 : }
921 0 : xResAccess->PROPPATCH( aProppatchValues, xEnv );
922 : {
923 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
924 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
925 : }
926 :
927 : // Notify propertyset info change listeners.
928 : beans::PropertySetInfoChangeEvent evt(
929 : static_cast< cppu::OWeakObject * >( this ),
930 : Name,
931 : -1, // No handle available
932 0 : beans::PropertySetInfoChange::PROPERTY_REMOVED );
933 0 : notifyPropertySetInfoChange( evt );
934 : }
935 0 : catch ( DAVException const & e )
936 : {
937 0 : if ( e.getStatus() == SC_FORBIDDEN )
938 : {
939 : // Support for setting arbitrary dead properties is optional!
940 :
941 : // Try to remove property from local store.
942 0 : ContentImplHelper::removeProperty( Name );
943 : }
944 : else
945 : {
946 0 : if ( shouldAccessNetworkAfterException( e ) )
947 : {
948 : try
949 : {
950 0 : ResourceType eType = getResourceType( xEnv );
951 0 : switch ( eType )
952 : {
953 : case UNKNOWN:
954 : case DAV:
955 0 : throw beans::UnknownPropertyException();
956 :
957 : case FTP:
958 : case NON_DAV:
959 : // Try to remove property from local store.
960 0 : ContentImplHelper::removeProperty( Name );
961 0 : break;
962 :
963 : default:
964 : OSL_FAIL( "Content::removeProperty - "
965 : "Unsupported resource type!" );
966 0 : break;
967 : }
968 : }
969 0 : catch ( uno::Exception const & )
970 : {
971 : OSL_FAIL( "Content::removeProperty - "
972 : "Unable to determine resource type!" );
973 : }
974 : }
975 : else
976 : {
977 : OSL_FAIL( "Content::removeProperty - "
978 : "Unable to determine resource type!" );
979 : // throw beans::UnknownPropertyException();
980 : }
981 : }
982 : }
983 0 : }
984 :
985 : // virtual
986 0 : void SAL_CALL Content::addProperty( const OUString& Name,
987 : sal_Int16 Attributes,
988 : const uno::Any& DefaultValue )
989 : throw( beans::PropertyExistException,
990 : beans::IllegalTypeException,
991 : lang::IllegalArgumentException,
992 : uno::RuntimeException, std::exception )
993 : {
994 0 : beans::Property aProperty;
995 0 : aProperty.Name = Name;
996 0 : aProperty.Type = DefaultValue.getValueType();
997 0 : aProperty.Attributes = Attributes;
998 0 : aProperty.Handle = -1;
999 :
1000 : addProperty( ucb::PropertyCommandArgument( aProperty, DefaultValue ),
1001 0 : uno::Reference< ucb::XCommandEnvironment >());
1002 0 : }
1003 :
1004 : // virtual
1005 0 : void SAL_CALL Content::removeProperty( const OUString& Name )
1006 : throw( beans::UnknownPropertyException,
1007 : beans::NotRemoveableException,
1008 : uno::RuntimeException, std::exception )
1009 : {
1010 : removeProperty( Name,
1011 0 : uno::Reference< ucb::XCommandEnvironment >() );
1012 0 : }
1013 :
1014 :
1015 :
1016 : // XContentCreator methods.
1017 :
1018 :
1019 :
1020 : // virtual
1021 : uno::Sequence< ucb::ContentInfo > SAL_CALL
1022 0 : Content::queryCreatableContentsInfo()
1023 : throw( uno::RuntimeException, std::exception )
1024 : {
1025 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1026 :
1027 0 : uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1028 :
1029 : // document.
1030 0 : aSeq.getArray()[ 0 ].Type = WEBDAV_CONTENT_TYPE;
1031 0 : aSeq.getArray()[ 0 ].Attributes
1032 : = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
1033 0 : | ucb::ContentInfoAttribute::KIND_DOCUMENT;
1034 :
1035 0 : beans::Property aProp;
1036 : m_pProvider->getProperty(
1037 0 : OUString( "Title" ), aProp );
1038 :
1039 0 : uno::Sequence< beans::Property > aDocProps( 1 );
1040 0 : aDocProps.getArray()[ 0 ] = aProp;
1041 0 : aSeq.getArray()[ 0 ].Properties = aDocProps;
1042 :
1043 : // folder.
1044 0 : aSeq.getArray()[ 1 ].Type = WEBDAV_COLLECTION_TYPE;
1045 0 : aSeq.getArray()[ 1 ].Attributes
1046 0 : = ucb::ContentInfoAttribute::KIND_FOLDER;
1047 :
1048 0 : uno::Sequence< beans::Property > aFolderProps( 1 );
1049 0 : aFolderProps.getArray()[ 0 ] = aProp;
1050 0 : aSeq.getArray()[ 1 ].Properties = aFolderProps;
1051 0 : return aSeq;
1052 : }
1053 :
1054 :
1055 : // virtual
1056 : uno::Reference< ucb::XContent > SAL_CALL
1057 0 : Content::createNewContent( const ucb::ContentInfo& Info )
1058 : throw( uno::RuntimeException, std::exception )
1059 : {
1060 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1061 :
1062 0 : if ( Info.Type.isEmpty() )
1063 0 : return uno::Reference< ucb::XContent >();
1064 :
1065 0 : if ( ( Info.Type != WEBDAV_COLLECTION_TYPE ) && ( Info.Type != WEBDAV_CONTENT_TYPE ) )
1066 0 : return uno::Reference< ucb::XContent >();
1067 :
1068 0 : OUString aURL = m_xIdentifier->getContentIdentifier();
1069 :
1070 : OSL_ENSURE( !aURL.isEmpty(),
1071 : "WebdavContent::createNewContent - empty identifier!" );
1072 :
1073 0 : if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
1074 0 : aURL += "/";
1075 :
1076 : bool isCollection;
1077 0 : if ( Info.Type == WEBDAV_COLLECTION_TYPE )
1078 : {
1079 0 : aURL += "New_Collection";
1080 0 : isCollection = true;
1081 : }
1082 : else
1083 : {
1084 0 : aURL += "New_Content";
1085 0 : isCollection = false;
1086 : }
1087 :
1088 : uno::Reference< ucb::XContentIdentifier > xId(
1089 0 : new ::ucbhelper::ContentIdentifier( aURL ) );
1090 :
1091 : // create the local content
1092 : try
1093 : {
1094 : return new ::webdav_ucp::Content( m_xContext,
1095 : m_pProvider,
1096 : xId,
1097 : m_xResAccess->getSessionFactory(),
1098 0 : isCollection );
1099 : }
1100 0 : catch ( ucb::ContentCreationException & )
1101 : {
1102 0 : return uno::Reference< ucb::XContent >();
1103 0 : }
1104 : }
1105 :
1106 :
1107 : // virtual
1108 0 : OUString Content::getParentURL()
1109 : {
1110 : // <scheme>:// -> ""
1111 : // <scheme>://foo -> ""
1112 : // <scheme>://foo/ -> ""
1113 : // <scheme>://foo/bar -> <scheme>://foo/
1114 : // <scheme>://foo/bar/ -> <scheme>://foo/
1115 : // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
1116 :
1117 0 : OUString aURL = m_xIdentifier->getContentIdentifier();
1118 :
1119 0 : sal_Int32 nPos = aURL.lastIndexOf( '/' );
1120 0 : if ( nPos == ( aURL.getLength() - 1 ) )
1121 : {
1122 : // Trailing slash found. Skip.
1123 0 : nPos = aURL.lastIndexOf( '/', nPos );
1124 : }
1125 :
1126 0 : sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos );
1127 0 : if ( nPos1 != -1 )
1128 0 : nPos1 = aURL.lastIndexOf( '/', nPos1 );
1129 :
1130 0 : if ( nPos1 == -1 )
1131 0 : return OUString();
1132 :
1133 0 : return OUString( aURL.copy( 0, nPos + 1 ) );
1134 : }
1135 :
1136 :
1137 :
1138 : // Non-interface methods.
1139 :
1140 :
1141 :
1142 : // static
1143 0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
1144 : const uno::Reference< uno::XComponentContext >& rxContext,
1145 : const uno::Sequence< beans::Property >& rProperties,
1146 : const ContentProperties& rData,
1147 : const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider,
1148 : const OUString& rContentId )
1149 : {
1150 : // Note: Empty sequence means "get values of all supported properties".
1151 :
1152 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
1153 0 : = new ::ucbhelper::PropertyValueSet( rxContext );
1154 :
1155 0 : sal_Int32 nCount = rProperties.getLength();
1156 0 : if ( nCount )
1157 : {
1158 0 : uno::Reference< beans::XPropertySet > xAdditionalPropSet;
1159 0 : bool bTriedToGetAdditionalPropSet = false;
1160 :
1161 0 : const beans::Property* pProps = rProperties.getConstArray();
1162 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1163 : {
1164 0 : const beans::Property& rProp = pProps[ n ];
1165 :
1166 : // Process standard UCB, DAV and HTTP properties.
1167 0 : const uno::Any & rValue = rData.getValue( rProp.Name );
1168 0 : if ( rValue.hasValue() )
1169 : {
1170 0 : xRow->appendObject( rProp, rValue );
1171 : }
1172 : else
1173 : {
1174 : // Process local Additional Properties.
1175 0 : if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1176 : {
1177 : xAdditionalPropSet
1178 0 : = uno::Reference< beans::XPropertySet >(
1179 : rProvider->getAdditionalPropertySet( rContentId,
1180 : false ),
1181 0 : uno::UNO_QUERY );
1182 0 : bTriedToGetAdditionalPropSet = true;
1183 : }
1184 :
1185 0 : if ( !xAdditionalPropSet.is() ||
1186 : !xRow->appendPropertySetValue(
1187 0 : xAdditionalPropSet, rProp ) )
1188 : {
1189 : // Append empty entry.
1190 0 : xRow->appendVoid( rProp );
1191 : }
1192 : }
1193 0 : }
1194 : }
1195 : else
1196 : {
1197 : // Append all standard UCB, DAV and HTTP properties.
1198 0 : const std::unique_ptr< PropertyValueMap > & xProps = rData.getProperties();
1199 :
1200 0 : PropertyValueMap::const_iterator it = xProps->begin();
1201 0 : PropertyValueMap::const_iterator end = xProps->end();
1202 :
1203 : ContentProvider * pProvider
1204 0 : = static_cast< ContentProvider * >( rProvider.get() );
1205 0 : beans::Property aProp;
1206 :
1207 0 : while ( it != end )
1208 : {
1209 0 : if ( pProvider->getProperty( (*it).first, aProp ) )
1210 0 : xRow->appendObject( aProp, (*it).second.value() );
1211 :
1212 0 : ++it;
1213 : }
1214 :
1215 : // Append all local Additional Properties.
1216 : uno::Reference< beans::XPropertySet > xSet(
1217 : rProvider->getAdditionalPropertySet( rContentId, false ),
1218 0 : uno::UNO_QUERY );
1219 0 : xRow->appendPropertySet( xSet );
1220 : }
1221 :
1222 0 : return uno::Reference< sdbc::XRow >( xRow.get() );
1223 : }
1224 :
1225 :
1226 0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
1227 : const uno::Sequence< beans::Property >& rProperties,
1228 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1229 : throw ( uno::Exception, std::exception )
1230 : {
1231 0 : std::unique_ptr< ContentProperties > xProps;
1232 0 : std::unique_ptr< ContentProperties > xCachedProps;
1233 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
1234 0 : OUString aUnescapedTitle;
1235 0 : bool bHasAll = false;
1236 0 : uno::Reference< ucb::XContentIdentifier > xIdentifier;
1237 0 : rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider;
1238 :
1239 : {
1240 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1241 :
1242 0 : aUnescapedTitle = NeonUri::unescape( m_aEscapedTitle );
1243 0 : xIdentifier.set( m_xIdentifier );
1244 0 : xProvider.set( m_xProvider.get() );
1245 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
1246 :
1247 : // First, ask cache...
1248 0 : if ( m_xCachedProps.get() )
1249 : {
1250 0 : xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) );
1251 :
1252 0 : std::vector< OUString > aMissingProps;
1253 0 : if ( xCachedProps->containsAllNames( rProperties, aMissingProps ) )
1254 : {
1255 : // All properties are already in cache! No server access needed.
1256 0 : bHasAll = true;
1257 : }
1258 :
1259 : // use the cached ContentProperties instance
1260 0 : xProps.reset( new ContentProperties( *xCachedProps.get() ) );
1261 0 : }
1262 : }
1263 :
1264 0 : if ( !m_bTransient && !bHasAll )
1265 : {
1266 :
1267 : // Obtain values from server...
1268 :
1269 :
1270 : // First, identify whether resource is DAV or not
1271 0 : bool bNetworkAccessAllowed = true;
1272 : ResourceType eType = getResourceType(
1273 0 : xEnv, xResAccess, &bNetworkAccessAllowed );
1274 :
1275 0 : if ( eType == DAV )
1276 : {
1277 : // cache lookup... getResourceType may fill the props cache via
1278 : // PROPFIND!
1279 0 : if ( m_xCachedProps.get() )
1280 : {
1281 : xCachedProps.reset(
1282 0 : new ContentProperties( *m_xCachedProps.get() ) );
1283 :
1284 0 : std::vector< OUString > aMissingProps;
1285 0 : if ( xCachedProps->containsAllNames(
1286 0 : rProperties, aMissingProps ) )
1287 : {
1288 : // All properties are already in cache! No server access
1289 : // needed.
1290 0 : bHasAll = true;
1291 : }
1292 :
1293 : // use the cached ContentProperties instance
1294 0 : xProps.reset( new ContentProperties( *xCachedProps.get() ) );
1295 : }
1296 :
1297 0 : if ( !bHasAll )
1298 : {
1299 : // Only DAV resources support PROPFIND
1300 0 : std::vector< OUString > aPropNames;
1301 :
1302 : uno::Sequence< beans::Property > aProperties(
1303 0 : rProperties.getLength() );
1304 :
1305 0 : if ( !m_aFailedPropNames.empty() )
1306 : {
1307 0 : sal_Int32 nProps = 0;
1308 0 : sal_Int32 nCount = rProperties.getLength();
1309 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1310 : {
1311 0 : const OUString & rName = rProperties[ n ].Name;
1312 :
1313 : std::vector< OUString >::const_iterator it
1314 0 : = m_aFailedPropNames.begin();
1315 : std::vector< OUString >::const_iterator end
1316 0 : = m_aFailedPropNames.end();
1317 :
1318 0 : while ( it != end )
1319 : {
1320 0 : if ( *it == rName )
1321 0 : break;
1322 :
1323 0 : ++it;
1324 : }
1325 :
1326 0 : if ( it == end )
1327 : {
1328 0 : aProperties[ nProps ] = rProperties[ n ];
1329 0 : nProps++;
1330 : }
1331 : }
1332 :
1333 0 : aProperties.realloc( nProps );
1334 : }
1335 : else
1336 : {
1337 0 : aProperties = rProperties;
1338 : }
1339 :
1340 0 : if ( aProperties.getLength() > 0 )
1341 : ContentProperties::UCBNamesToDAVNames(
1342 0 : aProperties, aPropNames );
1343 :
1344 0 : if ( !aPropNames.empty() )
1345 : {
1346 0 : std::vector< DAVResource > resources;
1347 : try
1348 : {
1349 : xResAccess->PROPFIND(
1350 0 : DAVZERO, aPropNames, resources, xEnv );
1351 :
1352 0 : if ( 1 == resources.size() )
1353 : {
1354 0 : if ( xProps.get())
1355 : xProps->addProperties(
1356 : aPropNames,
1357 0 : ContentProperties( resources[ 0 ] ));
1358 : else
1359 : xProps.reset(
1360 0 : new ContentProperties( resources[ 0 ] ) );
1361 : }
1362 : }
1363 0 : catch ( DAVException const & e )
1364 : {
1365 : bNetworkAccessAllowed = bNetworkAccessAllowed
1366 0 : && shouldAccessNetworkAfterException( e );
1367 :
1368 0 : if ( !bNetworkAccessAllowed )
1369 : {
1370 0 : cancelCommandExecution( e, xEnv );
1371 : // unreachable
1372 : }
1373 0 : }
1374 0 : }
1375 : }
1376 : }
1377 :
1378 0 : if ( bNetworkAccessAllowed )
1379 : {
1380 : // All properties obtained already?
1381 0 : std::vector< OUString > aMissingProps;
1382 0 : if ( !( xProps.get()
1383 : && xProps->containsAllNames(
1384 0 : rProperties, aMissingProps ) )
1385 0 : && !m_bDidGetOrHead )
1386 : {
1387 : // Possibly the missing props can be obtained using a HEAD
1388 : // request.
1389 :
1390 0 : std::vector< OUString > aHeaderNames;
1391 : ContentProperties::UCBNamesToHTTPNames(
1392 : rProperties,
1393 : aHeaderNames,
1394 0 : true /* bIncludeUnmatched */ );
1395 :
1396 0 : if ( !aHeaderNames.empty() )
1397 : {
1398 : try
1399 : {
1400 0 : DAVResource resource;
1401 0 : xResAccess->HEAD( aHeaderNames, resource, xEnv );
1402 0 : m_bDidGetOrHead = true;
1403 :
1404 0 : if ( xProps.get() )
1405 : xProps->addProperties(
1406 : aMissingProps,
1407 0 : ContentProperties( resource ) );
1408 : else
1409 0 : xProps.reset ( new ContentProperties( resource ) );
1410 :
1411 0 : if ( m_eResourceType == NON_DAV )
1412 : xProps->addProperties( aMissingProps,
1413 : ContentProperties(
1414 : aUnescapedTitle,
1415 0 : false ) );
1416 : }
1417 0 : catch ( DAVException const & e )
1418 : {
1419 : bNetworkAccessAllowed
1420 0 : = shouldAccessNetworkAfterException( e );
1421 :
1422 0 : if ( !bNetworkAccessAllowed )
1423 : {
1424 0 : cancelCommandExecution( e, xEnv );
1425 : // unreachable
1426 : }
1427 : }
1428 0 : }
1429 0 : }
1430 : }
1431 :
1432 : // might trigger HTTP redirect.
1433 : // Therefore, title must be updated here.
1434 0 : NeonUri aUri( xResAccess->getURL() );
1435 0 : aUnescapedTitle = aUri.GetPathBaseNameUnescaped();
1436 :
1437 0 : if ( eType == UNKNOWN )
1438 : {
1439 0 : xProps.reset( new ContentProperties( aUnescapedTitle ) );
1440 : }
1441 :
1442 : // For DAV resources we only know the Title, for non-DAV
1443 : // resources we additionally know that it is a document.
1444 :
1445 0 : if ( eType == DAV )
1446 : {
1447 : //xProps.reset(
1448 : // new ContentProperties( aUnescapedTitle ) );
1449 : xProps->addProperty(
1450 : OUString( "Title" ),
1451 : uno::makeAny( aUnescapedTitle ),
1452 0 : true );
1453 : }
1454 : else
1455 : {
1456 0 : if ( !xProps.get() )
1457 0 : xProps.reset( new ContentProperties( aUnescapedTitle, false ) );
1458 : else
1459 : xProps->addProperty(
1460 : OUString( "Title" ),
1461 : uno::makeAny( aUnescapedTitle ),
1462 0 : true );
1463 :
1464 : xProps->addProperty(
1465 : OUString( "IsFolder" ),
1466 : uno::makeAny( false ),
1467 0 : true );
1468 : xProps->addProperty(
1469 : OUString( "IsDocument" ),
1470 : uno::makeAny( true ),
1471 0 : true );
1472 0 : }
1473 : }
1474 : else
1475 : {
1476 : // No server access for just created (not yet committed) objects.
1477 : // Only a minimal set of properties supported at this stage.
1478 0 : if (m_bTransient)
1479 : xProps.reset( new ContentProperties( aUnescapedTitle,
1480 0 : m_bCollection ) );
1481 : }
1482 :
1483 0 : sal_Int32 nCount = rProperties.getLength();
1484 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1485 : {
1486 0 : const OUString rName = rProperties[ n ].Name;
1487 0 : if ( rName == "BaseURI" )
1488 : {
1489 : // Add BaseURI property, if requested.
1490 : xProps->addProperty(
1491 : OUString( "BaseURI" ),
1492 : uno::makeAny( getBaseURI( xResAccess ) ),
1493 0 : true );
1494 : }
1495 0 : else if ( rName == "CreatableContentsInfo" )
1496 : {
1497 : // Add CreatableContentsInfo property, if requested.
1498 0 : bool bFolder = false;
1499 : xProps->getValue(
1500 0 : OUString( "IsFolder" ) )
1501 0 : >>= bFolder;
1502 : xProps->addProperty(
1503 : OUString( "CreatableContentsInfo" ),
1504 : uno::makeAny( bFolder
1505 0 : ? queryCreatableContentsInfo()
1506 : : uno::Sequence< ucb::ContentInfo >() ),
1507 0 : true );
1508 : }
1509 0 : }
1510 :
1511 : uno::Reference< sdbc::XRow > xResultRow
1512 : = getPropertyValues( m_xContext,
1513 : rProperties,
1514 0 : *xProps,
1515 : xProvider,
1516 0 : xIdentifier->getContentIdentifier() );
1517 :
1518 : {
1519 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1520 :
1521 0 : if ( !m_xCachedProps.get() )
1522 0 : m_xCachedProps.reset( new CachableContentProperties( *xProps.get() ) );
1523 : else
1524 0 : m_xCachedProps->addProperties( *xProps.get() );
1525 :
1526 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
1527 0 : m_aEscapedTitle = NeonUri::escapeSegment( aUnescapedTitle );
1528 : }
1529 :
1530 0 : return xResultRow;
1531 : }
1532 :
1533 :
1534 0 : uno::Sequence< uno::Any > Content::setPropertyValues(
1535 : const uno::Sequence< beans::PropertyValue >& rValues,
1536 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1537 : throw ( uno::Exception, std::exception )
1538 : {
1539 0 : uno::Reference< ucb::XContentIdentifier > xIdentifier;
1540 0 : rtl::Reference< ContentProvider > xProvider;
1541 : bool bTransient;
1542 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
1543 :
1544 : {
1545 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1546 :
1547 0 : xProvider.set( m_pProvider );
1548 0 : xIdentifier.set( m_xIdentifier );
1549 0 : bTransient = m_bTransient;
1550 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
1551 : }
1552 :
1553 0 : uno::Sequence< uno::Any > aRet( rValues.getLength() );
1554 0 : uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1555 0 : sal_Int32 nChanged = 0;
1556 :
1557 0 : beans::PropertyChangeEvent aEvent;
1558 0 : aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1559 0 : aEvent.Further = sal_False;
1560 : // aEvent.PropertyName =
1561 0 : aEvent.PropertyHandle = -1;
1562 : // aEvent.OldValue =
1563 : // aEvent.NewValue =
1564 :
1565 0 : std::vector< ProppatchValue > aProppatchValues;
1566 0 : std::vector< sal_Int32 > aProppatchPropsPositions;
1567 :
1568 0 : uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1569 0 : bool bTriedToGetAdditionalPropSet = false;
1570 :
1571 0 : bool bExchange = false;
1572 0 : OUString aNewTitle;
1573 0 : OUString aOldTitle;
1574 0 : sal_Int32 nTitlePos = -1;
1575 :
1576 0 : uno::Reference< beans::XPropertySetInfo > xInfo;
1577 :
1578 0 : const beans::PropertyValue* pValues = rValues.getConstArray();
1579 0 : sal_Int32 nCount = rValues.getLength();
1580 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1581 : {
1582 0 : const beans::PropertyValue& rValue = pValues[ n ];
1583 0 : const OUString & rName = rValue.Name;
1584 :
1585 0 : beans::Property aTmpProp;
1586 0 : xProvider->getProperty( rName, aTmpProp );
1587 :
1588 0 : if ( aTmpProp.Attributes & beans::PropertyAttribute::READONLY )
1589 : {
1590 : // Read-only property!
1591 0 : aRet[ n ] <<= lang::IllegalAccessException(
1592 : OUString( "Property is read-only!" ),
1593 0 : static_cast< cppu::OWeakObject * >( this ) );
1594 0 : continue;
1595 : }
1596 :
1597 :
1598 : // Mandatory props.
1599 :
1600 :
1601 0 : if ( rName == "ContentType" )
1602 : {
1603 : // Read-only property!
1604 0 : aRet[ n ] <<= lang::IllegalAccessException(
1605 : OUString( "Property is read-only!" ),
1606 0 : static_cast< cppu::OWeakObject * >( this ) );
1607 : }
1608 0 : else if ( rName == "IsDocument" )
1609 : {
1610 : // Read-only property!
1611 0 : aRet[ n ] <<= lang::IllegalAccessException(
1612 : OUString( "Property is read-only!" ),
1613 0 : static_cast< cppu::OWeakObject * >( this ) );
1614 : }
1615 0 : else if ( rName == "IsFolder" )
1616 : {
1617 : // Read-only property!
1618 0 : aRet[ n ] <<= lang::IllegalAccessException(
1619 : OUString( "Property is read-only!" ),
1620 0 : static_cast< cppu::OWeakObject * >( this ) );
1621 : }
1622 0 : else if ( rName == "Title" )
1623 : {
1624 0 : OUString aNewValue;
1625 0 : if ( rValue.Value >>= aNewValue )
1626 : {
1627 : // No empty titles!
1628 0 : if ( !aNewValue.isEmpty() )
1629 : {
1630 : try
1631 : {
1632 0 : NeonUri aURI( xIdentifier->getContentIdentifier() );
1633 0 : aOldTitle = aURI.GetPathBaseNameUnescaped();
1634 :
1635 0 : if ( aNewValue != aOldTitle )
1636 : {
1637 : // modified title -> modified URL -> exchange !
1638 0 : if ( !bTransient )
1639 0 : bExchange = true;
1640 :
1641 : // new value will be set later...
1642 0 : aNewTitle = aNewValue;
1643 :
1644 : // remember position within sequence of values (for
1645 : // error handling).
1646 0 : nTitlePos = n;
1647 0 : }
1648 : }
1649 0 : catch ( DAVException const & )
1650 : {
1651 0 : aRet[ n ] <<= lang::IllegalArgumentException(
1652 : OUString( "Invalid content identifier!" ),
1653 : static_cast< cppu::OWeakObject * >( this ),
1654 0 : -1 );
1655 : }
1656 : }
1657 : else
1658 : {
1659 0 : aRet[ n ] <<= lang::IllegalArgumentException(
1660 : OUString( "Empty title not allowed!" ),
1661 : static_cast< cppu::OWeakObject * >( this ),
1662 0 : -1 );
1663 : }
1664 : }
1665 : else
1666 : {
1667 0 : aRet[ n ] <<= beans::IllegalTypeException(
1668 : OUString( "Property value has wrong type!" ),
1669 0 : static_cast< cppu::OWeakObject * >( this ) );
1670 0 : }
1671 : }
1672 : else
1673 : {
1674 :
1675 : // Optional props.
1676 :
1677 :
1678 0 : OUString aSpecialName;
1679 : bool bIsSpecial = DAVProperties::isUCBSpecialProperty(
1680 0 : rName, aSpecialName );
1681 :
1682 0 : if ( !xInfo.is() )
1683 0 : xInfo = getPropertySetInfo( xEnv,
1684 0 : false /* don't cache data */ );
1685 :
1686 0 : if ( !xInfo->hasPropertyByName(
1687 0 : bIsSpecial ? aSpecialName : rName ) )
1688 : {
1689 : // Check, whether property exists. Skip otherwise.
1690 : // PROPPATCH::set would add the property automatically, which
1691 : // is not allowed for "setPropertyValues" command!
1692 0 : aRet[ n ] <<= beans::UnknownPropertyException(
1693 : OUString( "Property is unknown!" ),
1694 0 : static_cast< cppu::OWeakObject * >( this ) );
1695 0 : continue;
1696 : }
1697 :
1698 0 : if ( rName == "Size" )
1699 : {
1700 : // Read-only property!
1701 0 : aRet[ n ] <<= lang::IllegalAccessException(
1702 : OUString( "Property is read-only!" ),
1703 0 : static_cast< cppu::OWeakObject * >( this ) );
1704 : }
1705 0 : else if ( rName == "DateCreated" )
1706 : {
1707 : // Read-only property!
1708 0 : aRet[ n ] <<= lang::IllegalAccessException(
1709 : OUString( "Property is read-only!" ),
1710 0 : static_cast< cppu::OWeakObject * >( this ) );
1711 : }
1712 0 : else if ( rName == "DateModified" )
1713 : {
1714 : // Read-only property!
1715 0 : aRet[ n ] <<= lang::IllegalAccessException(
1716 : OUString( "Property is read-only!" ),
1717 0 : static_cast< cppu::OWeakObject * >( this ) );
1718 : }
1719 0 : else if ( rName == "MediaType" )
1720 : {
1721 : // Read-only property!
1722 : // (but could be writable, if 'getcontenttype' would be)
1723 0 : aRet[ n ] <<= lang::IllegalAccessException(
1724 : OUString( "Property is read-only!" ),
1725 0 : static_cast< cppu::OWeakObject * >( this ) );
1726 : }
1727 0 : if ( rName == "CreatableContentsInfo" )
1728 : {
1729 : // Read-only property!
1730 0 : aRet[ n ] <<= lang::IllegalAccessException(
1731 : OUString( "Property is read-only!" ),
1732 0 : static_cast< cppu::OWeakObject * >( this ) );
1733 : }
1734 : else
1735 : {
1736 0 : if ( getResourceType( xEnv, xResAccess ) == DAV )
1737 : {
1738 : // Property value will be set on server.
1739 0 : ProppatchValue aValue( PROPSET, rName, rValue.Value );
1740 0 : aProppatchValues.push_back( aValue );
1741 :
1742 : // remember position within sequence of values (for
1743 : // error handling).
1744 0 : aProppatchPropsPositions.push_back( n );
1745 : }
1746 : else
1747 : {
1748 : // Property value will be stored in local property store.
1749 0 : if ( !bTriedToGetAdditionalPropSet &&
1750 0 : !xAdditionalPropSet.is() )
1751 : {
1752 : xAdditionalPropSet
1753 0 : = getAdditionalPropertySet( false );
1754 0 : bTriedToGetAdditionalPropSet = true;
1755 : }
1756 :
1757 0 : if ( xAdditionalPropSet.is() )
1758 : {
1759 : try
1760 : {
1761 : uno::Any aOldValue
1762 0 : = xAdditionalPropSet->getPropertyValue( rName );
1763 0 : if ( aOldValue != rValue.Value )
1764 : {
1765 0 : xAdditionalPropSet->setPropertyValue(
1766 0 : rName, rValue.Value );
1767 :
1768 0 : aEvent.PropertyName = rName;
1769 0 : aEvent.OldValue = aOldValue;
1770 0 : aEvent.NewValue = rValue.Value;
1771 :
1772 0 : aChanges.getArray()[ nChanged ] = aEvent;
1773 0 : nChanged++;
1774 0 : }
1775 : }
1776 0 : catch ( beans::UnknownPropertyException const & e )
1777 : {
1778 0 : aRet[ n ] <<= e;
1779 : }
1780 0 : catch ( lang::WrappedTargetException const & e )
1781 : {
1782 0 : aRet[ n ] <<= e;
1783 : }
1784 0 : catch ( beans::PropertyVetoException const & e )
1785 : {
1786 0 : aRet[ n ] <<= e;
1787 : }
1788 0 : catch ( lang::IllegalArgumentException const & e )
1789 : {
1790 0 : aRet[ n ] <<= e;
1791 : }
1792 : }
1793 : else
1794 : {
1795 0 : aRet[ n ] <<= uno::Exception(
1796 : OUString( "No property set for storing the value!" ),
1797 0 : static_cast< cppu::OWeakObject * >( this ) );
1798 : }
1799 : }
1800 0 : }
1801 : }
1802 0 : } // for
1803 :
1804 0 : if ( !bTransient && !aProppatchValues.empty() )
1805 : {
1806 : try
1807 : {
1808 : // Set property values at server.
1809 0 : xResAccess->PROPPATCH( aProppatchValues, xEnv );
1810 :
1811 : std::vector< ProppatchValue >::const_iterator it
1812 0 : = aProppatchValues.begin();
1813 : std::vector< ProppatchValue >::const_iterator end
1814 0 : = aProppatchValues.end();
1815 :
1816 0 : while ( it != end )
1817 : {
1818 0 : aEvent.PropertyName = (*it).name;
1819 0 : aEvent.OldValue = uno::Any(); // @@@ to expensive to obtain!
1820 0 : aEvent.NewValue = (*it).value;
1821 :
1822 0 : aChanges.getArray()[ nChanged ] = aEvent;
1823 0 : nChanged++;
1824 :
1825 0 : ++it;
1826 : }
1827 : }
1828 0 : catch ( DAVException const & e )
1829 : {
1830 : // OSL_FAIL( // "Content::setPropertyValues - PROPPATCH failed!" );
1831 :
1832 0 : cancelCommandExecution( e, xEnv );
1833 : // unreachable
1834 : }
1835 : }
1836 :
1837 0 : if ( bExchange )
1838 : {
1839 : // Assemble new content identifier...
1840 :
1841 0 : OUString aNewURL = getParentURL();
1842 0 : if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) )
1843 0 : aNewURL += "/";
1844 :
1845 0 : aNewURL += NeonUri::escapeSegment( aNewTitle );
1846 :
1847 : uno::Reference< ucb::XContentIdentifier > xNewId
1848 0 : = new ::ucbhelper::ContentIdentifier( aNewURL );
1849 0 : uno::Reference< ucb::XContentIdentifier > xOldId = xIdentifier;
1850 :
1851 : try
1852 : {
1853 0 : NeonUri sourceURI( xOldId->getContentIdentifier() );
1854 0 : NeonUri targetURI( xNewId->getContentIdentifier() );
1855 0 : targetURI.SetScheme( sourceURI.GetScheme() );
1856 :
1857 : xResAccess->MOVE(
1858 0 : sourceURI.GetPath(), targetURI.GetURI(), false, xEnv );
1859 : // @@@ Should check for resources that could not be moved
1860 : // (due to source access or target overwrite) and send
1861 : // this information through the interaction handler.
1862 :
1863 : // @@@ Existing content should be checked to see if it needs
1864 : // to be deleted at the source
1865 :
1866 : // @@@ Existing content should be checked to see if it has
1867 : // been overwritten at the target
1868 :
1869 0 : if ( exchangeIdentity( xNewId ) )
1870 : {
1871 0 : xResAccess->setURL( aNewURL );
1872 :
1873 : // DAV resources store all additional props on server!
1874 : // // Adapt Additional Core Properties.
1875 : // renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1876 : // xNewId->getContentIdentifier(),
1877 : // sal_True );
1878 : }
1879 : else
1880 : {
1881 : // Do not set new title!
1882 0 : aNewTitle = "";
1883 :
1884 : // Set error .
1885 0 : aRet[ nTitlePos ] <<= uno::Exception(
1886 : OUString("Exchange failed!"),
1887 0 : static_cast< cppu::OWeakObject * >( this ) );
1888 0 : }
1889 : }
1890 0 : catch ( DAVException const & e )
1891 : {
1892 : // Do not set new title!
1893 0 : aNewTitle = "";
1894 :
1895 : // Set error .
1896 0 : aRet[ nTitlePos ] <<= MapDAVException( e, true );
1897 0 : }
1898 : }
1899 :
1900 0 : if ( !aNewTitle.isEmpty() )
1901 : {
1902 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1903 :
1904 0 : aEvent.PropertyName = "Title";
1905 0 : aEvent.OldValue = uno::makeAny( aOldTitle );
1906 0 : aEvent.NewValue = uno::makeAny( aNewTitle );
1907 :
1908 0 : m_aEscapedTitle = NeonUri::escapeSegment( aNewTitle );
1909 :
1910 0 : aChanges.getArray()[ nChanged ] = aEvent;
1911 0 : nChanged++;
1912 : }
1913 :
1914 0 : if ( nChanged > 0 )
1915 : {
1916 0 : aChanges.realloc( nChanged );
1917 0 : notifyPropertiesChange( aChanges );
1918 : }
1919 :
1920 : {
1921 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1922 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
1923 : }
1924 :
1925 0 : return aRet;
1926 : }
1927 :
1928 :
1929 0 : uno::Any Content::open(
1930 : const ucb::OpenCommandArgument3 & rArg,
1931 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1932 : throw (uno::Exception, std::exception)
1933 : {
1934 0 : uno::Any aRet;
1935 :
1936 0 : bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) ||
1937 0 : ( rArg.Mode == ucb::OpenMode::FOLDERS ) ||
1938 0 : ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) );
1939 0 : if ( bOpenFolder )
1940 : {
1941 0 : if ( isFolder( xEnv ) )
1942 : {
1943 : // Open collection.
1944 :
1945 : uno::Reference< ucb::XDynamicResultSet > xSet
1946 0 : = new DynamicResultSet( m_xContext, this, rArg, xEnv );
1947 0 : aRet <<= xSet;
1948 : }
1949 : else
1950 : {
1951 : // Error: Not a folder!
1952 :
1953 0 : OUStringBuffer aMsg;
1954 0 : if ( getResourceType( xEnv ) == FTP )
1955 : {
1956 : // #114653#
1957 : aMsg.appendAscii( "FTP over HTTP proxy: resource cannot "
1958 0 : "be opened as folder! Wrong Open Mode!" );
1959 : }
1960 : else
1961 : {
1962 : aMsg.appendAscii( "Non-folder resource cannot be "
1963 0 : "opened as folder! Wrong Open Mode!" );
1964 : }
1965 :
1966 : ucbhelper::cancelCommandExecution(
1967 : uno::makeAny(
1968 : lang::IllegalArgumentException(
1969 : aMsg.makeStringAndClear(),
1970 : static_cast< cppu::OWeakObject * >( this ),
1971 : -1 ) ),
1972 0 : xEnv );
1973 : // Unreachable
1974 : }
1975 : }
1976 :
1977 0 : if ( rArg.Sink.is() )
1978 : {
1979 : // Open document.
1980 :
1981 0 : if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1982 0 : ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1983 : {
1984 : // Currently(?) unsupported.
1985 : ucbhelper::cancelCommandExecution(
1986 : uno::makeAny(
1987 : ucb::UnsupportedOpenModeException(
1988 : OUString(),
1989 : static_cast< cppu::OWeakObject * >( this ),
1990 : sal_Int16( rArg.Mode ) ) ),
1991 0 : xEnv );
1992 : // Unreachable
1993 : }
1994 :
1995 : uno::Reference< io::XOutputStream > xOut
1996 0 : = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
1997 0 : if ( xOut.is() )
1998 : {
1999 : // PUSH: write data
2000 : try
2001 : {
2002 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2003 :
2004 : {
2005 0 : osl::MutexGuard aGuard( m_aMutex );
2006 :
2007 : xResAccess.reset(
2008 0 : new DAVResourceAccess( *m_xResAccess.get() ) );
2009 : }
2010 :
2011 0 : xResAccess->setFlags( rArg.OpeningFlags );
2012 0 : DAVResource aResource;
2013 0 : std::vector< OUString > aHeaders;
2014 :
2015 0 : xResAccess->GET( xOut, aHeaders, aResource, xEnv );
2016 0 : m_bDidGetOrHead = true;
2017 :
2018 : {
2019 0 : osl::MutexGuard aGuard( m_aMutex );
2020 :
2021 : // cache headers.
2022 0 : if ( !m_xCachedProps.get())
2023 : m_xCachedProps.reset(
2024 0 : new CachableContentProperties( aResource ) );
2025 : else
2026 0 : m_xCachedProps->addProperties( aResource );
2027 :
2028 : m_xResAccess.reset(
2029 0 : new DAVResourceAccess( *xResAccess.get() ) );
2030 0 : }
2031 : }
2032 0 : catch ( DAVException const & e )
2033 : {
2034 0 : cancelCommandExecution( e, xEnv );
2035 : // Unreachable
2036 : }
2037 : }
2038 : else
2039 : {
2040 : uno::Reference< io::XActiveDataSink > xDataSink
2041 : = uno::Reference< io::XActiveDataSink >( rArg.Sink,
2042 0 : uno::UNO_QUERY );
2043 0 : if ( xDataSink.is() )
2044 : {
2045 : // PULL: wait for client read
2046 : try
2047 : {
2048 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2049 : {
2050 0 : osl::MutexGuard aGuard( m_aMutex );
2051 :
2052 : xResAccess.reset(
2053 0 : new DAVResourceAccess( *m_xResAccess.get() ) );
2054 : }
2055 :
2056 0 : xResAccess->setFlags( rArg.OpeningFlags );
2057 :
2058 : // fill inputsream sync; return if all data present
2059 0 : DAVResource aResource;
2060 0 : std::vector< OUString > aHeaders;
2061 :
2062 : uno::Reference< io::XInputStream > xIn
2063 0 : = xResAccess->GET( aHeaders, aResource, xEnv );
2064 0 : m_bDidGetOrHead = true;
2065 :
2066 : {
2067 0 : osl::MutexGuard aGuard( m_aMutex );
2068 :
2069 : // cache headers.
2070 0 : if ( !m_xCachedProps.get())
2071 : m_xCachedProps.reset(
2072 0 : new CachableContentProperties( aResource ) );
2073 : else
2074 : m_xCachedProps->addProperties(
2075 0 : aResource.properties );
2076 :
2077 : m_xResAccess.reset(
2078 0 : new DAVResourceAccess( *xResAccess.get() ) );
2079 : }
2080 :
2081 0 : xDataSink->setInputStream( xIn );
2082 : }
2083 0 : catch ( DAVException const & e )
2084 : {
2085 0 : cancelCommandExecution( e, xEnv );
2086 : // Unreachable
2087 : }
2088 : }
2089 : else
2090 : {
2091 : // Note: aOpenCommand.Sink may contain an XStream
2092 : // implementation. Support for this type of
2093 : // sink is optional...
2094 : ucbhelper::cancelCommandExecution(
2095 : uno::makeAny(
2096 : ucb::UnsupportedDataSinkException(
2097 : OUString(),
2098 : static_cast< cppu::OWeakObject * >( this ),
2099 : rArg.Sink ) ),
2100 0 : xEnv );
2101 : // Unreachable
2102 0 : }
2103 0 : }
2104 : }
2105 :
2106 0 : return aRet;
2107 : }
2108 :
2109 :
2110 0 : void Content::post(
2111 : const ucb::PostCommandArgument2 & rArg,
2112 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2113 : throw( uno::Exception )
2114 : {
2115 0 : uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY );
2116 0 : if ( xSink.is() )
2117 : {
2118 : try
2119 : {
2120 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2121 : {
2122 0 : osl::MutexGuard aGuard( m_aMutex );
2123 : xResAccess.reset(
2124 0 : new DAVResourceAccess( *m_xResAccess.get() ) );
2125 : }
2126 :
2127 : uno::Reference< io::XInputStream > xResult
2128 : = xResAccess->POST( rArg.MediaType,
2129 : rArg.Referer,
2130 : rArg.Source,
2131 0 : xEnv );
2132 :
2133 : {
2134 0 : osl::MutexGuard aGuard( m_aMutex );
2135 : m_xResAccess.reset(
2136 0 : new DAVResourceAccess( *xResAccess.get() ) );
2137 : }
2138 :
2139 0 : xSink->setInputStream( xResult );
2140 : }
2141 0 : catch ( DAVException const & e )
2142 : {
2143 0 : cancelCommandExecution( e, xEnv, true );
2144 : // Unreachable
2145 : }
2146 : }
2147 : else
2148 : {
2149 0 : uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
2150 0 : if ( xResult.is() )
2151 : {
2152 : try
2153 : {
2154 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2155 : {
2156 0 : osl::MutexGuard aGuard( m_aMutex );
2157 : xResAccess.reset(
2158 0 : new DAVResourceAccess( *m_xResAccess.get() ) );
2159 : }
2160 :
2161 : xResAccess->POST( rArg.MediaType,
2162 : rArg.Referer,
2163 : rArg.Source,
2164 : xResult,
2165 0 : xEnv );
2166 :
2167 : {
2168 0 : osl::MutexGuard aGuard( m_aMutex );
2169 : m_xResAccess.reset(
2170 0 : new DAVResourceAccess( *xResAccess.get() ) );
2171 0 : }
2172 : }
2173 0 : catch ( DAVException const & e )
2174 : {
2175 0 : cancelCommandExecution( e, xEnv, true );
2176 : // Unreachable
2177 : }
2178 : }
2179 : else
2180 : {
2181 : ucbhelper::cancelCommandExecution(
2182 : uno::makeAny(
2183 : ucb::UnsupportedDataSinkException(
2184 : OUString(),
2185 : static_cast< cppu::OWeakObject * >( this ),
2186 : rArg.Sink ) ),
2187 0 : xEnv );
2188 : // Unreachable
2189 0 : }
2190 0 : }
2191 0 : }
2192 :
2193 :
2194 0 : void Content::queryChildren( ContentRefList& rChildren )
2195 : {
2196 : // Obtain a list with a snapshot of all currently instantiated contents
2197 : // from provider and extract the contents which are direct children
2198 : // of this content.
2199 :
2200 0 : ::ucbhelper::ContentRefList aAllContents;
2201 0 : m_xProvider->queryExistingContents( aAllContents );
2202 :
2203 0 : OUString aURL = m_xIdentifier->getContentIdentifier();
2204 0 : sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
2205 :
2206 0 : if ( nURLPos != ( aURL.getLength() - 1 ) )
2207 : {
2208 : // No trailing slash found. Append.
2209 0 : aURL += "/";
2210 : }
2211 :
2212 0 : sal_Int32 nLen = aURL.getLength();
2213 :
2214 0 : ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
2215 0 : ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
2216 :
2217 0 : while ( it != end )
2218 : {
2219 0 : ::ucbhelper::ContentImplHelperRef xChild = (*it);
2220 : OUString aChildURL
2221 0 : = xChild->getIdentifier()->getContentIdentifier();
2222 :
2223 : // Is aURL a prefix of aChildURL?
2224 0 : if ( ( aChildURL.getLength() > nLen ) &&
2225 0 : ( aChildURL.startsWith( aURL ) ) )
2226 : {
2227 0 : sal_Int32 nPos = nLen;
2228 0 : nPos = aChildURL.indexOf( '/', nPos );
2229 :
2230 0 : if ( ( nPos == -1 ) ||
2231 0 : ( nPos == ( aChildURL.getLength() - 1 ) ) )
2232 : {
2233 : // No further slashes / only a final slash. It's a child!
2234 : rChildren.push_back(
2235 : ::webdav_ucp::Content::ContentRef(
2236 : static_cast< ::webdav_ucp::Content * >(
2237 0 : xChild.get() ) ) );
2238 : }
2239 : }
2240 0 : ++it;
2241 0 : }
2242 0 : }
2243 :
2244 :
2245 0 : void Content::insert(
2246 : const uno::Reference< io::XInputStream > & xInputStream,
2247 : bool bReplaceExisting,
2248 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
2249 : throw( uno::Exception )
2250 : {
2251 : bool bTransient, bCollection;
2252 0 : OUString aEscapedTitle;
2253 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2254 :
2255 : {
2256 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2257 :
2258 0 : bTransient = m_bTransient;
2259 0 : bCollection = m_bCollection;
2260 0 : aEscapedTitle = m_aEscapedTitle;
2261 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
2262 : }
2263 :
2264 : // Check, if all required properties are present.
2265 :
2266 0 : if ( aEscapedTitle.isEmpty() )
2267 : {
2268 : OSL_FAIL( "Content::insert - Title missing!" );
2269 :
2270 0 : uno::Sequence< OUString > aProps( 1 );
2271 0 : aProps[ 0 ] = "Title";
2272 : ucbhelper::cancelCommandExecution(
2273 : uno::makeAny( ucb::MissingPropertiesException(
2274 : OUString(),
2275 : static_cast< cppu::OWeakObject * >( this ),
2276 : aProps ) ),
2277 0 : Environment );
2278 : // Unreachable
2279 : }
2280 :
2281 0 : if ( !bReplaceExisting )
2282 : {
2283 : /* [RFC 2616] - HTTP
2284 :
2285 : The PUT method requests that the enclosed entity be stored under the
2286 : supplied Request-URI. If the Request-URI refers to an already
2287 : existing resource, the enclosed entity SHOULD be considered as a
2288 : modified version of the one residing on the origin server.
2289 : */
2290 :
2291 : /* [RFC 2518] - WebDAV
2292 :
2293 : MKCOL creates a new collection resource at the location specified by
2294 : the Request-URI. If the resource identified by the Request-URI is
2295 : non-null then the MKCOL MUST fail.
2296 : */
2297 :
2298 : // ==> Complain on PUT, continue on MKCOL.
2299 0 : if ( !bTransient || ( bTransient && !bCollection ) )
2300 : {
2301 : ucb::UnsupportedNameClashException aEx(
2302 : OUString( "Unable to write without overwrite!" ),
2303 : static_cast< cppu::OWeakObject * >( this ),
2304 0 : ucb::NameClash::ERROR );
2305 :
2306 0 : uno::Reference< task::XInteractionHandler > xIH;
2307 :
2308 0 : if ( Environment.is() )
2309 0 : xIH = Environment->getInteractionHandler();
2310 :
2311 0 : if ( xIH.is() )
2312 : {
2313 0 : uno::Any aExAsAny( uno::makeAny( aEx ) );
2314 :
2315 : rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest
2316 : = new ucbhelper::SimpleInteractionRequest(
2317 : aExAsAny,
2318 : ucbhelper::CONTINUATION_APPROVE
2319 0 : | ucbhelper::CONTINUATION_DISAPPROVE );
2320 0 : xIH->handle( xRequest.get() );
2321 :
2322 0 : const sal_Int32 nResp = xRequest->getResponse();
2323 :
2324 0 : switch ( nResp )
2325 : {
2326 : case ucbhelper::CONTINUATION_UNKNOWN:
2327 : // Not handled; throw.
2328 0 : throw aEx;
2329 : // break;
2330 :
2331 : case ucbhelper::CONTINUATION_APPROVE:
2332 : // Continue -> Overwrite.
2333 0 : bReplaceExisting = true;
2334 0 : break;
2335 :
2336 : case ucbhelper::CONTINUATION_DISAPPROVE:
2337 : // Abort.
2338 : throw ucb::CommandFailedException(
2339 : OUString(),
2340 : uno::Reference< uno::XInterface >(),
2341 0 : aExAsAny );
2342 : // break;
2343 :
2344 : default:
2345 : OSL_FAIL( "Content::insert - "
2346 : "Unknown interaction selection!" );
2347 : throw ucb::CommandFailedException(
2348 : OUString( "Unknown interaction selection!" ),
2349 : uno::Reference< uno::XInterface >(),
2350 0 : aExAsAny );
2351 : // break;
2352 0 : }
2353 : }
2354 : else
2355 : {
2356 : // No IH; throw.
2357 0 : throw aEx;
2358 0 : }
2359 : }
2360 : }
2361 :
2362 0 : if ( bTransient )
2363 : {
2364 : // Assemble new content identifier...
2365 0 : OUString aURL = getParentURL();
2366 0 : if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) )
2367 0 : aURL += "/";
2368 :
2369 0 : aURL += aEscapedTitle;
2370 :
2371 : try
2372 : {
2373 0 : xResAccess->setURL( aURL );
2374 :
2375 0 : if ( bCollection )
2376 0 : xResAccess->MKCOL( Environment );
2377 : else
2378 0 : xResAccess->PUT( xInputStream, Environment );
2379 : }
2380 0 : catch ( DAVException const & except )
2381 : {
2382 0 : if ( bCollection )
2383 : {
2384 0 : if ( except.getStatus() == SC_METHOD_NOT_ALLOWED )
2385 : {
2386 : // [RFC 2518] - WebDAV
2387 : // 405 (Method Not Allowed) - MKCOL can only be
2388 : // executed on a deleted/non-existent resource.
2389 :
2390 0 : if ( bReplaceExisting )
2391 : {
2392 : // Destroy old resource.
2393 : try
2394 : {
2395 0 : xResAccess->DESTROY( Environment );
2396 : }
2397 0 : catch ( DAVException const & e )
2398 : {
2399 0 : cancelCommandExecution( e, Environment, true );
2400 : // Unreachable
2401 : }
2402 :
2403 : // Insert (recursion!).
2404 0 : insert( xInputStream, bReplaceExisting, Environment );
2405 :
2406 : {
2407 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2408 : m_xResAccess.reset(
2409 0 : new DAVResourceAccess( *xResAccess.get() ) );
2410 : }
2411 :
2412 : // Success!
2413 0 : return;
2414 : }
2415 : else
2416 : {
2417 0 : OUString aTitle;
2418 : try
2419 : {
2420 0 : NeonUri aURI( aURL );
2421 0 : aTitle = aURI.GetPathBaseNameUnescaped();
2422 : }
2423 0 : catch ( DAVException const & )
2424 : {
2425 : }
2426 :
2427 : ucbhelper::cancelCommandExecution(
2428 : uno::makeAny(
2429 : ucb::NameClashException(
2430 : OUString(),
2431 : static_cast< cppu::OWeakObject * >( this ),
2432 : task::InteractionClassification_ERROR,
2433 : aTitle ) ),
2434 0 : Environment );
2435 : // Unreachable
2436 : }
2437 : }
2438 : }
2439 :
2440 0 : cancelCommandExecution( except, Environment, true );
2441 : // Unreachable
2442 0 : }
2443 :
2444 : {
2445 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2446 0 : m_xIdentifier = new ::ucbhelper::ContentIdentifier( aURL );
2447 : }
2448 :
2449 0 : inserted();
2450 :
2451 : {
2452 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2453 0 : m_bTransient = false;
2454 0 : }
2455 : }
2456 : else
2457 : {
2458 0 : if ( !xInputStream.is() )
2459 : {
2460 : ucbhelper::cancelCommandExecution(
2461 : uno::makeAny(
2462 : ucb::MissingInputStreamException(
2463 : OUString(),
2464 : static_cast< cppu::OWeakObject * >( this ) ) ),
2465 0 : Environment );
2466 : // Unreachable
2467 : }
2468 :
2469 : try
2470 : {
2471 0 : xResAccess->PUT( xInputStream, Environment );
2472 : }
2473 0 : catch ( DAVException const & e )
2474 : {
2475 0 : cancelCommandExecution( e, Environment, true );
2476 : // Unreachable
2477 : }
2478 : }
2479 :
2480 : {
2481 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2482 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
2483 0 : }
2484 : }
2485 :
2486 :
2487 0 : void Content::transfer(
2488 : const ucb::TransferInfo & rArgs,
2489 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
2490 : throw( uno::Exception )
2491 : {
2492 0 : uno::Reference< ucb::XContentIdentifier > xIdentifier;
2493 0 : uno::Reference< ucb::XContentProvider > xProvider;
2494 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2495 :
2496 : {
2497 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2498 :
2499 0 : xIdentifier.set( m_xIdentifier );
2500 0 : xProvider.set( m_xProvider.get() );
2501 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
2502 : }
2503 :
2504 0 : OUString aTargetURI;
2505 : try
2506 : {
2507 0 : NeonUri sourceURI( rArgs.SourceURL );
2508 0 : NeonUri targetURI( xIdentifier->getContentIdentifier() );
2509 0 : aTargetURI = targetURI.GetPathBaseNameUnescaped();
2510 :
2511 : // Check source's and target's URL scheme
2512 :
2513 0 : const OUString aScheme = sourceURI.GetScheme().toAsciiLowerCase();
2514 0 : if ( aScheme == WEBDAV_URL_SCHEME )
2515 : {
2516 : sourceURI.SetScheme(
2517 0 : OUString( HTTP_URL_SCHEME ) );
2518 : }
2519 0 : else if ( aScheme == DAV_URL_SCHEME )
2520 : {
2521 : sourceURI.SetScheme(
2522 0 : OUString( HTTP_URL_SCHEME ) );
2523 : }
2524 0 : else if ( aScheme == DAVS_URL_SCHEME )
2525 : {
2526 : sourceURI.SetScheme(
2527 0 : OUString( HTTPS_URL_SCHEME ) );
2528 : }
2529 : else
2530 : {
2531 0 : if ( aScheme != HTTP_URL_SCHEME && aScheme != HTTPS_URL_SCHEME )
2532 : {
2533 : ucbhelper::cancelCommandExecution(
2534 : uno::makeAny(
2535 : ucb::InteractiveBadTransferURLException(
2536 : OUString( "Unsupported URL scheme!" ),
2537 : static_cast< cppu::OWeakObject * >( this ) ) ),
2538 0 : Environment );
2539 : // Unreachable
2540 : }
2541 : }
2542 :
2543 0 : if ( targetURI.GetScheme().toAsciiLowerCase() == WEBDAV_URL_SCHEME )
2544 : targetURI.SetScheme(
2545 0 : OUString( HTTP_URL_SCHEME ) );
2546 0 : else if ( targetURI.GetScheme().toAsciiLowerCase() == DAV_URL_SCHEME )
2547 : targetURI.SetScheme(
2548 0 : OUString( HTTP_URL_SCHEME ) );
2549 :
2550 : // @@@ This implementation of 'transfer' only works
2551 : // if the source and target are located at same host.
2552 : // (Neon does not support cross-server copy/move)
2553 :
2554 : // Check for same host
2555 :
2556 0 : if ( !sourceURI.GetHost().isEmpty() &&
2557 0 : ( sourceURI.GetHost() != targetURI.GetHost() ) )
2558 : {
2559 : ucbhelper::cancelCommandExecution(
2560 : uno::makeAny( ucb::InteractiveBadTransferURLException(
2561 : OUString( "Different hosts!" ),
2562 : static_cast< cppu::OWeakObject * >( this ) ) ),
2563 0 : Environment );
2564 : // Unreachable
2565 : }
2566 :
2567 0 : OUString aTitle = rArgs.NewTitle;
2568 :
2569 0 : if ( aTitle.isEmpty() )
2570 0 : aTitle = sourceURI.GetPathBaseNameUnescaped();
2571 :
2572 0 : if ( aTitle == "/" )
2573 : {
2574 : // kso: ???
2575 0 : aTitle = "";
2576 : }
2577 :
2578 0 : targetURI.AppendPath( aTitle );
2579 :
2580 0 : OUString aTargetURL = xIdentifier->getContentIdentifier();
2581 0 : if ( ( aTargetURL.lastIndexOf( '/' ) + 1 )
2582 0 : != aTargetURL.getLength() )
2583 0 : aTargetURL += "/";
2584 :
2585 0 : aTargetURL += aTitle;
2586 :
2587 : uno::Reference< ucb::XContentIdentifier > xTargetId
2588 0 : = new ::ucbhelper::ContentIdentifier( aTargetURL );
2589 :
2590 : DAVResourceAccess aSourceAccess( m_xContext,
2591 : xResAccess->getSessionFactory(),
2592 0 : sourceURI.GetURI() );
2593 :
2594 0 : if ( rArgs.MoveData == sal_True )
2595 : {
2596 : uno::Reference< ucb::XContentIdentifier > xId
2597 0 : = new ::ucbhelper::ContentIdentifier( rArgs.SourceURL );
2598 :
2599 : // Note: The static cast is okay here, because its sure that
2600 : // xProvider is always the WebDAVContentProvider.
2601 : rtl::Reference< Content > xSource
2602 : = static_cast< Content * >(
2603 0 : xProvider->queryContent( xId ).get() );
2604 :
2605 : // [RFC 2518] - WebDAV
2606 : // If a resource exists at the destination and the Overwrite
2607 : // header is "T" then prior to performing the move the server
2608 : // MUST perform a DELETE with "Depth: infinity" on the
2609 : // destination resource. If the Overwrite header is set to
2610 : // "F" then the operation will fail.
2611 :
2612 0 : aSourceAccess.MOVE( sourceURI.GetPath(),
2613 0 : targetURI.GetURI(),
2614 : rArgs.NameClash
2615 : == ucb::NameClash::OVERWRITE,
2616 0 : Environment );
2617 :
2618 0 : if ( xSource.is() )
2619 : {
2620 : // Propagate destruction to listeners.
2621 0 : xSource->destroy( true );
2622 0 : }
2623 :
2624 : // DAV resources store all additional props on server!
2625 : // // Rename own and all children's Additional Core Properties.
2626 : // renameAdditionalPropertySet( xId->getContentIdentifier(),
2627 : // xTargetId->getContentIdentifier(),
2628 : // sal_True );
2629 : }
2630 : else
2631 : {
2632 : // [RFC 2518] - WebDAV
2633 : // If a resource exists at the destination and the Overwrite
2634 : // header is "T" then prior to performing the copy the server
2635 : // MUST perform a DELETE with "Depth: infinity" on the
2636 : // destination resource. If the Overwrite header is set to
2637 : // "F" then the operation will fail.
2638 :
2639 0 : aSourceAccess.COPY( sourceURI.GetPath(),
2640 0 : targetURI.GetURI(),
2641 : rArgs.NameClash
2642 : == ucb::NameClash::OVERWRITE,
2643 0 : Environment );
2644 :
2645 : // DAV resources store all additional props on server!
2646 : // // Copy own and all children's Additional Core Properties.
2647 : // copyAdditionalPropertySet( xId->getContentIdentifier(),
2648 : // xTargetId->getContentIdentifier(),
2649 : // sal_True );
2650 : }
2651 :
2652 : // Note: The static cast is okay here, because its sure that
2653 : // xProvider is always the WebDAVContentProvider.
2654 : rtl::Reference< Content > xTarget
2655 : = static_cast< Content * >(
2656 0 : xProvider->queryContent( xTargetId ).get() );
2657 :
2658 : // Announce transferred content in its new folder.
2659 0 : xTarget->inserted();
2660 : }
2661 0 : catch ( ucb::IllegalIdentifierException const & )
2662 : {
2663 : // queryContent
2664 : }
2665 0 : catch ( DAVException const & e )
2666 : {
2667 : // [RFC 2518] - WebDAV
2668 : // 412 (Precondition Failed) - The server was unable to maintain
2669 : // the liveness of the properties listed in the propertybehavior
2670 : // XML element or the Overwrite header is "F" and the state of
2671 : // the destination resource is non-null.
2672 :
2673 0 : if ( e.getStatus() == SC_PRECONDITION_FAILED )
2674 : {
2675 0 : switch ( rArgs.NameClash )
2676 : {
2677 : case ucb::NameClash::ERROR:
2678 : {
2679 : ucbhelper::cancelCommandExecution(
2680 : uno::makeAny(
2681 : ucb::NameClashException(
2682 : OUString(),
2683 : static_cast< cppu::OWeakObject * >( this ),
2684 : task::InteractionClassification_ERROR,
2685 : aTargetURI ) ),
2686 0 : Environment );
2687 : // Unreachable
2688 : }
2689 :
2690 : case ucb::NameClash::OVERWRITE:
2691 0 : break;
2692 :
2693 : case ucb::NameClash::KEEP: // deprecated
2694 : case ucb::NameClash::RENAME:
2695 : case ucb::NameClash::ASK:
2696 : default:
2697 : {
2698 : ucbhelper::cancelCommandExecution(
2699 : uno::makeAny(
2700 : ucb::UnsupportedNameClashException(
2701 : OUString(),
2702 : static_cast< cppu::OWeakObject * >( this ),
2703 : rArgs.NameClash ) ),
2704 0 : Environment );
2705 : // Unreachable
2706 : }
2707 : }
2708 : }
2709 :
2710 0 : cancelCommandExecution( e, Environment, true );
2711 : // Unreachable
2712 : }
2713 :
2714 : {
2715 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2716 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
2717 0 : }
2718 0 : }
2719 :
2720 :
2721 0 : void Content::destroy( bool bDeletePhysical )
2722 : throw( uno::Exception )
2723 : {
2724 : // @@@ take care about bDeletePhysical -> trashcan support
2725 0 : uno::Reference< ucb::XContent > xThis = this;
2726 :
2727 0 : deleted();
2728 :
2729 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2730 :
2731 : // Process instantiated children...
2732 :
2733 0 : ::webdav_ucp::Content::ContentRefList aChildren;
2734 0 : queryChildren( aChildren );
2735 :
2736 0 : ContentRefList::const_iterator it = aChildren.begin();
2737 0 : ContentRefList::const_iterator end = aChildren.end();
2738 :
2739 0 : while ( it != end )
2740 : {
2741 0 : (*it)->destroy( bDeletePhysical );
2742 0 : ++it;
2743 0 : }
2744 0 : }
2745 :
2746 :
2747 0 : bool Content::supportsExclusiveWriteLock(
2748 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
2749 : {
2750 0 : if ( getResourceType( Environment ) == DAV )
2751 : {
2752 0 : if ( m_xCachedProps.get() )
2753 : {
2754 0 : uno::Sequence< ucb::LockEntry > aSupportedLocks;
2755 0 : if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK )
2756 : >>= aSupportedLocks )
2757 : {
2758 0 : for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n )
2759 : {
2760 0 : if ( aSupportedLocks[ n ].Scope
2761 0 : == ucb::LockScope_EXCLUSIVE &&
2762 0 : aSupportedLocks[ n ].Type
2763 0 : == ucb::LockType_WRITE )
2764 0 : return true;
2765 : }
2766 0 : }
2767 : }
2768 : }
2769 0 : return false;
2770 : }
2771 :
2772 :
2773 0 : void Content::lock(
2774 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
2775 : throw( uno::Exception )
2776 : {
2777 : try
2778 : {
2779 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2780 : {
2781 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2782 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
2783 : }
2784 :
2785 0 : uno::Any aOwnerAny;
2786 : aOwnerAny
2787 0 : <<= OUString("http://ucb.openoffice.org");
2788 :
2789 : ucb::Lock aLock(
2790 : ucb::LockScope_EXCLUSIVE,
2791 : ucb::LockType_WRITE,
2792 : ucb::LockDepth_ZERO,
2793 : aOwnerAny,
2794 : 180, // lock timeout in secs
2795 : //-1, // infinite lock
2796 0 : uno::Sequence< OUString >() );
2797 :
2798 0 : xResAccess->LOCK( aLock, Environment );
2799 0 : m_bLocked = true;
2800 :
2801 : {
2802 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2803 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
2804 0 : }
2805 : }
2806 0 : catch ( DAVException const & e )
2807 : {
2808 0 : cancelCommandExecution( e, Environment, false );
2809 : // Unreachable
2810 : }
2811 0 : }
2812 :
2813 :
2814 0 : void Content::unlock(
2815 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
2816 : throw( uno::Exception )
2817 : {
2818 : try
2819 : {
2820 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
2821 : {
2822 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2823 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
2824 : }
2825 :
2826 0 : xResAccess->UNLOCK( Environment );
2827 0 : m_bLocked = false;
2828 :
2829 : {
2830 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2831 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
2832 0 : }
2833 : }
2834 0 : catch ( DAVException const & e )
2835 : {
2836 0 : cancelCommandExecution( e, Environment, false );
2837 : // Unreachable
2838 : }
2839 0 : }
2840 :
2841 :
2842 0 : bool Content::exchangeIdentity(
2843 : const uno::Reference< ucb::XContentIdentifier >& xNewId )
2844 : {
2845 0 : if ( !xNewId.is() )
2846 0 : return false;
2847 :
2848 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
2849 :
2850 0 : uno::Reference< ucb::XContent > xThis = this;
2851 :
2852 : // Already persistent?
2853 0 : if ( m_bTransient )
2854 : {
2855 : OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
2856 0 : return false;
2857 : }
2858 :
2859 : // Exchange own identitity.
2860 :
2861 : // Fail, if a content with given id already exists.
2862 : // if ( !hasData( xNewId ) )
2863 : {
2864 0 : OUString aOldURL = m_xIdentifier->getContentIdentifier();
2865 :
2866 0 : aGuard.clear();
2867 0 : if ( exchange( xNewId ) )
2868 : {
2869 : // Process instantiated children...
2870 :
2871 0 : ContentRefList aChildren;
2872 0 : queryChildren( aChildren );
2873 :
2874 0 : ContentRefList::const_iterator it = aChildren.begin();
2875 0 : ContentRefList::const_iterator end = aChildren.end();
2876 :
2877 0 : while ( it != end )
2878 : {
2879 0 : ContentRef xChild = (*it);
2880 :
2881 : // Create new content identifier for the child...
2882 : uno::Reference< ucb::XContentIdentifier >
2883 0 : xOldChildId = xChild->getIdentifier();
2884 : OUString aOldChildURL
2885 0 : = xOldChildId->getContentIdentifier();
2886 : OUString aNewChildURL
2887 : = aOldChildURL.replaceAt(
2888 : 0,
2889 : aOldURL.getLength(),
2890 0 : xNewId->getContentIdentifier() );
2891 : uno::Reference< ucb::XContentIdentifier > xNewChildId
2892 0 : = new ::ucbhelper::ContentIdentifier( aNewChildURL );
2893 :
2894 0 : if ( !xChild->exchangeIdentity( xNewChildId ) )
2895 0 : return false;
2896 :
2897 0 : ++it;
2898 0 : }
2899 0 : return true;
2900 0 : }
2901 : }
2902 :
2903 : OSL_FAIL( "Content::exchangeIdentity - "
2904 : "Panic! Cannot exchange identity!" );
2905 0 : return false;
2906 : }
2907 :
2908 :
2909 0 : bool Content::isFolder(
2910 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
2911 : throw( uno::Exception, std::exception )
2912 : {
2913 : {
2914 0 : osl::MutexGuard aGuard( m_aMutex );
2915 :
2916 0 : if ( m_bTransient )
2917 0 : return m_bCollection;
2918 : }
2919 :
2920 0 : uno::Sequence< beans::Property > aProperties( 1 );
2921 0 : aProperties[ 0 ].Name = "IsFolder";
2922 0 : aProperties[ 0 ].Handle = -1;
2923 0 : uno::Reference< sdbc::XRow > xRow( getPropertyValues( aProperties, xEnv ) );
2924 0 : if ( xRow.is() )
2925 : {
2926 : try
2927 : {
2928 0 : return xRow->getBoolean( 1 );
2929 : }
2930 0 : catch ( sdbc::SQLException const & )
2931 : {
2932 : }
2933 : }
2934 :
2935 0 : return false;
2936 : }
2937 :
2938 :
2939 0 : uno::Any Content::MapDAVException( const DAVException & e, bool bWrite )
2940 : {
2941 : // Map DAVException...
2942 0 : uno::Any aException;
2943 :
2944 0 : OUString aURL;
2945 0 : if ( m_bTransient )
2946 : {
2947 0 : aURL = getParentURL();
2948 0 : if ( aURL.lastIndexOf('/') != ( aURL.getLength() - 1 ) )
2949 0 : aURL += "/";
2950 :
2951 0 : aURL += m_aEscapedTitle;
2952 : }
2953 : else
2954 : {
2955 0 : aURL = m_xIdentifier->getContentIdentifier();
2956 : }
2957 :
2958 0 : switch ( e.getStatus() )
2959 : {
2960 : case SC_NOT_FOUND:
2961 : {
2962 0 : uno::Sequence< uno::Any > aArgs( 1 );
2963 0 : aArgs[ 0 ] <<= beans::PropertyValue(
2964 : OUString("Uri"), -1,
2965 : uno::makeAny(aURL),
2966 0 : beans::PropertyState_DIRECT_VALUE);
2967 :
2968 0 : aException <<=
2969 : ucb::InteractiveAugmentedIOException(
2970 : OUString("Not found!"),
2971 : static_cast< cppu::OWeakObject * >( this ),
2972 : task::InteractionClassification_ERROR,
2973 : ucb::IOErrorCode_NOT_EXISTING,
2974 0 : aArgs );
2975 0 : return aException;
2976 : }
2977 : default:
2978 0 : break;
2979 : }
2980 :
2981 0 : switch ( e.getError() )
2982 : {
2983 : case DAVException::DAV_HTTP_ERROR:
2984 : {
2985 0 : if ( bWrite )
2986 0 : aException <<=
2987 : ucb::InteractiveNetworkWriteException(
2988 0 : e.getData(),
2989 : static_cast< cppu::OWeakObject * >( this ),
2990 : task::InteractionClassification_ERROR,
2991 0 : e.getData() );
2992 : else
2993 0 : aException <<=
2994 : ucb::InteractiveNetworkReadException(
2995 0 : e.getData(),
2996 : static_cast< cppu::OWeakObject * >( this ),
2997 : task::InteractionClassification_ERROR,
2998 0 : e.getData() );
2999 0 : break;
3000 : }
3001 :
3002 : case DAVException::DAV_HTTP_LOOKUP:
3003 0 : aException <<=
3004 : ucb::InteractiveNetworkResolveNameException(
3005 : OUString(),
3006 : static_cast< cppu::OWeakObject * >( this ),
3007 : task::InteractionClassification_ERROR,
3008 0 : e.getData() );
3009 0 : break;
3010 :
3011 : // @@@ No matching InteractiveNetwork*Exception
3012 : // case DAVException::DAV_HTTP_AUTH:
3013 : // break;
3014 :
3015 : // @@@ No matching InteractiveNetwork*Exception
3016 : // case DAVException::DAV_HTTP_AUTHPROXY:
3017 : // break;
3018 :
3019 : case DAVException::DAV_HTTP_CONNECT:
3020 0 : aException <<=
3021 : ucb::InteractiveNetworkConnectException(
3022 : OUString(),
3023 : static_cast< cppu::OWeakObject * >( this ),
3024 : task::InteractionClassification_ERROR,
3025 0 : e.getData() );
3026 0 : break;
3027 :
3028 : // @@@ No matching InteractiveNetwork*Exception
3029 : // case DAVException::DAV_HTTP_TIMEOUT:
3030 : // break;
3031 :
3032 : // @@@ No matching InteractiveNetwork*Exception
3033 : // case DAVException::DAV_HTTP_REDIRECT:
3034 : // break;
3035 :
3036 : // @@@ No matching InteractiveNetwork*Exception
3037 : // case DAVException::DAV_SESSION_CREATE:
3038 : // break;
3039 :
3040 : case DAVException::DAV_INVALID_ARG:
3041 0 : aException <<=
3042 : lang::IllegalArgumentException(
3043 : OUString(),
3044 : static_cast< cppu::OWeakObject * >( this ),
3045 0 : -1 );
3046 0 : break;
3047 :
3048 : case DAVException::DAV_LOCKED:
3049 0 : aException <<=
3050 : ucb::InteractiveLockingLockedException(
3051 : OUString("Locked!"),
3052 : static_cast< cppu::OWeakObject * >( this ),
3053 : task::InteractionClassification_ERROR,
3054 : aURL,
3055 0 : sal_False ); // not SelfOwned
3056 0 : break;
3057 :
3058 : case DAVException::DAV_LOCKED_SELF:
3059 0 : aException <<=
3060 : ucb::InteractiveLockingLockedException(
3061 : OUString("Locked (self!)"),
3062 : static_cast< cppu::OWeakObject * >( this ),
3063 : task::InteractionClassification_ERROR,
3064 : aURL,
3065 0 : sal_True ); // SelfOwned
3066 0 : break;
3067 :
3068 : case DAVException::DAV_NOT_LOCKED:
3069 0 : aException <<=
3070 : ucb::InteractiveLockingNotLockedException(
3071 : OUString("Not locked!"),
3072 : static_cast< cppu::OWeakObject * >( this ),
3073 : task::InteractionClassification_ERROR,
3074 0 : aURL );
3075 0 : break;
3076 :
3077 : case DAVException::DAV_LOCK_EXPIRED:
3078 0 : aException <<=
3079 : ucb::InteractiveLockingLockExpiredException(
3080 : OUString("Lock expired!"),
3081 : static_cast< cppu::OWeakObject * >( this ),
3082 : task::InteractionClassification_ERROR,
3083 0 : aURL );
3084 0 : break;
3085 :
3086 : default:
3087 0 : aException <<=
3088 : ucb::InteractiveNetworkGeneralException(
3089 : OUString(),
3090 : static_cast< cppu::OWeakObject * >( this ),
3091 0 : task::InteractionClassification_ERROR );
3092 0 : break;
3093 : }
3094 :
3095 0 : return aException;
3096 : }
3097 :
3098 :
3099 : // static
3100 0 : bool Content::shouldAccessNetworkAfterException( const DAVException & e )
3101 : {
3102 0 : if ( ( e.getStatus() == SC_NOT_FOUND ) ||
3103 0 : ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) ||
3104 0 : ( e.getError() == DAVException::DAV_HTTP_CONNECT ) ||
3105 0 : ( e.getError() == DAVException::DAV_HTTP_AUTH ) ||
3106 0 : ( e.getError() == DAVException::DAV_HTTP_AUTHPROXY ) )
3107 0 : return false;
3108 :
3109 0 : return true;
3110 : }
3111 :
3112 :
3113 0 : void Content::cancelCommandExecution(
3114 : const DAVException & e,
3115 : const uno::Reference< ucb::XCommandEnvironment > & xEnv,
3116 : bool bWrite /* = sal_False */ )
3117 : throw ( uno::Exception )
3118 : {
3119 0 : ucbhelper::cancelCommandExecution( MapDAVException( e, bWrite ), xEnv );
3120 : // Unreachable
3121 0 : }
3122 :
3123 :
3124 : const OUString
3125 0 : Content::getBaseURI( const std::unique_ptr< DAVResourceAccess > & rResAccess )
3126 : {
3127 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
3128 :
3129 : // First, try to obtain value of response header "Content-Location".
3130 0 : if ( m_xCachedProps.get() )
3131 : {
3132 0 : OUString aLocation;
3133 0 : m_xCachedProps->getValue( OUString( "Content-Location" ) ) >>= aLocation;
3134 0 : if ( !aLocation.isEmpty() )
3135 : {
3136 : try
3137 : {
3138 : // Do not use m_xIdentifier->getContentIdentifier() because it
3139 : // for example does not reflect redirects applied to requests
3140 : // done using the original URI but m_xResAccess' URI does.
3141 0 : return rtl::Uri::convertRelToAbs( rResAccess->getURL(),
3142 0 : aLocation );
3143 : }
3144 0 : catch ( rtl::MalformedUriException const & )
3145 : {
3146 : }
3147 0 : }
3148 : }
3149 :
3150 0 : return OUString( rResAccess->getURL() );
3151 : }
3152 :
3153 :
3154 0 : Content::ResourceType Content::getResourceType(
3155 : const uno::Reference< ucb::XCommandEnvironment >& xEnv,
3156 : const std::unique_ptr< DAVResourceAccess > & rResAccess,
3157 : bool * networkAccessAllowed)
3158 : throw ( uno::Exception, std::exception )
3159 : {
3160 : {
3161 0 : osl::MutexGuard g(m_aMutex);
3162 0 : if (m_eResourceType != UNKNOWN) {
3163 0 : return m_eResourceType;
3164 0 : }
3165 : }
3166 :
3167 0 : ResourceType eResourceType = UNKNOWN;
3168 :
3169 0 : const OUString & rURL = rResAccess->getURL();
3170 : const OUString aScheme(
3171 0 : rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() );
3172 :
3173 0 : if ( aScheme == FTP_URL_SCHEME )
3174 : {
3175 0 : eResourceType = FTP;
3176 : }
3177 : else
3178 : {
3179 : try
3180 : {
3181 : // Try to fetch some frequently used property value, e.g. those
3182 : // used when loading documents... along with identifying whether
3183 : // this is a DAV resource.
3184 0 : std::vector< DAVResource > resources;
3185 0 : std::vector< OUString > aPropNames;
3186 0 : uno::Sequence< beans::Property > aProperties( 5 );
3187 0 : aProperties[ 0 ].Name = "IsFolder";
3188 0 : aProperties[ 1 ].Name = "IsDocument";
3189 0 : aProperties[ 2 ].Name = "IsReadOnly";
3190 0 : aProperties[ 3 ].Name = "MediaType";
3191 0 : aProperties[ 4 ].Name = DAVProperties::SUPPORTEDLOCK;
3192 :
3193 0 : ContentProperties::UCBNamesToDAVNames( aProperties, aPropNames );
3194 :
3195 0 : rResAccess->PROPFIND( DAVZERO, aPropNames, resources, xEnv );
3196 :
3197 0 : if ( resources.size() == 1 )
3198 : {
3199 0 : osl::MutexGuard g(m_aMutex);
3200 : m_xCachedProps.reset(
3201 0 : new CachableContentProperties( resources[ 0 ] ) );
3202 : m_xCachedProps->containsAllNames(
3203 0 : aProperties, m_aFailedPropNames );
3204 : }
3205 :
3206 0 : eResourceType = DAV;
3207 : }
3208 0 : catch ( DAVException const & e )
3209 : {
3210 0 : rResAccess->resetUri();
3211 :
3212 0 : if ( e.getStatus() == SC_METHOD_NOT_ALLOWED )
3213 : {
3214 : // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
3215 : // resource is NON_DAV
3216 0 : eResourceType = NON_DAV;
3217 : }
3218 0 : else if (networkAccessAllowed != 0)
3219 : {
3220 : *networkAccessAllowed = *networkAccessAllowed
3221 0 : && shouldAccessNetworkAfterException(e);
3222 : }
3223 : }
3224 : }
3225 :
3226 0 : osl::MutexGuard g(m_aMutex);
3227 0 : if (m_eResourceType == UNKNOWN) {
3228 0 : m_eResourceType = eResourceType;
3229 : } else {
3230 : SAL_WARN_IF(
3231 : eResourceType != m_eResourceType, "ucb.ucp.webdav",
3232 : "different resource types for <" << rURL << ">: "
3233 : << +eResourceType << " vs. " << +m_eResourceType);
3234 : }
3235 0 : return m_eResourceType;
3236 : }
3237 :
3238 :
3239 0 : Content::ResourceType Content::getResourceType(
3240 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
3241 : throw ( uno::Exception, std::exception )
3242 : {
3243 0 : std::unique_ptr< DAVResourceAccess > xResAccess;
3244 : {
3245 0 : osl::MutexGuard aGuard( m_aMutex );
3246 0 : xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
3247 : }
3248 0 : Content::ResourceType const ret = getResourceType( xEnv, xResAccess );
3249 : {
3250 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
3251 0 : m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
3252 : }
3253 0 : return ret;
3254 : }
3255 :
3256 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|