update dev300-m58
[ooovba.git] / ucb / source / core / ucbcmds.cxx
blob0db14ca73fc45879fc0d6928c58989ba259cf39d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ucbcmds.cxx,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
35 TODO
36 **************************************************************************
38 *************************************************************************/
39 #include <osl/diagnose.h>
40 #include <cppuhelper/implbase1.hxx>
41 #include <cppuhelper/exc_hlp.hxx>
42 #include <rtl/ustring.h>
43 #include <rtl/ustring.hxx>
44 #ifndef __COM_SUN_STAR_LANG_XINTERFACE_HPP_
45 #include <com/sun/star/uno/XInterface.hpp>
46 #endif
47 #include <com/sun/star/beans/PropertyState.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/container/XChild.hpp>
50 #include <com/sun/star/beans/XPropertySetInfo.hpp>
51 #include <com/sun/star/io/XActiveDataSink.hpp>
52 #include <com/sun/star/io/XOutputStream.hpp>
53 #include <com/sun/star/io/XSeekable.hpp>
54 #include <com/sun/star/sdbc/XRow.hpp>
55 #include <com/sun/star/task/XInteractionHandler.hpp>
56 #include <com/sun/star/ucb/CommandFailedException.hpp>
57 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
58 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp>
59 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
60 #ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_
61 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
62 #endif
63 #include <com/sun/star/ucb/NameClash.hpp>
64 #include <com/sun/star/ucb/NameClashException.hpp>
65 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
66 #include <com/sun/star/ucb/OpenMode.hpp>
67 #include <com/sun/star/ucb/TransferInfo.hpp>
68 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
69 #include <com/sun/star/ucb/XCommandInfo.hpp>
70 #include <com/sun/star/ucb/XContentAccess.hpp>
71 #include <com/sun/star/ucb/XContentCreator.hpp>
72 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
73 #include <com/sun/star/uno/Any.hxx>
74 #include <com/sun/star/uno/Sequence.hxx>
75 #include <ucbhelper/cancelcommandexecution.hxx>
76 #include <ucbhelper/simplenameclashresolverequest.hxx>
77 #include "ucbcmds.hxx"
78 #include "ucb.hxx"
80 using namespace com::sun::star;
82 namespace ucb_commands
85 //=========================================================================
87 // struct TransferCommandContext.
89 //=========================================================================
91 struct TransferCommandContext
93 uno::Reference< lang::XMultiServiceFactory > xSMgr;
94 uno::Reference< ucb::XCommandProcessor > xProcessor;
95 uno::Reference< ucb::XCommandEnvironment > xEnv;
96 uno::Reference< ucb::XCommandEnvironment > xOrigEnv;
97 ucb::GlobalTransferCommandArgument aArg;
99 TransferCommandContext(
100 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr,
101 const uno::Reference< ucb::XCommandProcessor > & rxProcessor,
102 const uno::Reference< ucb::XCommandEnvironment > & rxEnv,
103 const uno::Reference< ucb::XCommandEnvironment > & rxOrigEnv,
104 const ucb::GlobalTransferCommandArgument & rArg )
105 : xSMgr( rxSMgr ), xProcessor( rxProcessor ), xEnv( rxEnv ),
106 xOrigEnv( rxOrigEnv ), aArg( rArg ) {}
109 //=========================================================================
111 // class InteractionHandlerProxy.
113 //=========================================================================
115 class InteractionHandlerProxy :
116 public cppu::WeakImplHelper1< task::XInteractionHandler >
118 uno::Reference< task::XInteractionHandler > m_xOrig;
120 public:
121 InteractionHandlerProxy(
122 const uno::Reference< task::XInteractionHandler > & xOrig )
123 : m_xOrig( xOrig ) {}
125 // XInteractionHandler methods.
126 virtual void SAL_CALL handle(
127 const uno::Reference< task::XInteractionRequest >& Request )
128 throw ( uno::RuntimeException );
131 //=========================================================================
132 // virtual
133 void SAL_CALL InteractionHandlerProxy::handle(
134 const uno::Reference< task::XInteractionRequest >& Request )
135 throw ( uno::RuntimeException )
137 if ( !m_xOrig.is() )
138 return;
140 // Filter unwanted requests by just not handling them.
141 uno::Any aRequest = Request->getRequest();
143 // "transfer"
144 ucb::InteractiveBadTransferURLException aBadTransferURLEx;
145 if ( aRequest >>= aBadTransferURLEx )
147 return;
149 else
151 // "transfer"
152 ucb::UnsupportedNameClashException aUnsupportedNameClashEx;
153 if ( aRequest >>= aUnsupportedNameClashEx )
155 if ( aUnsupportedNameClashEx.NameClash
156 != ucb::NameClash::ERROR )
157 return;
159 else
161 // "insert"
162 ucb::NameClashException aNameClashEx;
163 if ( aRequest >>= aNameClashEx )
165 return;
167 else
169 // "transfer"
170 ucb::UnsupportedCommandException aUnsupportedCommandEx;
171 if ( aRequest >>= aUnsupportedCommandEx )
173 return;
179 // not filtered; let the original handler do the work.
180 m_xOrig->handle( Request );
183 //=========================================================================
185 // class CommandEnvironment.
187 //=========================================================================
189 class CommandEnvironment :
190 public cppu::WeakImplHelper1< ucb::XCommandEnvironment >
192 uno::Reference< task::XInteractionHandler > m_xIH;
193 uno::Reference< ucb::XProgressHandler > m_xPH;
195 public:
196 CommandEnvironment(
197 const uno::Reference< task::XInteractionHandler > & xIH,
198 const uno::Reference< ucb::XProgressHandler > & xPH )
199 : m_xIH( xIH ), m_xPH( xPH ) {}
201 // XCommandEnvironment methods.
202 virtual uno::Reference< task::XInteractionHandler > SAL_CALL
203 getInteractionHandler()
204 throw ( uno::RuntimeException );
205 virtual uno::Reference< ucb::XProgressHandler > SAL_CALL
206 getProgressHandler()
207 throw ( uno::RuntimeException );
210 //=========================================================================
211 // virtual
212 uno::Reference< task::XInteractionHandler > SAL_CALL
213 CommandEnvironment::getInteractionHandler()
214 throw ( uno::RuntimeException )
216 return m_xIH;
219 //=========================================================================
220 // virtual
221 uno::Reference< ucb::XProgressHandler > SAL_CALL
222 CommandEnvironment::getProgressHandler()
223 throw ( uno::RuntimeException )
225 return m_xPH;
228 //=========================================================================
230 // class ActiveDataSink.
232 //=========================================================================
234 class ActiveDataSink : public cppu::WeakImplHelper1< io::XActiveDataSink >
236 uno::Reference< io::XInputStream > m_xStream;
238 public:
239 // XActiveDataSink methods.
240 virtual void SAL_CALL setInputStream(
241 const uno::Reference< io::XInputStream >& aStream )
242 throw( uno::RuntimeException );
243 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
244 throw( uno::RuntimeException );
247 //=========================================================================
248 // virtual
249 void SAL_CALL ActiveDataSink::setInputStream(
250 const uno::Reference< io::XInputStream >& aStream )
251 throw( uno::RuntimeException )
253 m_xStream = aStream;
256 //=========================================================================
257 // virtual
258 uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream()
259 throw( uno::RuntimeException )
261 return m_xStream;
264 //=========================================================================
266 // class CommandProcessorInfo.
268 //=========================================================================
270 class CommandProcessorInfo :
271 public cppu::WeakImplHelper1< ucb::XCommandInfo >
273 uno::Sequence< ucb::CommandInfo > * m_pInfo;
275 public:
276 CommandProcessorInfo();
277 virtual ~CommandProcessorInfo();
279 // XCommandInfo methods
280 virtual uno::Sequence< ucb::CommandInfo > SAL_CALL getCommands()
281 throw( uno::RuntimeException );
282 virtual ucb::CommandInfo SAL_CALL
283 getCommandInfoByName( const rtl::OUString& Name )
284 throw( ucb::UnsupportedCommandException, uno::RuntimeException );
285 virtual ucb::CommandInfo SAL_CALL
286 getCommandInfoByHandle( sal_Int32 Handle )
287 throw( ucb::UnsupportedCommandException, uno::RuntimeException );
288 virtual sal_Bool SAL_CALL hasCommandByName( const rtl::OUString& Name )
289 throw( uno::RuntimeException );
290 virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle )
291 throw( uno::RuntimeException );
294 //=========================================================================
295 CommandProcessorInfo::CommandProcessorInfo()
297 m_pInfo = new uno::Sequence< ucb::CommandInfo >( 2 );
299 (*m_pInfo)[ 0 ]
300 = ucb::CommandInfo(
301 rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME ), // Name
302 GETCOMMANDINFO_HANDLE, // Handle
303 getCppuVoidType() ); // ArgType
304 (*m_pInfo)[ 1 ]
305 = ucb::CommandInfo(
306 rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME ), // Name
307 GLOBALTRANSFER_HANDLE, // Handle
308 getCppuType(
309 static_cast<
310 ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType
313 //=========================================================================
314 // virtual
315 CommandProcessorInfo::~CommandProcessorInfo()
317 delete m_pInfo;
320 //=========================================================================
321 // virtual
322 uno::Sequence< ucb::CommandInfo > SAL_CALL
323 CommandProcessorInfo::getCommands()
324 throw( uno::RuntimeException )
326 return uno::Sequence< ucb::CommandInfo >( *m_pInfo );
329 //=========================================================================
330 // virtual
331 ucb::CommandInfo SAL_CALL
332 CommandProcessorInfo::getCommandInfoByName( const rtl::OUString& Name )
333 throw( ucb::UnsupportedCommandException, uno::RuntimeException )
335 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
337 if ( (*m_pInfo)[ n ].Name == Name )
338 return ucb::CommandInfo( (*m_pInfo)[ n ] );
341 throw ucb::UnsupportedCommandException();
344 //=========================================================================
345 // virtual
346 ucb::CommandInfo SAL_CALL
347 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle )
348 throw( ucb::UnsupportedCommandException, uno::RuntimeException )
350 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
352 if ( (*m_pInfo)[ n ].Handle == Handle )
353 return ucb::CommandInfo( (*m_pInfo)[ n ] );
356 throw ucb::UnsupportedCommandException();
359 //=========================================================================
360 // virtual
361 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName(
362 const rtl::OUString& Name )
363 throw( uno::RuntimeException )
365 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
367 if ( (*m_pInfo)[ n ].Name == Name )
368 return sal_True;
371 return sal_False;
374 //=========================================================================
375 // virtual
376 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle )
377 throw( uno::RuntimeException )
379 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
381 if ( (*m_pInfo)[ n ].Handle == Handle )
382 return sal_True;
385 return sal_False;
388 //=========================================================================
389 //=========================================================================
390 //=========================================================================
392 static rtl::OUString createDesiredName(
393 const rtl::OUString & rSourceURL, const rtl::OUString & rNewTitle )
395 rtl::OUString aName( rNewTitle );
396 if ( aName.getLength() == 0 )
398 // calculate name using source URL
400 // @@@ It's not guaranteed that slashes contained in the URL are
401 // actually path separators. This depends on the fact whether the
402 // URL is hierarchical. Only then the slashes are path separators.
403 // Therefore this algorithm is not guaranteed to work! But, ATM
404 // I don't know a better solution. It would have been better to
405 // have a member for the clashing name in
406 // UnsupportedNameClashException...
408 sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' );
409 bool bTrailingSlash = false;
410 if ( nLastSlash == rSourceURL.getLength() - 1 )
412 nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash );
413 bTrailingSlash = true;
416 if ( nLastSlash != -1 )
418 if ( bTrailingSlash )
419 aName = rSourceURL.copy(
420 nLastSlash + 1,
421 rSourceURL.getLength() - nLastSlash - 2 );
422 else
423 aName = rSourceURL.copy( nLastSlash + 1 );
425 else
427 aName = rSourceURL;
430 // query, fragment present?
431 sal_Int32 nPos = aName.indexOf( '?' );
432 if ( nPos == -1 )
433 nPos = aName.indexOf( '#' );
435 if ( nPos != -1 )
436 aName = aName.copy( 0, nPos );
438 return rtl::OUString( aName );
441 static rtl::OUString createDesiredName(
442 const ucb::GlobalTransferCommandArgument & rArg )
444 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
447 static rtl::OUString createDesiredName(
448 const ucb::TransferInfo & rArg )
450 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
453 //=========================================================================
454 enum NameClashContinuation { NOT_HANDLED, ABORT, OVERWRITE, NEW_NAME, UNKNOWN };
456 static NameClashContinuation interactiveNameClashResolve(
457 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
458 const rtl::OUString & rTargetURL,
459 const rtl::OUString & rClashingName,
460 /* [out] */ uno::Any & rException,
461 /* [out] */ rtl::OUString & rNewName )
463 rtl::Reference< ucbhelper::SimpleNameClashResolveRequest > xRequest(
464 new ucbhelper::SimpleNameClashResolveRequest(
465 rTargetURL, // target folder URL
466 rClashingName, // clashing name
467 rtl::OUString(), // no proposal for new name
468 sal_True /* bSupportsOverwriteData */ ) );
470 rException = xRequest->getRequest();
471 if ( xEnv.is() )
473 uno::Reference< task::XInteractionHandler > xIH
474 = xEnv->getInteractionHandler();
475 if ( xIH.is() )
478 xIH->handle( xRequest.get() );
480 rtl::Reference< ucbhelper::InteractionContinuation >
481 xSelection( xRequest->getSelection() );
483 if ( xSelection.is() )
485 // Handler handled the request.
486 uno::Reference< task::XInteractionAbort > xAbort(
487 xSelection.get(), uno::UNO_QUERY );
488 if ( xAbort.is() )
490 // Abort.
491 return ABORT;
493 else
495 uno::Reference<
496 ucb::XInteractionReplaceExistingData >
497 xReplace(
498 xSelection.get(), uno::UNO_QUERY );
499 if ( xReplace.is() )
501 // Try again: Replace existing data.
502 return OVERWRITE;
504 else
506 uno::Reference<
507 ucb::XInteractionSupplyName >
508 xSupplyName(
509 xSelection.get(), uno::UNO_QUERY );
510 if ( xSupplyName.is() )
512 // Try again: Use new name.
513 rNewName = xRequest->getNewName();
514 return NEW_NAME;
516 else
518 OSL_ENSURE( sal_False,
519 "Unknown interaction continuation!" );
520 return UNKNOWN;
527 return NOT_HANDLED;
530 //=========================================================================
531 static bool setTitle(
532 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessor,
533 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
534 const rtl::OUString & rNewTitle )
535 throw( uno::RuntimeException )
539 uno::Sequence< beans::PropertyValue > aPropValues( 1 );
540 aPropValues[ 0 ].Name
541 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
542 aPropValues[ 0 ].Handle = -1;
543 aPropValues[ 0 ].Value = uno::makeAny( rNewTitle );
545 ucb::Command aSetPropsCommand(
546 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
548 uno::makeAny( aPropValues ) );
550 uno::Any aResult
551 = xCommandProcessor->execute( aSetPropsCommand, 0, xEnv );
553 uno::Sequence< uno::Any > aErrors;
554 aResult >>= aErrors;
556 OSL_ENSURE( aErrors.getLength() == 1,
557 "getPropertyValues return value invalid!" );
559 if ( aErrors[ 0 ].hasValue() )
561 // error occured.
562 OSL_ENSURE( sal_False, "error setting Title property!" );
563 return false;
566 catch ( uno::RuntimeException const & )
568 throw;
570 catch ( uno::Exception const & )
572 return false;
575 return true;
578 //=========================================================================
579 static uno::Reference< ucb::XContent > createNew(
580 const TransferCommandContext & rContext,
581 const uno::Reference< ucb::XContent > & xTarget,
582 sal_Bool bSourceIsFolder,
583 sal_Bool bSourceIsDocument,
584 sal_Bool bSourceIsLink )
585 throw( uno::Exception )
587 //////////////////////////////////////////////////////////////////////
589 // (1) Obtain creatable types from target.
591 //////////////////////////////////////////////////////////////////////
593 uno::Reference< ucb::XContentCreator > xCreator(
594 xTarget, uno::UNO_QUERY );
596 if ( !xCreator.is() )
598 uno::Any aProps
599 = uno::makeAny(beans::PropertyValue(
600 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
601 "Folder")),
603 uno::makeAny(rContext.aArg.TargetURL),
604 beans::PropertyState_DIRECT_VALUE));
605 ucbhelper::cancelCommandExecution(
606 ucb::IOErrorCode_CANT_CREATE,
607 uno::Sequence< uno::Any >(&aProps, 1),
608 rContext.xOrigEnv,
609 rtl::OUString::createFromAscii( "Target is no XContentCreator!" ),
610 rContext.xProcessor );
611 // Unreachable
614 uno::Sequence< ucb::ContentInfo > aTypesInfo
615 = xCreator->queryCreatableContentsInfo();
617 sal_Int32 nCount = aTypesInfo.getLength();
618 if ( !nCount )
620 uno::Any aProps
621 = uno::makeAny(beans::PropertyValue(
622 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
623 "Folder")),
625 uno::makeAny(rContext.aArg.TargetURL),
626 beans::PropertyState_DIRECT_VALUE));
627 ucbhelper::cancelCommandExecution(
628 ucb::IOErrorCode_CANT_CREATE,
629 uno::Sequence< uno::Any >(&aProps, 1),
630 rContext.xOrigEnv,
631 rtl::OUString::createFromAscii( "No types creatable!" ),
632 rContext.xProcessor );
633 // Unreachable
636 //////////////////////////////////////////////////////////////////////
638 // (2) Try to find a matching target type for the source object.
640 //////////////////////////////////////////////////////////////////////
642 uno::Reference< ucb::XContent > xNew;
643 for ( sal_Int32 n = 0; n < nCount; ++n )
645 sal_Int32 nAttribs = aTypesInfo[ n ].Attributes;
646 sal_Bool bMatch = sal_False;
648 if ( rContext.aArg.Operation == ucb::TransferCommandOperation_LINK )
650 // Create link
652 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
654 // Match!
655 bMatch = sal_True;
658 else if ( ( rContext.aArg.Operation
659 == ucb::TransferCommandOperation_COPY ) ||
660 ( rContext.aArg.Operation
661 == ucb::TransferCommandOperation_MOVE ) )
663 // Copy / Move
665 // Is source a link? Create link in target folder then.
666 if ( bSourceIsLink )
668 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
670 // Match!
671 bMatch = sal_True;
674 else
676 // (not a and not b) or (a and b)
677 // not( a or b) or (a and b)
679 if ( ( !!bSourceIsFolder ==
680 !!( nAttribs
681 & ucb::ContentInfoAttribute::KIND_FOLDER ) )
683 ( !!bSourceIsDocument ==
684 !!( nAttribs
685 & ucb::ContentInfoAttribute::KIND_DOCUMENT ) )
688 // Match!
689 bMatch = sal_True;
693 else
695 ucbhelper::cancelCommandExecution(
696 uno::makeAny( lang::IllegalArgumentException(
697 rtl::OUString::createFromAscii(
698 "Unknown transfer operation!" ),
699 rContext.xProcessor,
700 -1 ) ),
701 rContext.xOrigEnv );
702 // Unreachable
705 if ( bMatch )
707 //////////////////////////////////////////////////////////////
709 // (3) Create a new, empty object of matched type.
711 //////////////////////////////////////////////////////////////
713 xNew = xCreator->createNewContent( aTypesInfo[ n ] );
715 if ( !xNew.is() )
717 uno::Any aProps
718 = uno::makeAny(
719 beans::PropertyValue(
720 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
721 "Folder")),
723 uno::makeAny(rContext.aArg.TargetURL),
724 beans::PropertyState_DIRECT_VALUE));
725 ucbhelper::cancelCommandExecution(
726 ucb::IOErrorCode_CANT_CREATE,
727 uno::Sequence< uno::Any >(&aProps, 1),
728 rContext.xOrigEnv,
729 rtl::OUString::createFromAscii(
730 "createNewContent failed!" ),
731 rContext.xProcessor );
732 // Unreachable
734 break; // escape from 'for' loop
736 } // for
738 return xNew;
741 //=========================================================================
742 static void transferProperties(
743 const TransferCommandContext & rContext,
744 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS,
745 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorN )
746 throw( uno::Exception )
748 ucb::Command aGetPropertySetInfoCommand(
749 rtl::OUString::createFromAscii( "getPropertySetInfo" ),
751 uno::Any() );
753 uno::Reference< beans::XPropertySetInfo > xInfo;
754 xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv )
755 >>= xInfo;
757 if ( !xInfo.is() )
759 uno::Any aProps
760 = uno::makeAny(beans::PropertyValue(
761 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
762 "Uri")),
764 uno::makeAny(rContext.aArg.SourceURL),
765 beans::PropertyState_DIRECT_VALUE));
766 ucbhelper::cancelCommandExecution(
767 ucb::IOErrorCode_CANT_READ,
768 uno::Sequence< uno::Any >(&aProps, 1),
769 rContext.xOrigEnv,
770 rtl::OUString::createFromAscii(
771 "Unable to get propertyset info from source object!" ),
772 rContext.xProcessor );
773 // Unreachable
776 uno::Sequence< beans::Property > aAllProps = xInfo->getProperties();
778 ucb::Command aGetPropsCommand1(
779 rtl::OUString::createFromAscii( "getPropertyValues" ),
781 uno::makeAny( aAllProps ) );
783 uno::Reference< sdbc::XRow > xRow1;
784 xCommandProcessorS->execute(
785 aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1;
787 if ( !xRow1.is() )
789 uno::Any aProps
790 = uno::makeAny(beans::PropertyValue(
791 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
792 "Uri")),
794 uno::makeAny(rContext.aArg.SourceURL),
795 beans::PropertyState_DIRECT_VALUE));
796 ucbhelper::cancelCommandExecution(
797 ucb::IOErrorCode_CANT_READ,
798 uno::Sequence< uno::Any >(&aProps, 1),
799 rContext.xOrigEnv,
800 rtl::OUString::createFromAscii(
801 "Unable to get properties from source object!" ),
802 rContext.xProcessor );
803 // Unreachable
806 // Assemble data structure for setPropertyValues command.
808 // Note: Make room for additional Title and TargetURL too. -> + 2
809 uno::Sequence< beans::PropertyValue > aPropValues(
810 aAllProps.getLength() + 2 );
812 sal_Bool bHasTitle = ( rContext.aArg.NewTitle.getLength() == 0 );
813 sal_Bool bHasTargetURL = ( rContext.aArg.Operation
814 != ucb::TransferCommandOperation_LINK );
816 sal_Int32 nWritePos = 0;
817 for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m )
819 const beans::Property & rCurrProp = aAllProps[ m ];
820 beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ];
822 uno::Any aValue;
824 if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 )
826 // Supply new title, if given.
827 if ( !bHasTitle )
829 bHasTitle = sal_True;
830 aValue <<= rContext.aArg.NewTitle;
833 else if ( rCurrProp.Name.compareToAscii( "TargetURL" ) == 0 )
835 // Supply source URL as link target for the new link to create.
836 if ( !bHasTargetURL )
838 bHasTargetURL = sal_True;
839 aValue <<= rContext.aArg.SourceURL;
843 if ( !aValue.hasValue() )
847 aValue = xRow1->getObject(
848 m + 1, uno::Reference< container::XNameAccess >() );
850 catch ( sdbc::SQLException const & )
852 // Argh! But try to bring things to an end. Perhaps the
853 // mad property is not really important...
857 if ( aValue.hasValue() )
859 rCurrValue.Name = rCurrProp.Name;
860 rCurrValue.Handle = rCurrProp.Handle;
861 rCurrValue.Value = aValue;
862 // rCurrValue.State =
864 nWritePos++;
868 // Title needed, but not set yet?
869 if ( !bHasTitle && ( rContext.aArg.NewTitle.getLength() > 0 ) )
871 aPropValues[ nWritePos ].Name
872 = rtl::OUString::createFromAscii( "Title" );
873 aPropValues[ nWritePos ].Handle = -1;
874 aPropValues[ nWritePos ].Value <<= rContext.aArg.NewTitle;
876 nWritePos++;
879 // TargetURL needed, but not set yet?
880 if ( !bHasTargetURL && ( rContext.aArg.Operation
881 == ucb::TransferCommandOperation_LINK ) )
883 aPropValues[ nWritePos ].Name
884 = rtl::OUString::createFromAscii( "TargetURL" );
885 aPropValues[ nWritePos ].Handle = -1;
886 aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL;
888 nWritePos++;
891 aPropValues.realloc( nWritePos );
893 // Set properties at new object.
895 ucb::Command aSetPropsCommand(
896 rtl::OUString::createFromAscii( "setPropertyValues" ),
898 uno::makeAny( aPropValues ) );
900 xCommandProcessorN->execute( aSetPropsCommand, 0, rContext.xEnv );
902 // @@@ What to do with source props that are not supported by the
903 // new object? addProperty ???
906 //=========================================================================
907 static uno::Reference< io::XInputStream > getInputStream(
908 const TransferCommandContext & rContext,
909 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
910 throw( uno::Exception )
912 uno::Reference< io::XInputStream > xInputStream;
914 //////////////////////////////////////////////////////////////////////
916 // (1) Try to get data as XInputStream via XActiveDataSink.
918 //////////////////////////////////////////////////////////////////////
922 uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink;
924 ucb::OpenCommandArgument2 aArg;
925 aArg.Mode = ucb::OpenMode::DOCUMENT;
926 aArg.Priority = 0; // unused
927 aArg.Sink = xSink;
928 aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused
930 ucb::Command aOpenCommand(
931 rtl::OUString::createFromAscii( "open" ),
933 uno::makeAny( aArg ) );
935 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
936 xInputStream = xSink->getInputStream();
938 catch ( uno::RuntimeException const & )
940 throw;
942 catch ( uno::Exception const & )
944 // will be handled below.
947 if ( !xInputStream.is() )
949 //////////////////////////////////////////////////////////////////
951 // (2) Try to get data via XOutputStream.
953 //////////////////////////////////////////////////////////////////
957 uno::Reference< io::XOutputStream > xOutputStream(
958 rContext.xSMgr->createInstance(
959 rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ),
960 uno::UNO_QUERY );
962 if ( xOutputStream.is() )
964 ucb::OpenCommandArgument2 aArg;
965 aArg.Mode = ucb::OpenMode::DOCUMENT;
966 aArg.Priority = 0; // unused
967 aArg.Sink = xOutputStream;
968 aArg.Properties = uno::Sequence< beans::Property >( 0 );
970 ucb::Command aOpenCommand(
971 rtl::OUString::createFromAscii( "open" ),
973 uno::makeAny( aArg ) );
975 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
977 xInputStream = uno::Reference< io::XInputStream >(
978 xOutputStream, uno::UNO_QUERY );
981 catch ( uno::RuntimeException const & )
983 throw;
985 catch ( uno::Exception const & )
987 OSL_ENSURE( sal_False, "unable to get input stream from document!" );
991 return xInputStream;
994 //=========================================================================
995 static uno::Reference< sdbc::XResultSet > getResultSet(
996 const TransferCommandContext & rContext,
997 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
998 throw( uno::Exception )
1000 uno::Reference< sdbc::XResultSet > xResultSet;
1002 uno::Sequence< beans::Property > aProps( 3 );
1004 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
1005 aProps[ 0 ].Handle = -1; /* unknown */
1006 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
1007 aProps[ 1 ].Handle = -1; /* unknown */
1008 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
1009 aProps[ 2 ].Handle = -1; /* unknown */
1011 ucb::OpenCommandArgument2 aArg;
1012 aArg.Mode = ucb::OpenMode::ALL;
1013 aArg.Priority = 0; // unused
1014 aArg.Sink = 0;
1015 aArg.Properties = aProps;
1017 ucb::Command aOpenCommand( rtl::OUString::createFromAscii( "open" ),
1019 uno::makeAny( aArg ) );
1022 uno::Reference< ucb::XDynamicResultSet > xSet;
1023 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet;
1025 if ( xSet.is() )
1026 xResultSet = xSet->getStaticResultSet();
1028 catch ( uno::RuntimeException const & )
1030 throw;
1032 catch ( uno::Exception const & )
1034 OSL_ENSURE( sal_False, "unable to get result set from folder!" );
1037 return xResultSet;
1040 //=========================================================================
1041 static void handleNameClashRename(
1042 const TransferCommandContext & rContext,
1043 const uno::Reference< ucb::XContent > & xNew,
1044 const uno::Reference<
1045 ucb::XCommandProcessor > & xCommandProcessorN,
1046 const uno::Reference<
1047 ucb::XCommandProcessor > & xCommandProcessorS,
1048 /* [inout] */ uno::Reference< io::XInputStream > & xInputStream )
1049 throw( uno::Exception )
1051 sal_Int32 nTry = 0;
1053 // Obtain old title.
1054 uno::Sequence< beans::Property > aProps( 1 );
1055 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" );
1056 aProps[ 0 ].Handle = -1;
1058 ucb::Command aGetPropsCommand(
1059 rtl::OUString::createFromAscii( "getPropertyValues" ),
1061 uno::makeAny( aProps ) );
1063 uno::Reference< sdbc::XRow > xRow;
1064 xCommandProcessorN->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
1066 if ( !xRow.is() )
1068 uno::Any aProps2
1069 = uno::makeAny(
1070 beans::PropertyValue(
1071 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1073 uno::makeAny(
1074 xNew->getIdentifier()->getContentIdentifier() ),
1075 beans::PropertyState_DIRECT_VALUE ) );
1076 ucbhelper::cancelCommandExecution(
1077 ucb::IOErrorCode_CANT_READ,
1078 uno::Sequence< uno::Any >( &aProps2, 1 ),
1079 rContext.xOrigEnv,
1080 rtl::OUString::createFromAscii(
1081 "Unable to get properties from new object!" ),
1082 rContext.xProcessor );
1083 // Unreachable
1086 rtl::OUString aOldTitle = xRow->getString( 1 );
1087 if ( !aOldTitle.getLength() )
1089 ucbhelper::cancelCommandExecution(
1090 uno::makeAny( beans::UnknownPropertyException(
1091 rtl::OUString::createFromAscii(
1092 "Unable to get property 'Title' "
1093 "from new object!" ),
1094 rContext.xProcessor ) ),
1095 rContext.xOrigEnv );
1096 // Unreachable
1099 // Some pseudo-intelligence for not destroying file extensions.
1100 rtl::OUString aOldTitlePre;
1101 rtl::OUString aOldTitlePost;
1102 sal_Int32 nPos = aOldTitle.lastIndexOf( '.' );
1103 if ( nPos != -1 )
1105 aOldTitlePre = aOldTitle.copy( 0, nPos );
1106 aOldTitlePost = aOldTitle.copy( nPos );
1108 else
1109 aOldTitlePre = aOldTitle;
1111 if ( nPos > 0 )
1112 aOldTitlePre += rtl::OUString::createFromAscii( "_" );
1114 sal_Bool bContinue = sal_True;
1117 nTry++;
1119 rtl::OUString aNewTitle = aOldTitlePre;
1120 aNewTitle += rtl::OUString::valueOf( nTry );
1121 aNewTitle += aOldTitlePost;
1123 // Set new title
1124 setTitle( xCommandProcessorN, rContext.xEnv, aNewTitle );
1126 // Retry inserting the content.
1129 // Previous try may have read from stream. Seek to begin (if
1130 // optional interface XSeekable is supported) or get a new stream.
1131 if ( xInputStream.is() )
1133 uno::Reference< io::XSeekable > xSeekable(
1134 xInputStream, uno::UNO_QUERY );
1135 if ( xSeekable.is() )
1139 xSeekable->seek( 0 );
1141 catch ( lang::IllegalArgumentException const & )
1143 xInputStream.clear();
1145 catch ( io::IOException const & )
1147 xInputStream.clear();
1150 else
1151 xInputStream.clear();
1153 if ( !xInputStream.is() )
1155 xInputStream
1156 = getInputStream( rContext, xCommandProcessorS );
1157 if ( !xInputStream.is() )
1159 uno::Any aProps2
1160 = uno::makeAny(
1161 beans::PropertyValue(
1162 rtl::OUString(
1163 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1165 uno::makeAny(
1166 xNew->getIdentifier()->
1167 getContentIdentifier() ),
1168 beans::PropertyState_DIRECT_VALUE ) );
1169 ucbhelper::cancelCommandExecution(
1170 ucb::IOErrorCode_CANT_READ,
1171 uno::Sequence< uno::Any >( &aProps2, 1 ),
1172 rContext.xOrigEnv,
1173 rtl::OUString::createFromAscii(
1174 "Got no data stream from source!" ),
1175 rContext.xProcessor );
1176 // Unreachable
1181 ucb::InsertCommandArgument aArg;
1182 aArg.Data = xInputStream;
1183 aArg.ReplaceExisting = sal_False;
1185 ucb::Command aInsertCommand(
1186 rtl::OUString::createFromAscii( "insert" ),
1188 uno::makeAny( aArg ) );
1190 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1192 // Success!
1193 bContinue = sal_False;
1195 catch ( uno::RuntimeException const & )
1197 throw;
1199 catch ( uno::Exception const & )
1203 while ( bContinue && ( nTry < 50 ) );
1205 if ( nTry == 50 )
1207 ucbhelper::cancelCommandExecution(
1208 uno::makeAny(
1209 ucb::UnsupportedNameClashException(
1210 rtl::OUString::createFromAscii(
1211 "Unable to resolve name clash!" ),
1212 rContext.xProcessor,
1213 ucb::NameClash::RENAME ) ),
1214 rContext.xOrigEnv );
1215 // Unreachable
1219 //=========================================================================
1220 static void globalTransfer(
1221 const TransferCommandContext & rContext,
1222 const uno::Reference< ucb::XContent > & xSource,
1223 const uno::Reference< ucb::XContent > & xTarget,
1224 const uno::Reference< sdbc::XRow > & xSourceProps )
1225 throw( uno::Exception )
1227 // IsFolder: property is required.
1228 sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 );
1229 if ( !bSourceIsFolder && xSourceProps->wasNull() )
1231 ucbhelper::cancelCommandExecution(
1232 uno::makeAny( beans::UnknownPropertyException(
1233 rtl::OUString::createFromAscii(
1234 "Unable to get property 'IsFolder' "
1235 "from source object!" ),
1236 rContext.xProcessor ) ),
1237 rContext.xOrigEnv );
1238 // Unreachable
1241 // IsDocument: property is required.
1242 sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 );
1243 if ( !bSourceIsDocument && xSourceProps->wasNull() )
1245 ucbhelper::cancelCommandExecution(
1246 uno::makeAny( beans::UnknownPropertyException(
1247 rtl::OUString::createFromAscii(
1248 "Unable to get property 'IsDocument' "
1249 "from source object!" ),
1250 rContext.xProcessor ) ),
1251 rContext.xOrigEnv );
1252 // Unreachable
1255 // TargetURL: property is optional.
1256 sal_Bool bSourceIsLink = ( xSourceProps->getString( 3 ).getLength() > 0 );
1258 //////////////////////////////////////////////////////////////////////
1260 // (1) Try to find a matching target type for the source object and
1261 // create a new, empty object of that type.
1263 //////////////////////////////////////////////////////////////////////
1265 uno::Reference< ucb::XContent > xNew = createNew( rContext,
1266 xTarget,
1267 bSourceIsFolder,
1268 bSourceIsDocument,
1269 bSourceIsLink );
1270 if ( !xNew.is() )
1272 uno::Any aProps
1273 = uno::makeAny(beans::PropertyValue(
1274 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1275 "Folder")),
1277 uno::makeAny(rContext.aArg.TargetURL),
1278 beans::PropertyState_DIRECT_VALUE));
1279 ucbhelper::cancelCommandExecution(
1280 ucb::IOErrorCode_CANT_CREATE,
1281 uno::Sequence< uno::Any >(&aProps, 1),
1282 rContext.xOrigEnv,
1283 rtl::OUString::createFromAscii(
1284 "No matching content type at target!" ),
1285 rContext.xProcessor );
1286 // Unreachable
1289 //////////////////////////////////////////////////////////////////////
1291 // (2) Transfer property values from source to new object.
1293 //////////////////////////////////////////////////////////////////////
1295 uno::Reference< ucb::XCommandProcessor > xCommandProcessorN(
1296 xNew, uno::UNO_QUERY );
1297 if ( !xCommandProcessorN.is() )
1299 uno::Any aProps
1300 = uno::makeAny(beans::PropertyValue(
1301 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1302 "Uri")),
1304 uno::makeAny(
1305 xNew->getIdentifier()->
1306 getContentIdentifier()),
1307 beans::PropertyState_DIRECT_VALUE));
1308 ucbhelper::cancelCommandExecution(
1309 ucb::IOErrorCode_CANT_WRITE,
1310 uno::Sequence< uno::Any >(&aProps, 1),
1311 rContext.xOrigEnv,
1312 rtl::OUString::createFromAscii(
1313 "New content is not a XCommandProcessor!" ),
1314 rContext.xProcessor );
1315 // Unreachable
1318 // Obtain all properties from source.
1320 uno::Reference< ucb::XCommandProcessor > xCommandProcessorS(
1321 xSource, uno::UNO_QUERY );
1322 if ( !xCommandProcessorS.is() )
1324 uno::Any aProps
1325 = uno::makeAny(beans::PropertyValue(
1326 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1327 "Uri")),
1329 uno::makeAny(rContext.aArg.SourceURL),
1330 beans::PropertyState_DIRECT_VALUE));
1331 ucbhelper::cancelCommandExecution(
1332 ucb::IOErrorCode_CANT_READ,
1333 uno::Sequence< uno::Any >(&aProps, 1),
1334 rContext.xOrigEnv,
1335 rtl::OUString::createFromAscii(
1336 "Source content is not a XCommandProcessor!" ),
1337 rContext.xProcessor );
1338 // Unreachable
1341 transferProperties( rContext, xCommandProcessorS, xCommandProcessorN );
1343 //////////////////////////////////////////////////////////////////////
1345 // (3) Try to obtain a data stream from source.
1347 //////////////////////////////////////////////////////////////////////
1349 uno::Reference< io::XInputStream > xInputStream;
1351 if ( bSourceIsDocument && ( rContext.aArg.Operation
1352 != ucb::TransferCommandOperation_LINK ) )
1353 xInputStream = getInputStream( rContext, xCommandProcessorS );
1355 //////////////////////////////////////////////////////////////////////
1357 // (4) Try to obtain a resultset (children) from source.
1359 //////////////////////////////////////////////////////////////////////
1361 uno::Reference< sdbc::XResultSet > xResultSet;
1363 if ( bSourceIsFolder && ( rContext.aArg.Operation
1364 != ucb::TransferCommandOperation_LINK ) )
1365 xResultSet = getResultSet( rContext, xCommandProcessorS );
1367 //////////////////////////////////////////////////////////////////////
1369 // (5) Insert (store) new content.
1371 //////////////////////////////////////////////////////////////////////
1373 ucb::InsertCommandArgument aArg;
1374 aArg.Data = xInputStream;
1376 switch ( rContext.aArg.NameClash )
1378 case ucb::NameClash::OVERWRITE:
1379 aArg.ReplaceExisting = sal_True;
1380 break;
1382 case ucb::NameClash::ERROR:
1383 case ucb::NameClash::RENAME:
1384 case ucb::NameClash::KEEP: // deprecated
1385 case ucb::NameClash::ASK:
1386 aArg.ReplaceExisting = sal_False;
1387 break;
1389 default:
1390 aArg.ReplaceExisting = sal_False;
1391 OSL_ENSURE( sal_False, "Unknown nameclash directive!" );
1392 break;
1395 rtl::OUString aDesiredName = createDesiredName( rContext.aArg );
1397 bool bRetry;
1400 bRetry = false;
1404 ucb::Command aInsertCommand(
1405 rtl::OUString::createFromAscii( "insert" ),
1407 uno::makeAny( aArg ) );
1409 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1411 catch ( ucb::UnsupportedNameClashException const & exc )
1413 OSL_ENSURE( !aArg.ReplaceExisting,
1414 "BUG: UnsupportedNameClashException not allowed here!" );
1416 if (exc.NameClash != ucb::NameClash::ERROR) {
1417 OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" );
1420 // No chance to solve name clashes, because I'm not able to detect
1421 // whether there is one.
1422 throw ucb::UnsupportedNameClashException(
1423 rtl::OUString::createFromAscii(
1424 "Unable to resolve name clashes, no chance to detect "
1425 "that there is one!" ),
1426 rContext.xProcessor,
1427 rContext.aArg.NameClash );
1429 catch ( ucb::NameClashException const & )
1431 // The 'insert' command throws a NameClashException if the parameter
1432 // ReplaceExisting of the command's argument was set to false and
1433 // there exists a resource with a clashing name in the target folder
1434 // of the operation.
1436 // 'insert' command has no direct support for name clashes other
1437 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1438 // ( ReplaceExisting == true ). So we have to implement the
1439 // other name clash handling directives on top of the content.
1441 // @@@ 'insert' command should be extended that it accepts a
1442 // name clash handling directive, exactly like 'transfer' command.
1444 switch ( rContext.aArg.NameClash )
1446 case ucb::NameClash::OVERWRITE:
1448 ucbhelper::cancelCommandExecution(
1449 uno::makeAny(
1450 ucb::UnsupportedNameClashException(
1451 rtl::OUString::createFromAscii(
1452 "BUG: insert + replace == true MUST NOT "
1453 "throw NameClashException." ),
1454 rContext.xProcessor,
1455 rContext.aArg.NameClash ) ),
1456 rContext.xOrigEnv );
1457 // Unreachable
1460 case ucb::NameClash::ERROR:
1461 throw;
1463 case ucb::NameClash::RENAME:
1465 // "invent" a new valid title.
1466 handleNameClashRename( rContext,
1467 xNew,
1468 xCommandProcessorN,
1469 xCommandProcessorS,
1470 xInputStream );
1471 break;
1474 case ucb::NameClash::ASK:
1476 uno::Any aExc;
1477 rtl::OUString aNewTitle;
1478 NameClashContinuation eCont
1479 = interactiveNameClashResolve(
1480 rContext.xOrigEnv, // always use original environment!
1481 rContext.aArg.TargetURL, // target folder URL
1482 aDesiredName,
1483 aExc,
1484 aNewTitle );
1486 switch ( eCont )
1488 case NOT_HANDLED:
1489 // Not handled.
1490 cppu::throwException( aExc );
1491 // break;
1493 case UNKNOWN:
1494 // Handled, but not clear, how...
1495 // fall-thru intended.
1497 case ABORT:
1498 throw ucb::CommandFailedException(
1499 rtl::OUString(
1500 RTL_CONSTASCII_USTRINGPARAM(
1501 "abort requested via interaction "
1502 "handler" ) ),
1503 uno::Reference< uno::XInterface >(),
1504 aExc );
1505 // break;
1507 case OVERWRITE:
1508 OSL_ENSURE( aArg.ReplaceExisting == sal_False,
1509 "Hu? ReplaceExisting already true?"
1511 aArg.ReplaceExisting = sal_True;
1512 bRetry = true;
1513 break;
1515 case NEW_NAME:
1517 // set new name -> set "Title" property...
1518 if ( setTitle( xCommandProcessorN,
1519 rContext.xEnv,
1520 aNewTitle ) )
1522 // remember suggested title...
1523 aDesiredName = aNewTitle;
1525 // ... and try again.
1526 bRetry = true;
1528 else
1530 // error setting title. Abort.
1531 throw ucb::CommandFailedException(
1532 rtl::OUString(
1533 RTL_CONSTASCII_USTRINGPARAM(
1534 "error setting Title property!"
1535 ) ),
1536 uno::Reference< uno::XInterface >(),
1537 aExc );
1539 break;
1543 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1545 break;
1547 case ucb::NameClash::KEEP: // deprecated
1548 default:
1550 ucbhelper::cancelCommandExecution(
1551 uno::makeAny(
1552 ucb::UnsupportedNameClashException(
1553 rtl::OUString(
1554 RTL_CONSTASCII_USTRINGPARAM(
1555 "default action, don't know how to "
1556 "handle name clash" ) ),
1557 rContext.xProcessor,
1558 rContext.aArg.NameClash ) ),
1559 rContext.xOrigEnv );
1560 // Unreachable
1565 while ( bRetry );
1567 //////////////////////////////////////////////////////////////////////
1569 // (6) Process children of source.
1571 //////////////////////////////////////////////////////////////////////
1573 if ( xResultSet.is() )
1577 // Iterate over children...
1579 uno::Reference< sdbc::XRow > xChildRow(
1580 xResultSet, uno::UNO_QUERY );
1582 if ( !xChildRow.is() )
1584 uno::Any aProps
1585 = uno::makeAny(
1586 beans::PropertyValue(
1587 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1588 "Uri")),
1590 uno::makeAny(rContext.aArg.SourceURL),
1591 beans::PropertyState_DIRECT_VALUE));
1592 ucbhelper::cancelCommandExecution(
1593 ucb::IOErrorCode_CANT_READ,
1594 uno::Sequence< uno::Any >(&aProps, 1),
1595 rContext.xOrigEnv,
1596 rtl::OUString::createFromAscii(
1597 "Unable to get properties from children of source!" ),
1598 rContext.xProcessor );
1599 // Unreachable
1602 uno::Reference< ucb::XContentAccess > xChildAccess(
1603 xResultSet, uno::UNO_QUERY );
1605 if ( !xChildAccess.is() )
1607 uno::Any aProps
1608 = uno::makeAny(
1609 beans::PropertyValue(
1610 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1611 "Uri")),
1613 uno::makeAny(rContext.aArg.SourceURL),
1614 beans::PropertyState_DIRECT_VALUE));
1615 ucbhelper::cancelCommandExecution(
1616 ucb::IOErrorCode_CANT_READ,
1617 uno::Sequence< uno::Any >(&aProps, 1),
1618 rContext.xOrigEnv,
1619 rtl::OUString::createFromAscii(
1620 "Unable to get children of source!" ),
1621 rContext.xProcessor );
1622 // Unreachable
1625 if ( xResultSet->first() )
1627 ucb::GlobalTransferCommandArgument aTransArg(
1628 rContext.aArg.Operation, // Operation
1629 rtl::OUString(), // SourceURL; filled later
1630 xNew->getIdentifier()
1631 ->getContentIdentifier(), // TargetURL
1632 rtl::OUString(), // NewTitle;
1633 rContext.aArg.NameClash ); // NameClash
1635 ucb_commands::TransferCommandContext aSubCtx(
1636 rContext.xSMgr,
1637 rContext.xProcessor,
1638 rContext.xEnv,
1639 rContext.xOrigEnv,
1640 aTransArg );
1643 uno::Reference< ucb::XContent > xChild
1644 = xChildAccess->queryContent();
1645 if ( xChild.is() )
1647 // Recursion!
1649 aSubCtx.aArg.SourceURL
1650 = xChild->getIdentifier()->getContentIdentifier();
1652 ucb_commands::globalTransfer( aSubCtx,
1653 xChild,
1654 xNew,
1655 xChildRow );
1658 while ( xResultSet->next() );
1661 catch ( sdbc::SQLException const & )
1666 try {
1667 uno::Reference< ucb::XCommandProcessor > xcp(
1668 xTarget, uno::UNO_QUERY );
1670 uno::Any aAny;
1671 uno::Reference< ucb::XCommandInfo > xci;
1672 if(xcp.is())
1673 aAny =
1674 xcp->execute(
1675 ucb::Command(
1676 rtl::OUString::createFromAscii("getCommandInfo"),
1678 uno::Any()),
1680 rContext.xEnv );
1682 const rtl::OUString cmdName =
1683 rtl::OUString::createFromAscii("flush");
1684 if((aAny >>= xci) && xci->hasCommandByName(cmdName))
1685 xcp->execute(
1686 ucb::Command(
1687 cmdName,
1689 uno::Any()) ,
1691 rContext.xEnv );
1693 catch( uno::Exception const & )
1698 } /* namescpace ucb_commands */
1700 //=========================================================================
1702 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1704 //=========================================================================
1706 uno::Reference< ucb::XCommandInfo >
1707 UniversalContentBroker::getCommandInfo()
1709 return uno::Reference< ucb::XCommandInfo >(
1710 new ucb_commands::CommandProcessorInfo() );
1713 //=========================================================================
1714 void UniversalContentBroker::globalTransfer(
1715 const ucb::GlobalTransferCommandArgument & rArg,
1716 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1717 throw( uno::Exception )
1719 // Use own command environment with own interaction handler intercepting
1720 // some interaction requests that shell not be handled by the user-supplied
1721 // interaction handler.
1722 uno::Reference< ucb::XCommandEnvironment > xLocalEnv;
1723 if (xEnv.is())
1724 xLocalEnv.set( new ucb_commands::CommandEnvironment(
1725 new ucb_commands::InteractionHandlerProxy(
1726 xEnv->getInteractionHandler() ),
1727 xEnv->getProgressHandler() ) );
1729 //////////////////////////////////////////////////////////////////////
1731 // (1) Try to transfer the content using 'transfer' command.
1733 //////////////////////////////////////////////////////////////////////
1735 uno::Reference< ucb::XContent > xTarget;
1736 uno::Reference< ucb::XContentIdentifier > xId
1737 = createContentIdentifier( rArg.TargetURL );
1738 if ( xId.is() )
1742 xTarget = queryContent( xId );
1744 catch ( ucb::IllegalIdentifierException const & )
1749 if ( !xTarget.is() )
1751 uno::Any aProps
1752 = uno::makeAny(beans::PropertyValue(
1753 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1754 "Uri")),
1756 uno::makeAny(rArg.TargetURL),
1757 beans::PropertyState_DIRECT_VALUE));
1758 ucbhelper::cancelCommandExecution(
1759 ucb::IOErrorCode_CANT_READ,
1760 uno::Sequence< uno::Any >(&aProps, 1),
1761 xEnv,
1762 rtl::OUString::createFromAscii(
1763 "Can't instanciate target object!" ),
1764 this );
1765 // Unreachable
1768 if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) ||
1769 ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) )
1771 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1772 xTarget, uno::UNO_QUERY );
1773 if ( !xCommandProcessor.is() )
1775 uno::Any aProps
1776 = uno::makeAny(
1777 beans::PropertyValue(
1778 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1779 "Uri")),
1781 uno::makeAny(rArg.TargetURL),
1782 beans::PropertyState_DIRECT_VALUE));
1783 ucbhelper::cancelCommandExecution(
1784 ucb::IOErrorCode_CANT_READ,
1785 uno::Sequence< uno::Any >(&aProps, 1),
1786 xEnv,
1787 rtl::OUString::createFromAscii(
1788 "Target content is not a XCommandProcessor!" ),
1789 this );
1790 // Unreachable
1793 ucb::TransferInfo aTransferArg(
1794 ( rArg.Operation
1795 == ucb::TransferCommandOperation_MOVE ), // MoveData
1796 rArg.SourceURL, // SourceURL
1797 rArg.NewTitle, // NewTitle
1798 rArg.NameClash ); // NameClash
1800 bool bRetry;
1803 bRetry = false;
1807 ucb::Command aCommand(
1808 rtl::OUString::createFromAscii( "transfer" ), // Name
1809 -1, // Handle
1810 uno::makeAny( aTransferArg ) ); // Argument
1812 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
1814 // Command succeeded. We're done.
1815 return;
1817 catch ( ucb::InteractiveBadTransferURLException const & )
1819 // Source URL is not supported by target. Try to transfer
1820 // the content "manually".
1822 catch ( ucb::UnsupportedCommandException const & )
1824 // 'transfer' command is not supported by commandprocessor.
1825 // Try to transfer manually.
1827 catch ( ucb::UnsupportedNameClashException const & exc )
1829 OSL_ENSURE( aTransferArg.NameClash == exc.NameClash,
1830 "nameclash mismatch!" );
1831 if ( exc.NameClash == ucb::NameClash::ASK )
1833 // Try to detect a name clash by invoking "transfer" with
1834 // NameClash::ERROR.
1837 ucb::TransferInfo aTransferArg1(
1838 aTransferArg.MoveData,
1839 aTransferArg.SourceURL,
1840 aTransferArg.NewTitle,
1841 ucb::NameClash::ERROR );
1843 ucb::Command aCommand1(
1844 rtl::OUString::createFromAscii( "transfer" ),
1846 uno::makeAny( aTransferArg1 ) );
1848 xCommandProcessor->execute( aCommand1, 0, xLocalEnv );
1850 // Command succeeded. We're done.
1851 return;
1853 catch ( ucb::UnsupportedNameClashException const & )
1855 // No chance to solve name clashes, because I'm not
1856 // able to detect whether there is one.
1857 throw exc; // Not just 'throw;'!
1859 catch ( ucb::NameClashException const & )
1861 // There's a clash. Use interaction handler to solve it.
1863 uno::Any aExc;
1864 rtl::OUString aNewTitle;
1865 ucb_commands::NameClashContinuation eCont
1866 = ucb_commands::interactiveNameClashResolve(
1867 xEnv, // always use original environment!
1868 rArg.TargetURL, // target folder URL
1869 ucb_commands::createDesiredName(
1870 aTransferArg ), // clashing name
1871 aExc,
1872 aNewTitle );
1874 switch ( eCont )
1876 case ucb_commands::NOT_HANDLED:
1877 // Not handled.
1878 cppu::throwException( aExc );
1879 // break;
1881 case ucb_commands::UNKNOWN:
1882 // Handled, but not clear, how...
1883 // fall-thru intended.
1885 case ucb_commands::ABORT:
1886 throw ucb::CommandFailedException(
1887 rtl::OUString(
1888 RTL_CONSTASCII_USTRINGPARAM(
1889 "abort requested via interaction "
1890 "handler" ) ),
1891 uno::Reference< uno::XInterface >(),
1892 aExc );
1893 // break;
1895 case ucb_commands::OVERWRITE:
1896 aTransferArg.NameClash
1897 = ucb::NameClash::OVERWRITE;
1898 bRetry = true;
1899 break;
1901 case ucb_commands::NEW_NAME:
1902 aTransferArg.NewTitle = aNewTitle;
1903 bRetry = true;
1904 break;
1907 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1910 else
1912 throw;
1916 while ( bRetry );
1919 //////////////////////////////////////////////////////////////////////
1921 // (2) Try to transfer the content "manually".
1923 //////////////////////////////////////////////////////////////////////
1925 uno::Reference< ucb::XContent > xSource;
1928 uno::Reference< ucb::XContentIdentifier > xId2
1929 = createContentIdentifier( rArg.SourceURL );
1930 if ( xId2.is() )
1931 xSource = queryContent( xId2 );
1933 catch ( ucb::IllegalIdentifierException const & )
1935 // Error handling via "if ( !xSource.is() )" below.
1938 if ( !xSource.is() )
1940 uno::Any aProps
1941 = uno::makeAny(beans::PropertyValue(
1942 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1943 "Uri")),
1945 uno::makeAny(rArg.SourceURL),
1946 beans::PropertyState_DIRECT_VALUE));
1947 ucbhelper::cancelCommandExecution(
1948 ucb::IOErrorCode_CANT_READ,
1949 uno::Sequence< uno::Any >(&aProps, 1),
1950 xEnv,
1951 rtl::OUString::createFromAscii(
1952 "Can't instanciate source object!" ),
1953 this );
1954 // Unreachable
1957 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1958 xSource, uno::UNO_QUERY );
1959 if ( !xCommandProcessor.is() )
1961 uno::Any aProps
1962 = uno::makeAny(beans::PropertyValue(
1963 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1964 "Uri")),
1966 uno::makeAny(rArg.SourceURL),
1967 beans::PropertyState_DIRECT_VALUE));
1968 ucbhelper::cancelCommandExecution(
1969 ucb::IOErrorCode_CANT_READ,
1970 uno::Sequence< uno::Any >(&aProps, 1),
1971 xEnv,
1972 rtl::OUString::createFromAscii(
1973 "Source content is not a XCommandProcessor!" ),
1974 this );
1975 // Unreachable
1978 // Obtain interesting property values from source...
1980 uno::Sequence< beans::Property > aProps( 4 );
1982 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
1983 aProps[ 0 ].Handle = -1; /* unknown */
1984 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
1985 aProps[ 1 ].Handle = -1; /* unknown */
1986 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
1987 aProps[ 2 ].Handle = -1; /* unknown */
1988 aProps[ 3 ].Name = rtl::OUString::createFromAscii( "BaseURI" );
1989 aProps[ 3 ].Handle = -1; /* unknown */
1991 ucb::Command aGetPropsCommand(
1992 rtl::OUString::createFromAscii( "getPropertyValues" ),
1994 uno::makeAny( aProps ) );
1996 uno::Reference< sdbc::XRow > xRow;
1997 xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow;
1999 if ( !xRow.is() )
2001 uno::Any aProps2
2002 = uno::makeAny(beans::PropertyValue(
2003 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2004 "Uri")),
2006 uno::makeAny(rArg.SourceURL),
2007 beans::PropertyState_DIRECT_VALUE));
2008 ucbhelper::cancelCommandExecution(
2009 ucb::IOErrorCode_CANT_READ,
2010 uno::Sequence< uno::Any >(&aProps2, 1),
2011 xEnv,
2012 rtl::OUString::createFromAscii(
2013 "Unable to get properties from source object!" ),
2014 this );
2015 // Unreachable
2018 ucb_commands::TransferCommandContext aTransferCtx(
2019 m_xSMgr, this, xLocalEnv, xEnv, rArg );
2021 if ( rArg.NewTitle.getLength() == 0 )
2023 // BaseURI: property is optional.
2024 rtl::OUString aBaseURI( xRow->getString( 4 ) );
2025 if ( aBaseURI.getLength() )
2027 aTransferCtx.aArg.NewTitle
2028 = ucb_commands::createDesiredName( aBaseURI, rtl::OUString() );
2032 // Do it!
2033 ucb_commands::globalTransfer( aTransferCtx, xSource, xTarget, xRow );
2035 //////////////////////////////////////////////////////////////////////
2037 // (3) Delete source, if operation is MOVE.
2039 //////////////////////////////////////////////////////////////////////
2041 if ( rArg.Operation == ucb::TransferCommandOperation_MOVE )
2045 ucb::Command aCommand(
2046 rtl::OUString::createFromAscii( "delete" ), // Name
2047 -1, // Handle
2048 uno::makeAny( sal_Bool( sal_True ) ) ); // Argument
2050 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
2052 catch ( uno::Exception const & )
2054 OSL_ENSURE( sal_False, "Cannot delete source object!" );
2055 throw;