1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32 #include <osl/diagnose.h>
33 #include <cppuhelper/implbase1.hxx>
34 #include <cppuhelper/exc_hlp.hxx>
35 #include <rtl/ustring.h>
36 #include <rtl/ustring.hxx>
37 #include <com/sun/star/uno/XInterface.hpp>
38 #include <com/sun/star/beans/PropertyState.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/beans/XPropertySetInfo.hpp>
43 #include <com/sun/star/io/XActiveDataSink.hpp>
44 #include <com/sun/star/io/XOutputStream.hpp>
45 #include <com/sun/star/io/XSeekable.hpp>
46 #include <com/sun/star/sdbc/XRow.hpp>
47 #include <com/sun/star/task/XInteractionHandler.hpp>
48 #include <com/sun/star/ucb/CommandEnvironment.hpp>
49 #include <com/sun/star/ucb/CommandFailedException.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp>
52 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
53 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
54 #include <com/sun/star/ucb/NameClash.hpp>
55 #include <com/sun/star/ucb/NameClashException.hpp>
56 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
57 #include <com/sun/star/ucb/OpenMode.hpp>
58 #include <com/sun/star/ucb/TransferInfo.hpp>
59 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
60 #include <com/sun/star/ucb/XCommandInfo.hpp>
61 #include <com/sun/star/ucb/XContentAccess.hpp>
62 #include <com/sun/star/ucb/XContentCreator.hpp>
63 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
64 #include <com/sun/star/uno/Any.hxx>
65 #include <com/sun/star/uno/Sequence.hxx>
66 #include <ucbhelper/cancelcommandexecution.hxx>
67 #include <ucbhelper/simplenameclashresolverequest.hxx>
68 #include "ucbcmds.hxx"
69 #include "ucb.hxx"
70
71 using namespace com::sun::star;
72
73 namespace
74 {
75
76 //=========================================================================
77 //
78 // struct TransferCommandContext.
79 //
80 //=========================================================================
81
82 struct TransferCommandContext
83 {
84 uno::Reference< lang::XMultiServiceFactory > xSMgr;
85 uno::Reference< ucb::XCommandProcessor > xProcessor;
86 uno::Reference< ucb::XCommandEnvironment > xEnv;
87 uno::Reference< ucb::XCommandEnvironment > xOrigEnv;
88 ucb::GlobalTransferCommandArgument aArg;
89
TransferCommandContext__anonaad216a20111::TransferCommandContext90 TransferCommandContext(
91 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr,
92 const uno::Reference< ucb::XCommandProcessor > & rxProcessor,
93 const uno::Reference< ucb::XCommandEnvironment > & rxEnv,
94 const uno::Reference< ucb::XCommandEnvironment > & rxOrigEnv,
95 const ucb::GlobalTransferCommandArgument & rArg )
96 : xSMgr( rxSMgr ), xProcessor( rxProcessor ), xEnv( rxEnv ),
97 xOrigEnv( rxOrigEnv ), aArg( rArg ) {}
98 };
99
100 //=========================================================================
101 //
102 // class InteractionHandlerProxy.
103 //
104 //=========================================================================
105
106 class InteractionHandlerProxy :
107 public cppu::WeakImplHelper1< task::XInteractionHandler >
108 {
109 uno::Reference< task::XInteractionHandler > m_xOrig;
110
111 public:
InteractionHandlerProxy(const uno::Reference<task::XInteractionHandler> & xOrig)112 InteractionHandlerProxy(
113 const uno::Reference< task::XInteractionHandler > & xOrig )
114 : m_xOrig( xOrig ) {}
115
116 // XInteractionHandler methods.
117 virtual void SAL_CALL handle(
118 const uno::Reference< task::XInteractionRequest >& Request )
119 throw ( uno::RuntimeException );
120 };
121
122 //=========================================================================
123 // virtual
handle(const uno::Reference<task::XInteractionRequest> & Request)124 void SAL_CALL InteractionHandlerProxy::handle(
125 const uno::Reference< task::XInteractionRequest >& Request )
126 throw ( uno::RuntimeException )
127 {
128 if ( !m_xOrig.is() )
129 return;
130
131 // Filter unwanted requests by just not handling them.
132 uno::Any aRequest = Request->getRequest();
133
134 // "transfer"
135 ucb::InteractiveBadTransferURLException aBadTransferURLEx;
136 if ( aRequest >>= aBadTransferURLEx )
137 {
138 return;
139 }
140 else
141 {
142 // "transfer"
143 ucb::UnsupportedNameClashException aUnsupportedNameClashEx;
144 if ( aRequest >>= aUnsupportedNameClashEx )
145 {
146 if ( aUnsupportedNameClashEx.NameClash
147 != ucb::NameClash::ERROR )
148 return;
149 }
150 else
151 {
152 // "insert"
153 ucb::NameClashException aNameClashEx;
154 if ( aRequest >>= aNameClashEx )
155 {
156 return;
157 }
158 else
159 {
160 // "transfer"
161 ucb::UnsupportedCommandException aUnsupportedCommandEx;
162 if ( aRequest >>= aUnsupportedCommandEx )
163 {
164 return;
165 }
166 }
167 }
168 }
169
170 // not filtered; let the original handler do the work.
171 m_xOrig->handle( Request );
172 }
173
174 //=========================================================================
175 //
176 // class ActiveDataSink.
177 //
178 //=========================================================================
179
180 class ActiveDataSink : public cppu::WeakImplHelper1< io::XActiveDataSink >
181 {
182 uno::Reference< io::XInputStream > m_xStream;
183
184 public:
185 // XActiveDataSink methods.
186 virtual void SAL_CALL setInputStream(
187 const uno::Reference< io::XInputStream >& aStream )
188 throw( uno::RuntimeException );
189 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
190 throw( uno::RuntimeException );
191 };
192
193 //=========================================================================
194 // virtual
setInputStream(const uno::Reference<io::XInputStream> & aStream)195 void SAL_CALL ActiveDataSink::setInputStream(
196 const uno::Reference< io::XInputStream >& aStream )
197 throw( uno::RuntimeException )
198 {
199 m_xStream = aStream;
200 }
201
202 //=========================================================================
203 // virtual
getInputStream()204 uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream()
205 throw( uno::RuntimeException )
206 {
207 return m_xStream;
208 }
209
210 //=========================================================================
211 //
212 // class CommandProcessorInfo.
213 //
214 //=========================================================================
215
216 class CommandProcessorInfo :
217 public cppu::WeakImplHelper1< ucb::XCommandInfo >
218 {
219 uno::Sequence< ucb::CommandInfo > * m_pInfo;
220
221 public:
222 CommandProcessorInfo();
223 virtual ~CommandProcessorInfo();
224
225 // XCommandInfo methods
226 virtual uno::Sequence< ucb::CommandInfo > SAL_CALL getCommands()
227 throw( uno::RuntimeException );
228 virtual ucb::CommandInfo SAL_CALL
229 getCommandInfoByName( const rtl::OUString& Name )
230 throw( ucb::UnsupportedCommandException, uno::RuntimeException );
231 virtual ucb::CommandInfo SAL_CALL
232 getCommandInfoByHandle( sal_Int32 Handle )
233 throw( ucb::UnsupportedCommandException, uno::RuntimeException );
234 virtual sal_Bool SAL_CALL hasCommandByName( const rtl::OUString& Name )
235 throw( uno::RuntimeException );
236 virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle )
237 throw( uno::RuntimeException );
238 };
239
240 //=========================================================================
CommandProcessorInfo()241 CommandProcessorInfo::CommandProcessorInfo()
242 {
243 m_pInfo = new uno::Sequence< ucb::CommandInfo >( 2 );
244
245 (*m_pInfo)[ 0 ]
246 = ucb::CommandInfo(
247 rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME ), // Name
248 GETCOMMANDINFO_HANDLE, // Handle
249 getCppuVoidType() ); // ArgType
250 (*m_pInfo)[ 1 ]
251 = ucb::CommandInfo(
252 rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME ), // Name
253 GLOBALTRANSFER_HANDLE, // Handle
254 getCppuType(
255 static_cast<
256 ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType
257 }
258
259 //=========================================================================
260 // virtual
~CommandProcessorInfo()261 CommandProcessorInfo::~CommandProcessorInfo()
262 {
263 delete m_pInfo;
264 }
265
266 //=========================================================================
267 // virtual
268 uno::Sequence< ucb::CommandInfo > SAL_CALL
getCommands()269 CommandProcessorInfo::getCommands()
270 throw( uno::RuntimeException )
271 {
272 return uno::Sequence< ucb::CommandInfo >( *m_pInfo );
273 }
274
275 //=========================================================================
276 // virtual
277 ucb::CommandInfo SAL_CALL
getCommandInfoByName(const rtl::OUString & Name)278 CommandProcessorInfo::getCommandInfoByName( const rtl::OUString& Name )
279 throw( ucb::UnsupportedCommandException, uno::RuntimeException )
280 {
281 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
282 {
283 if ( (*m_pInfo)[ n ].Name == Name )
284 return ucb::CommandInfo( (*m_pInfo)[ n ] );
285 }
286
287 throw ucb::UnsupportedCommandException();
288 }
289
290 //=========================================================================
291 // virtual
292 ucb::CommandInfo SAL_CALL
getCommandInfoByHandle(sal_Int32 Handle)293 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle )
294 throw( ucb::UnsupportedCommandException, uno::RuntimeException )
295 {
296 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
297 {
298 if ( (*m_pInfo)[ n ].Handle == Handle )
299 return ucb::CommandInfo( (*m_pInfo)[ n ] );
300 }
301
302 throw ucb::UnsupportedCommandException();
303 }
304
305 //=========================================================================
306 // virtual
hasCommandByName(const rtl::OUString & Name)307 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName(
308 const rtl::OUString& Name )
309 throw( uno::RuntimeException )
310 {
311 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
312 {
313 if ( (*m_pInfo)[ n ].Name == Name )
314 return sal_True;
315 }
316
317 return sal_False;
318 }
319
320 //=========================================================================
321 // virtual
hasCommandByHandle(sal_Int32 Handle)322 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle )
323 throw( uno::RuntimeException )
324 {
325 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
326 {
327 if ( (*m_pInfo)[ n ].Handle == Handle )
328 return sal_True;
329 }
330
331 return sal_False;
332 }
333
334 //=========================================================================
335 //=========================================================================
336 //=========================================================================
337
createDesiredName(const rtl::OUString & rSourceURL,const rtl::OUString & rNewTitle)338 rtl::OUString createDesiredName(
339 const rtl::OUString & rSourceURL, const rtl::OUString & rNewTitle )
340 {
341 rtl::OUString aName( rNewTitle );
342 if ( aName.getLength() == 0 )
343 {
344 // calculate name using source URL
345
346 // @@@ It's not guaranteed that slashes contained in the URL are
347 // actually path separators. This depends on the fact whether the
348 // URL is hierarchical. Only then the slashes are path separators.
349 // Therefore this algorithm is not guaranteed to work! But, ATM
350 // I don't know a better solution. It would have been better to
351 // have a member for the clashing name in
352 // UnsupportedNameClashException...
353
354 sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' );
355 bool bTrailingSlash = false;
356 if ( nLastSlash == rSourceURL.getLength() - 1 )
357 {
358 nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash );
359 bTrailingSlash = true;
360 }
361
362 if ( nLastSlash != -1 )
363 {
364 if ( bTrailingSlash )
365 aName = rSourceURL.copy(
366 nLastSlash + 1,
367 rSourceURL.getLength() - nLastSlash - 2 );
368 else
369 aName = rSourceURL.copy( nLastSlash + 1 );
370 }
371 else
372 {
373 aName = rSourceURL;
374 }
375
376 // query, fragment present?
377 sal_Int32 nPos = aName.indexOf( '?' );
378 if ( nPos == -1 )
379 nPos = aName.indexOf( '#' );
380
381 if ( nPos != -1 )
382 aName = aName.copy( 0, nPos );
383 }
384 return rtl::OUString( aName );
385 }
386
createDesiredName(const ucb::GlobalTransferCommandArgument & rArg)387 rtl::OUString createDesiredName(
388 const ucb::GlobalTransferCommandArgument & rArg )
389 {
390 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
391 }
392
createDesiredName(const ucb::TransferInfo & rArg)393 rtl::OUString createDesiredName(
394 const ucb::TransferInfo & rArg )
395 {
396 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
397 }
398
399 //=========================================================================
400 enum NameClashContinuation { NOT_HANDLED, ABORT, OVERWRITE, NEW_NAME, UNKNOWN };
401
interactiveNameClashResolve(const uno::Reference<ucb::XCommandEnvironment> & xEnv,const rtl::OUString & rTargetURL,const rtl::OUString & rClashingName,uno::Any & rException,rtl::OUString & rNewName)402 NameClashContinuation interactiveNameClashResolve(
403 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
404 const rtl::OUString & rTargetURL,
405 const rtl::OUString & rClashingName,
406 /* [out] */ uno::Any & rException,
407 /* [out] */ rtl::OUString & rNewName )
408 {
409 rtl::Reference< ucbhelper::SimpleNameClashResolveRequest > xRequest(
410 new ucbhelper::SimpleNameClashResolveRequest(
411 rTargetURL, // target folder URL
412 rClashingName, // clashing name
413 rtl::OUString(), // no proposal for new name
414 sal_True /* bSupportsOverwriteData */ ) );
415
416 rException = xRequest->getRequest();
417 if ( xEnv.is() )
418 {
419 uno::Reference< task::XInteractionHandler > xIH
420 = xEnv->getInteractionHandler();
421 if ( xIH.is() )
422 {
423
424 xIH->handle( xRequest.get() );
425
426 rtl::Reference< ucbhelper::InteractionContinuation >
427 xSelection( xRequest->getSelection() );
428
429 if ( xSelection.is() )
430 {
431 // Handler handled the request.
432 uno::Reference< task::XInteractionAbort > xAbort(
433 xSelection.get(), uno::UNO_QUERY );
434 if ( xAbort.is() )
435 {
436 // Abort.
437 return ABORT;
438 }
439 else
440 {
441 uno::Reference<
442 ucb::XInteractionReplaceExistingData >
443 xReplace(
444 xSelection.get(), uno::UNO_QUERY );
445 if ( xReplace.is() )
446 {
447 // Try again: Replace existing data.
448 return OVERWRITE;
449 }
450 else
451 {
452 uno::Reference<
453 ucb::XInteractionSupplyName >
454 xSupplyName(
455 xSelection.get(), uno::UNO_QUERY );
456 if ( xSupplyName.is() )
457 {
458 // Try again: Use new name.
459 rNewName = xRequest->getNewName();
460 return NEW_NAME;
461 }
462 else
463 {
464 OSL_ENSURE( sal_False,
465 "Unknown interaction continuation!" );
466 return UNKNOWN;
467 }
468 }
469 }
470 }
471 }
472 }
473 return NOT_HANDLED;
474 }
475
476 //=========================================================================
setTitle(const uno::Reference<ucb::XCommandProcessor> & xCommandProcessor,const uno::Reference<ucb::XCommandEnvironment> & xEnv,const rtl::OUString & rNewTitle)477 bool setTitle(
478 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessor,
479 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
480 const rtl::OUString & rNewTitle )
481 throw( uno::RuntimeException )
482 {
483 try
484 {
485 uno::Sequence< beans::PropertyValue > aPropValues( 1 );
486 aPropValues[ 0 ].Name
487 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
488 aPropValues[ 0 ].Handle = -1;
489 aPropValues[ 0 ].Value = uno::makeAny( rNewTitle );
490
491 ucb::Command aSetPropsCommand(
492 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
493 -1,
494 uno::makeAny( aPropValues ) );
495
496 uno::Any aResult
497 = xCommandProcessor->execute( aSetPropsCommand, 0, xEnv );
498
499 uno::Sequence< uno::Any > aErrors;
500 aResult >>= aErrors;
501
502 OSL_ENSURE( aErrors.getLength() == 1,
503 "getPropertyValues return value invalid!" );
504
505 if ( aErrors[ 0 ].hasValue() )
506 {
507 // error occured.
508 OSL_ENSURE( sal_False, "error setting Title property!" );
509 return false;
510 }
511 }
512 catch ( uno::RuntimeException const & )
513 {
514 throw;
515 }
516 catch ( uno::Exception const & )
517 {
518 return false;
519 }
520
521 return true;
522 }
523
524 //=========================================================================
createNew(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xTarget,sal_Bool bSourceIsFolder,sal_Bool bSourceIsDocument,sal_Bool bSourceIsLink)525 uno::Reference< ucb::XContent > createNew(
526 const TransferCommandContext & rContext,
527 const uno::Reference< ucb::XContent > & xTarget,
528 sal_Bool bSourceIsFolder,
529 sal_Bool bSourceIsDocument,
530 sal_Bool bSourceIsLink )
531 throw( uno::Exception )
532 {
533 //////////////////////////////////////////////////////////////////////
534 //
535 // (1) Obtain creatable types from target.
536 //
537 //////////////////////////////////////////////////////////////////////
538
539 // First, try it using "CreatabeleContentsInfo" property and
540 // "createNewContent" command -> the "new" way.
541
542 uno::Reference< ucb::XCommandProcessor > xCommandProcessorT(
543 xTarget, uno::UNO_QUERY );
544 if ( !xCommandProcessorT.is() )
545 {
546 uno::Any aProps
547 = uno::makeAny(beans::PropertyValue(
548 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
549 "Folder")),
550 -1,
551 uno::makeAny(rContext.aArg.TargetURL),
552 beans::PropertyState_DIRECT_VALUE));
553 ucbhelper::cancelCommandExecution(
554 ucb::IOErrorCode_CANT_CREATE,
555 uno::Sequence< uno::Any >(&aProps, 1),
556 rContext.xOrigEnv,
557 rtl::OUString::createFromAscii( "Target is no XCommandProcessor!" ),
558 rContext.xProcessor );
559 // Unreachable
560 }
561
562 uno::Sequence< beans::Property > aPropsToObtain( 1 );
563 aPropsToObtain[ 0 ].Name
564 = rtl::OUString::createFromAscii( "CreatableContentsInfo" );
565 aPropsToObtain[ 0 ].Handle
566 = -1;
567
568 ucb::Command aGetPropsCommand(
569 rtl::OUString::createFromAscii( "getPropertyValues" ),
570 -1,
571 uno::makeAny( aPropsToObtain ) );
572
573 uno::Reference< sdbc::XRow > xRow;
574 xCommandProcessorT->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
575
576 uno::Sequence< ucb::ContentInfo > aTypesInfo;
577 bool bGotTypesInfo = false;
578
579 if ( xRow.is() )
580 {
581 uno::Any aValue = xRow->getObject(
582 1, uno::Reference< container::XNameAccess >() );
583 if ( aValue.hasValue() && ( aValue >>= aTypesInfo ) )
584 {
585 bGotTypesInfo = true;
586 }
587 }
588
589 uno::Reference< ucb::XContentCreator > xCreator;
590
591 if ( !bGotTypesInfo )
592 {
593 // Second, try it using XContentCreator interface -> the "old" way (not
594 // providing the chance to supply an XCommandEnvironment.
595
596 xCreator.set( xTarget, uno::UNO_QUERY );
597
598 if ( !xCreator.is() )
599 {
600 uno::Any aProps
601 = uno::makeAny(beans::PropertyValue(
602 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
603 "Folder")),
604 -1,
605 uno::makeAny(rContext.aArg.TargetURL),
606 beans::PropertyState_DIRECT_VALUE));
607 ucbhelper::cancelCommandExecution(
608 ucb::IOErrorCode_CANT_CREATE,
609 uno::Sequence< uno::Any >(&aProps, 1),
610 rContext.xOrigEnv,
611 rtl::OUString::createFromAscii( "Target is no XContentCreator!" ),
612 rContext.xProcessor );
613 // Unreachable
614 }
615
616 aTypesInfo = xCreator->queryCreatableContentsInfo();
617 }
618
619 sal_Int32 nCount = aTypesInfo.getLength();
620 if ( !nCount )
621 {
622 uno::Any aProps
623 = uno::makeAny(beans::PropertyValue(
624 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Folder")),
625 -1,
626 uno::makeAny(rContext.aArg.TargetURL),
627 beans::PropertyState_DIRECT_VALUE));
628 ucbhelper::cancelCommandExecution(
629 ucb::IOErrorCode_CANT_CREATE,
630 uno::Sequence< uno::Any >(&aProps, 1),
631 rContext.xOrigEnv,
632 rtl::OUString::createFromAscii( "No types creatable!" ),
633 rContext.xProcessor );
634 // Unreachable
635 }
636
637 //////////////////////////////////////////////////////////////////////
638 //
639 // (2) Try to find a matching target type for the source object.
640 //
641 //////////////////////////////////////////////////////////////////////
642
643 uno::Reference< ucb::XContent > xNew;
644 for ( sal_Int32 n = 0; n < nCount; ++n )
645 {
646 sal_Int32 nAttribs = aTypesInfo[ n ].Attributes;
647 sal_Bool bMatch = sal_False;
648
649 if ( rContext.aArg.Operation == ucb::TransferCommandOperation_LINK )
650 {
651 // Create link
652
653 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
654 {
655 // Match!
656 bMatch = sal_True;
657 }
658 }
659 else if ( ( rContext.aArg.Operation
660 == ucb::TransferCommandOperation_COPY ) ||
661 ( rContext.aArg.Operation
662 == ucb::TransferCommandOperation_MOVE ) )
663 {
664 // Copy / Move
665
666 // Is source a link? Create link in target folder then.
667 if ( bSourceIsLink )
668 {
669 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
670 {
671 // Match!
672 bMatch = sal_True;
673 }
674 }
675 else
676 {
677 // (not a and not b) or (a and b)
678 // not( a or b) or (a and b)
679 //
680 if ( ( !!bSourceIsFolder ==
681 !!( nAttribs
682 & ucb::ContentInfoAttribute::KIND_FOLDER ) )
683 &&
684 ( !!bSourceIsDocument ==
685 !!( nAttribs
686 & ucb::ContentInfoAttribute::KIND_DOCUMENT ) )
687 )
688 {
689 // Match!
690 bMatch = sal_True;
691 }
692 }
693 }
694 else
695 {
696 ucbhelper::cancelCommandExecution(
697 uno::makeAny( lang::IllegalArgumentException(
698 rtl::OUString::createFromAscii(
699 "Unknown transfer operation!" ),
700 rContext.xProcessor,
701 -1 ) ),
702 rContext.xOrigEnv );
703 // Unreachable
704 }
705
706 if ( bMatch )
707 {
708 //////////////////////////////////////////////////////////////
709 //
710 // (3) Create a new, empty object of matched type.
711 //
712 //////////////////////////////////////////////////////////////
713
714 if ( !xCreator.is() )
715 {
716 // First, try it using "CreatabeleContentsInfo" property and
717 // "createNewContent" command -> the "new" way.
718 ucb::Command aCreateNewCommand(
719 rtl::OUString::createFromAscii( "createNewContent" ),
720 -1,
721 uno::makeAny( aTypesInfo[ n ] ) );
722
723 xCommandProcessorT->execute( aCreateNewCommand, 0, rContext.xEnv )
724 >>= xNew;
725 }
726 else
727 {
728 // Second, try it using XContentCreator interface -> the "old"
729 // way (not providing the chance to supply an XCommandEnvironment.
730
731 xNew = xCreator->createNewContent( aTypesInfo[ n ] );
732 }
733
734 if ( !xNew.is() )
735 {
736 uno::Any aProps
737 = uno::makeAny(
738 beans::PropertyValue(
739 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
740 "Folder")),
741 -1,
742 uno::makeAny(rContext.aArg.TargetURL),
743 beans::PropertyState_DIRECT_VALUE));
744 ucbhelper::cancelCommandExecution(
745 ucb::IOErrorCode_CANT_CREATE,
746 uno::Sequence< uno::Any >(&aProps, 1),
747 rContext.xOrigEnv,
748 rtl::OUString::createFromAscii(
749 "createNewContent failed!" ),
750 rContext.xProcessor );
751 // Unreachable
752 }
753 break; // escape from 'for' loop
754 }
755 } // for
756
757 return xNew;
758 }
759
760 //=========================================================================
transferProperties(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorN)761 void transferProperties(
762 const TransferCommandContext & rContext,
763 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS,
764 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorN )
765 throw( uno::Exception )
766 {
767 ucb::Command aGetPropertySetInfoCommand(
768 rtl::OUString::createFromAscii( "getPropertySetInfo" ),
769 -1,
770 uno::Any() );
771
772 uno::Reference< beans::XPropertySetInfo > xInfo;
773 xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv )
774 >>= xInfo;
775
776 if ( !xInfo.is() )
777 {
778 uno::Any aProps
779 = uno::makeAny(beans::PropertyValue(
780 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
781 "Uri")),
782 -1,
783 uno::makeAny(rContext.aArg.SourceURL),
784 beans::PropertyState_DIRECT_VALUE));
785 ucbhelper::cancelCommandExecution(
786 ucb::IOErrorCode_CANT_READ,
787 uno::Sequence< uno::Any >(&aProps, 1),
788 rContext.xOrigEnv,
789 rtl::OUString::createFromAscii(
790 "Unable to get propertyset info from source object!" ),
791 rContext.xProcessor );
792 // Unreachable
793 }
794
795 uno::Sequence< beans::Property > aAllProps = xInfo->getProperties();
796
797 ucb::Command aGetPropsCommand1(
798 rtl::OUString::createFromAscii( "getPropertyValues" ),
799 -1,
800 uno::makeAny( aAllProps ) );
801
802 uno::Reference< sdbc::XRow > xRow1;
803 xCommandProcessorS->execute(
804 aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1;
805
806 if ( !xRow1.is() )
807 {
808 uno::Any aProps
809 = uno::makeAny(beans::PropertyValue(
810 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
811 "Uri")),
812 -1,
813 uno::makeAny(rContext.aArg.SourceURL),
814 beans::PropertyState_DIRECT_VALUE));
815 ucbhelper::cancelCommandExecution(
816 ucb::IOErrorCode_CANT_READ,
817 uno::Sequence< uno::Any >(&aProps, 1),
818 rContext.xOrigEnv,
819 rtl::OUString::createFromAscii(
820 "Unable to get properties from source object!" ),
821 rContext.xProcessor );
822 // Unreachable
823 }
824
825 // Assemble data structure for setPropertyValues command.
826
827 // Note: Make room for additional Title and TargetURL too. -> + 2
828 uno::Sequence< beans::PropertyValue > aPropValues(
829 aAllProps.getLength() + 2 );
830
831 sal_Bool bHasTitle = ( rContext.aArg.NewTitle.getLength() == 0 );
832 sal_Bool bHasTargetURL = ( rContext.aArg.Operation
833 != ucb::TransferCommandOperation_LINK );
834
835 sal_Int32 nWritePos = 0;
836 for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m )
837 {
838 const beans::Property & rCurrProp = aAllProps[ m ];
839 beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ];
840
841 uno::Any aValue;
842
843 if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 )
844 {
845 // Supply new title, if given.
846 if ( !bHasTitle )
847 {
848 bHasTitle = sal_True;
849 aValue <<= rContext.aArg.NewTitle;
850 }
851 }
852 else if ( rCurrProp.Name.compareToAscii( "TargetURL" ) == 0 )
853 {
854 // Supply source URL as link target for the new link to create.
855 if ( !bHasTargetURL )
856 {
857 bHasTargetURL = sal_True;
858 aValue <<= rContext.aArg.SourceURL;
859 }
860 }
861
862 if ( !aValue.hasValue() )
863 {
864 try
865 {
866 aValue = xRow1->getObject(
867 m + 1, uno::Reference< container::XNameAccess >() );
868 }
869 catch ( sdbc::SQLException const & )
870 {
871 // Argh! But try to bring things to an end. Perhaps the
872 // mad property is not really important...
873 }
874 }
875
876 if ( aValue.hasValue() )
877 {
878 rCurrValue.Name = rCurrProp.Name;
879 rCurrValue.Handle = rCurrProp.Handle;
880 rCurrValue.Value = aValue;
881 // rCurrValue.State =
882
883 nWritePos++;
884 }
885 }
886
887 // Title needed, but not set yet?
888 if ( !bHasTitle && ( rContext.aArg.NewTitle.getLength() > 0 ) )
889 {
890 aPropValues[ nWritePos ].Name
891 = rtl::OUString::createFromAscii( "Title" );
892 aPropValues[ nWritePos ].Handle = -1;
893 aPropValues[ nWritePos ].Value <<= rContext.aArg.NewTitle;
894
895 nWritePos++;
896 }
897
898 // TargetURL needed, but not set yet?
899 if ( !bHasTargetURL && ( rContext.aArg.Operation
900 == ucb::TransferCommandOperation_LINK ) )
901 {
902 aPropValues[ nWritePos ].Name
903 = rtl::OUString::createFromAscii( "TargetURL" );
904 aPropValues[ nWritePos ].Handle = -1;
905 aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL;
906
907 nWritePos++;
908 }
909
910 aPropValues.realloc( nWritePos );
911
912 // Set properties at new object.
913
914 ucb::Command aSetPropsCommand(
915 rtl::OUString::createFromAscii( "setPropertyValues" ),
916 -1,
917 uno::makeAny( aPropValues ) );
918
919 xCommandProcessorN->execute( aSetPropsCommand, 0, rContext.xEnv );
920
921 // @@@ What to do with source props that are not supported by the
922 // new object? addProperty ???
923 }
924
925 //=========================================================================
getInputStream(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS)926 uno::Reference< io::XInputStream > getInputStream(
927 const TransferCommandContext & rContext,
928 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
929 throw( uno::Exception )
930 {
931 uno::Reference< io::XInputStream > xInputStream;
932
933 //////////////////////////////////////////////////////////////////////
934 //
935 // (1) Try to get data as XInputStream via XActiveDataSink.
936 //
937 //////////////////////////////////////////////////////////////////////
938
939 try
940 {
941 uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink;
942
943 ucb::OpenCommandArgument2 aArg;
944 aArg.Mode = ucb::OpenMode::DOCUMENT;
945 aArg.Priority = 0; // unused
946 aArg.Sink = xSink;
947 aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused
948
949 ucb::Command aOpenCommand(
950 rtl::OUString::createFromAscii( "open" ),
951 -1,
952 uno::makeAny( aArg ) );
953
954 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
955 xInputStream = xSink->getInputStream();
956 }
957 catch ( uno::RuntimeException const & )
958 {
959 throw;
960 }
961 catch ( uno::Exception const & )
962 {
963 // will be handled below.
964 }
965
966 if ( !xInputStream.is() )
967 {
968 //////////////////////////////////////////////////////////////////
969 //
970 // (2) Try to get data via XOutputStream.
971 //
972 //////////////////////////////////////////////////////////////////
973
974 try
975 {
976 uno::Reference< io::XOutputStream > xOutputStream(
977 rContext.xSMgr->createInstance(
978 rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ),
979 uno::UNO_QUERY );
980
981 if ( xOutputStream.is() )
982 {
983 ucb::OpenCommandArgument2 aArg;
984 aArg.Mode = ucb::OpenMode::DOCUMENT;
985 aArg.Priority = 0; // unused
986 aArg.Sink = xOutputStream;
987 aArg.Properties = uno::Sequence< beans::Property >( 0 );
988
989 ucb::Command aOpenCommand(
990 rtl::OUString::createFromAscii( "open" ),
991 -1,
992 uno::makeAny( aArg ) );
993
994 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
995
996 xInputStream = uno::Reference< io::XInputStream >(
997 xOutputStream, uno::UNO_QUERY );
998 }
999 }
1000 catch ( uno::RuntimeException const & )
1001 {
1002 throw;
1003 }
1004 catch ( uno::Exception const & )
1005 {
1006 OSL_ENSURE( sal_False, "unable to get input stream from document!" );
1007 }
1008 }
1009
1010 return xInputStream;
1011 }
1012
1013 //=========================================================================
getResultSet(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS)1014 uno::Reference< sdbc::XResultSet > getResultSet(
1015 const TransferCommandContext & rContext,
1016 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
1017 throw( uno::Exception )
1018 {
1019 uno::Reference< sdbc::XResultSet > xResultSet;
1020
1021 uno::Sequence< beans::Property > aProps( 3 );
1022
1023 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
1024 aProps[ 0 ].Handle = -1; /* unknown */
1025 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
1026 aProps[ 1 ].Handle = -1; /* unknown */
1027 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
1028 aProps[ 2 ].Handle = -1; /* unknown */
1029
1030 ucb::OpenCommandArgument2 aArg;
1031 aArg.Mode = ucb::OpenMode::ALL;
1032 aArg.Priority = 0; // unused
1033 aArg.Sink = 0;
1034 aArg.Properties = aProps;
1035
1036 ucb::Command aOpenCommand( rtl::OUString::createFromAscii( "open" ),
1037 -1,
1038 uno::makeAny( aArg ) );
1039 try
1040 {
1041 uno::Reference< ucb::XDynamicResultSet > xSet;
1042 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet;
1043
1044 if ( xSet.is() )
1045 xResultSet = xSet->getStaticResultSet();
1046 }
1047 catch ( uno::RuntimeException const & )
1048 {
1049 throw;
1050 }
1051 catch ( uno::Exception const & )
1052 {
1053 OSL_ENSURE( sal_False, "unable to get result set from folder!" );
1054 }
1055
1056 return xResultSet;
1057 }
1058
1059 //=========================================================================
handleNameClashRename(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xNew,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorN,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS,uno::Reference<io::XInputStream> & xInputStream)1060 void handleNameClashRename(
1061 const TransferCommandContext & rContext,
1062 const uno::Reference< ucb::XContent > & xNew,
1063 const uno::Reference<
1064 ucb::XCommandProcessor > & xCommandProcessorN,
1065 const uno::Reference<
1066 ucb::XCommandProcessor > & xCommandProcessorS,
1067 /* [inout] */ uno::Reference< io::XInputStream > & xInputStream )
1068 throw( uno::Exception )
1069 {
1070 sal_Int32 nTry = 0;
1071
1072 // Obtain old title.
1073 uno::Sequence< beans::Property > aProps( 1 );
1074 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" );
1075 aProps[ 0 ].Handle = -1;
1076
1077 ucb::Command aGetPropsCommand(
1078 rtl::OUString::createFromAscii( "getPropertyValues" ),
1079 -1,
1080 uno::makeAny( aProps ) );
1081
1082 uno::Reference< sdbc::XRow > xRow;
1083 xCommandProcessorN->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
1084
1085 if ( !xRow.is() )
1086 {
1087 uno::Any aProps2
1088 = uno::makeAny(
1089 beans::PropertyValue(
1090 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1091 -1,
1092 uno::makeAny(
1093 xNew->getIdentifier()->getContentIdentifier() ),
1094 beans::PropertyState_DIRECT_VALUE ) );
1095 ucbhelper::cancelCommandExecution(
1096 ucb::IOErrorCode_CANT_READ,
1097 uno::Sequence< uno::Any >( &aProps2, 1 ),
1098 rContext.xOrigEnv,
1099 rtl::OUString::createFromAscii(
1100 "Unable to get properties from new object!" ),
1101 rContext.xProcessor );
1102 // Unreachable
1103 }
1104
1105 rtl::OUString aOldTitle = xRow->getString( 1 );
1106 if ( !aOldTitle.getLength() )
1107 {
1108 ucbhelper::cancelCommandExecution(
1109 uno::makeAny( beans::UnknownPropertyException(
1110 rtl::OUString::createFromAscii(
1111 "Unable to get property 'Title' "
1112 "from new object!" ),
1113 rContext.xProcessor ) ),
1114 rContext.xOrigEnv );
1115 // Unreachable
1116 }
1117
1118 // Some pseudo-intelligence for not destroying file extensions.
1119 rtl::OUString aOldTitlePre;
1120 rtl::OUString aOldTitlePost;
1121 sal_Int32 nPos = aOldTitle.lastIndexOf( '.' );
1122 if ( nPos != -1 )
1123 {
1124 aOldTitlePre = aOldTitle.copy( 0, nPos );
1125 aOldTitlePost = aOldTitle.copy( nPos );
1126 }
1127 else
1128 aOldTitlePre = aOldTitle;
1129
1130 if ( nPos > 0 )
1131 aOldTitlePre += rtl::OUString::createFromAscii( "_" );
1132
1133 sal_Bool bContinue = sal_True;
1134 do
1135 {
1136 nTry++;
1137
1138 rtl::OUString aNewTitle = aOldTitlePre;
1139 aNewTitle += rtl::OUString::valueOf( nTry );
1140 aNewTitle += aOldTitlePost;
1141
1142 // Set new title
1143 setTitle( xCommandProcessorN, rContext.xEnv, aNewTitle );
1144
1145 // Retry inserting the content.
1146 try
1147 {
1148 // Previous try may have read from stream. Seek to begin (if
1149 // optional interface XSeekable is supported) or get a new stream.
1150 if ( xInputStream.is() )
1151 {
1152 uno::Reference< io::XSeekable > xSeekable(
1153 xInputStream, uno::UNO_QUERY );
1154 if ( xSeekable.is() )
1155 {
1156 try
1157 {
1158 xSeekable->seek( 0 );
1159 }
1160 catch ( lang::IllegalArgumentException const & )
1161 {
1162 xInputStream.clear();
1163 }
1164 catch ( io::IOException const & )
1165 {
1166 xInputStream.clear();
1167 }
1168 }
1169 else
1170 xInputStream.clear();
1171
1172 if ( !xInputStream.is() )
1173 {
1174 xInputStream
1175 = getInputStream( rContext, xCommandProcessorS );
1176 if ( !xInputStream.is() )
1177 {
1178 uno::Any aProps2
1179 = uno::makeAny(
1180 beans::PropertyValue(
1181 rtl::OUString(
1182 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1183 -1,
1184 uno::makeAny(
1185 xNew->getIdentifier()->
1186 getContentIdentifier() ),
1187 beans::PropertyState_DIRECT_VALUE ) );
1188 ucbhelper::cancelCommandExecution(
1189 ucb::IOErrorCode_CANT_READ,
1190 uno::Sequence< uno::Any >( &aProps2, 1 ),
1191 rContext.xOrigEnv,
1192 rtl::OUString::createFromAscii(
1193 "Got no data stream from source!" ),
1194 rContext.xProcessor );
1195 // Unreachable
1196 }
1197 }
1198 }
1199
1200 ucb::InsertCommandArgument aArg;
1201 aArg.Data = xInputStream;
1202 aArg.ReplaceExisting = sal_False;
1203
1204 ucb::Command aInsertCommand(
1205 rtl::OUString::createFromAscii( "insert" ),
1206 -1,
1207 uno::makeAny( aArg ) );
1208
1209 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1210
1211 // Success!
1212 bContinue = sal_False;
1213 }
1214 catch ( uno::RuntimeException const & )
1215 {
1216 throw;
1217 }
1218 catch ( uno::Exception const & )
1219 {
1220 }
1221 }
1222 while ( bContinue && ( nTry < 50 ) );
1223
1224 if ( nTry == 50 )
1225 {
1226 ucbhelper::cancelCommandExecution(
1227 uno::makeAny(
1228 ucb::UnsupportedNameClashException(
1229 rtl::OUString::createFromAscii(
1230 "Unable to resolve name clash!" ),
1231 rContext.xProcessor,
1232 ucb::NameClash::RENAME ) ),
1233 rContext.xOrigEnv );
1234 // Unreachable
1235 }
1236 }
1237
1238 //=========================================================================
globalTransfer_(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xSource,const uno::Reference<ucb::XContent> & xTarget,const uno::Reference<sdbc::XRow> & xSourceProps)1239 void globalTransfer_(
1240 const TransferCommandContext & rContext,
1241 const uno::Reference< ucb::XContent > & xSource,
1242 const uno::Reference< ucb::XContent > & xTarget,
1243 const uno::Reference< sdbc::XRow > & xSourceProps )
1244 throw( uno::Exception )
1245 {
1246 // IsFolder: property is required.
1247 sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 );
1248 if ( !bSourceIsFolder && xSourceProps->wasNull() )
1249 {
1250 ucbhelper::cancelCommandExecution(
1251 uno::makeAny( beans::UnknownPropertyException(
1252 rtl::OUString::createFromAscii(
1253 "Unable to get property 'IsFolder' "
1254 "from source object!" ),
1255 rContext.xProcessor ) ),
1256 rContext.xOrigEnv );
1257 // Unreachable
1258 }
1259
1260 // IsDocument: property is required.
1261 sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 );
1262 if ( !bSourceIsDocument && xSourceProps->wasNull() )
1263 {
1264 ucbhelper::cancelCommandExecution(
1265 uno::makeAny( beans::UnknownPropertyException(
1266 rtl::OUString::createFromAscii(
1267 "Unable to get property 'IsDocument' "
1268 "from source object!" ),
1269 rContext.xProcessor ) ),
1270 rContext.xOrigEnv );
1271 // Unreachable
1272 }
1273
1274 // TargetURL: property is optional.
1275 sal_Bool bSourceIsLink = ( xSourceProps->getString( 3 ).getLength() > 0 );
1276
1277 //////////////////////////////////////////////////////////////////////
1278 //
1279 // (1) Try to find a matching target type for the source object and
1280 // create a new, empty object of that type.
1281 //
1282 //////////////////////////////////////////////////////////////////////
1283
1284 uno::Reference< ucb::XContent > xNew = createNew( rContext,
1285 xTarget,
1286 bSourceIsFolder,
1287 bSourceIsDocument,
1288 bSourceIsLink );
1289 if ( !xNew.is() )
1290 {
1291 uno::Any aProps
1292 = uno::makeAny(beans::PropertyValue(
1293 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1294 "Folder")),
1295 -1,
1296 uno::makeAny(rContext.aArg.TargetURL),
1297 beans::PropertyState_DIRECT_VALUE));
1298 ucbhelper::cancelCommandExecution(
1299 ucb::IOErrorCode_CANT_CREATE,
1300 uno::Sequence< uno::Any >(&aProps, 1),
1301 rContext.xOrigEnv,
1302 rtl::OUString::createFromAscii(
1303 "No matching content type at target!" ),
1304 rContext.xProcessor );
1305 // Unreachable
1306 }
1307
1308 //////////////////////////////////////////////////////////////////////
1309 //
1310 // (2) Transfer property values from source to new object.
1311 //
1312 //////////////////////////////////////////////////////////////////////
1313
1314 uno::Reference< ucb::XCommandProcessor > xCommandProcessorN(
1315 xNew, uno::UNO_QUERY );
1316 if ( !xCommandProcessorN.is() )
1317 {
1318 uno::Any aProps
1319 = uno::makeAny(beans::PropertyValue(
1320 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1321 "Uri")),
1322 -1,
1323 uno::makeAny(
1324 xNew->getIdentifier()->
1325 getContentIdentifier()),
1326 beans::PropertyState_DIRECT_VALUE));
1327 ucbhelper::cancelCommandExecution(
1328 ucb::IOErrorCode_CANT_WRITE,
1329 uno::Sequence< uno::Any >(&aProps, 1),
1330 rContext.xOrigEnv,
1331 rtl::OUString::createFromAscii(
1332 "New content is not a XCommandProcessor!" ),
1333 rContext.xProcessor );
1334 // Unreachable
1335 }
1336
1337 // Obtain all properties from source.
1338
1339 uno::Reference< ucb::XCommandProcessor > xCommandProcessorS(
1340 xSource, uno::UNO_QUERY );
1341 if ( !xCommandProcessorS.is() )
1342 {
1343 uno::Any aProps
1344 = uno::makeAny(beans::PropertyValue(
1345 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1346 "Uri")),
1347 -1,
1348 uno::makeAny(rContext.aArg.SourceURL),
1349 beans::PropertyState_DIRECT_VALUE));
1350 ucbhelper::cancelCommandExecution(
1351 ucb::IOErrorCode_CANT_READ,
1352 uno::Sequence< uno::Any >(&aProps, 1),
1353 rContext.xOrigEnv,
1354 rtl::OUString::createFromAscii(
1355 "Source content is not a XCommandProcessor!" ),
1356 rContext.xProcessor );
1357 // Unreachable
1358 }
1359
1360 transferProperties( rContext, xCommandProcessorS, xCommandProcessorN );
1361
1362 //////////////////////////////////////////////////////////////////////
1363 //
1364 // (3) Try to obtain a data stream from source.
1365 //
1366 //////////////////////////////////////////////////////////////////////
1367
1368 uno::Reference< io::XInputStream > xInputStream;
1369
1370 if ( bSourceIsDocument && ( rContext.aArg.Operation
1371 != ucb::TransferCommandOperation_LINK ) )
1372 xInputStream = getInputStream( rContext, xCommandProcessorS );
1373
1374 //////////////////////////////////////////////////////////////////////
1375 //
1376 // (4) Try to obtain a resultset (children) from source.
1377 //
1378 //////////////////////////////////////////////////////////////////////
1379
1380 uno::Reference< sdbc::XResultSet > xResultSet;
1381
1382 if ( bSourceIsFolder && ( rContext.aArg.Operation
1383 != ucb::TransferCommandOperation_LINK ) )
1384 xResultSet = getResultSet( rContext, xCommandProcessorS );
1385
1386 //////////////////////////////////////////////////////////////////////
1387 //
1388 // (5) Insert (store) new content.
1389 //
1390 //////////////////////////////////////////////////////////////////////
1391
1392 ucb::InsertCommandArgument aArg;
1393 aArg.Data = xInputStream;
1394
1395 switch ( rContext.aArg.NameClash )
1396 {
1397 case ucb::NameClash::OVERWRITE:
1398 aArg.ReplaceExisting = sal_True;
1399 break;
1400
1401 case ucb::NameClash::ERROR:
1402 case ucb::NameClash::RENAME:
1403 case ucb::NameClash::KEEP: // deprecated
1404 case ucb::NameClash::ASK:
1405 aArg.ReplaceExisting = sal_False;
1406 break;
1407
1408 default:
1409 aArg.ReplaceExisting = sal_False;
1410 OSL_ENSURE( sal_False, "Unknown nameclash directive!" );
1411 break;
1412 }
1413
1414 rtl::OUString aDesiredName = createDesiredName( rContext.aArg );
1415
1416 bool bRetry;
1417 do
1418 {
1419 bRetry = false;
1420
1421 try
1422 {
1423 ucb::Command aInsertCommand(
1424 rtl::OUString::createFromAscii( "insert" ),
1425 -1,
1426 uno::makeAny( aArg ) );
1427
1428 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1429 }
1430 catch ( ucb::UnsupportedNameClashException const & exc )
1431 {
1432 OSL_ENSURE( !aArg.ReplaceExisting,
1433 "BUG: UnsupportedNameClashException not allowed here!" );
1434
1435 if (exc.NameClash != ucb::NameClash::ERROR) {
1436 OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" );
1437 }
1438
1439 // No chance to solve name clashes, because I'm not able to detect
1440 // whether there is one.
1441 throw ucb::UnsupportedNameClashException(
1442 rtl::OUString::createFromAscii(
1443 "Unable to resolve name clashes, no chance to detect "
1444 "that there is one!" ),
1445 rContext.xProcessor,
1446 rContext.aArg.NameClash );
1447 }
1448 catch ( ucb::NameClashException const & )
1449 {
1450 // The 'insert' command throws a NameClashException if the parameter
1451 // ReplaceExisting of the command's argument was set to false and
1452 // there exists a resource with a clashing name in the target folder
1453 // of the operation.
1454
1455 // 'insert' command has no direct support for name clashes other
1456 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1457 // ( ReplaceExisting == true ). So we have to implement the
1458 // other name clash handling directives on top of the content.
1459
1460 // @@@ 'insert' command should be extended that it accepts a
1461 // name clash handling directive, exactly like 'transfer' command.
1462
1463 switch ( rContext.aArg.NameClash )
1464 {
1465 case ucb::NameClash::OVERWRITE:
1466 {
1467 ucbhelper::cancelCommandExecution(
1468 uno::makeAny(
1469 ucb::UnsupportedNameClashException(
1470 rtl::OUString::createFromAscii(
1471 "BUG: insert + replace == true MUST NOT "
1472 "throw NameClashException." ),
1473 rContext.xProcessor,
1474 rContext.aArg.NameClash ) ),
1475 rContext.xOrigEnv );
1476 // Unreachable
1477 }
1478
1479 case ucb::NameClash::ERROR:
1480 throw;
1481
1482 case ucb::NameClash::RENAME:
1483 {
1484 // "invent" a new valid title.
1485 handleNameClashRename( rContext,
1486 xNew,
1487 xCommandProcessorN,
1488 xCommandProcessorS,
1489 xInputStream );
1490 break;
1491 }
1492
1493 case ucb::NameClash::ASK:
1494 {
1495 uno::Any aExc;
1496 rtl::OUString aNewTitle;
1497 NameClashContinuation eCont
1498 = interactiveNameClashResolve(
1499 rContext.xOrigEnv, // always use original environment!
1500 rContext.aArg.TargetURL, // target folder URL
1501 aDesiredName,
1502 aExc,
1503 aNewTitle );
1504
1505 switch ( eCont )
1506 {
1507 case NOT_HANDLED:
1508 // Not handled.
1509 cppu::throwException( aExc );
1510 // break;
1511
1512 case UNKNOWN:
1513 // Handled, but not clear, how...
1514 // fall-thru intended.
1515
1516 case ABORT:
1517 throw ucb::CommandFailedException(
1518 rtl::OUString(
1519 RTL_CONSTASCII_USTRINGPARAM(
1520 "abort requested via interaction "
1521 "handler" ) ),
1522 uno::Reference< uno::XInterface >(),
1523 aExc );
1524 // break;
1525
1526 case OVERWRITE:
1527 OSL_ENSURE( aArg.ReplaceExisting == sal_False,
1528 "Hu? ReplaceExisting already true?"
1529 );
1530 aArg.ReplaceExisting = sal_True;
1531 bRetry = true;
1532 break;
1533
1534 case NEW_NAME:
1535 {
1536 // set new name -> set "Title" property...
1537 if ( setTitle( xCommandProcessorN,
1538 rContext.xEnv,
1539 aNewTitle ) )
1540 {
1541 // remember suggested title...
1542 aDesiredName = aNewTitle;
1543
1544 // ... and try again.
1545 bRetry = true;
1546 }
1547 else
1548 {
1549 // error setting title. Abort.
1550 throw ucb::CommandFailedException(
1551 rtl::OUString(
1552 RTL_CONSTASCII_USTRINGPARAM(
1553 "error setting Title property!"
1554 ) ),
1555 uno::Reference< uno::XInterface >(),
1556 aExc );
1557 }
1558 break;
1559 }
1560 }
1561
1562 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1563 }
1564 break;
1565
1566 case ucb::NameClash::KEEP: // deprecated
1567 default:
1568 {
1569 ucbhelper::cancelCommandExecution(
1570 uno::makeAny(
1571 ucb::UnsupportedNameClashException(
1572 rtl::OUString(
1573 RTL_CONSTASCII_USTRINGPARAM(
1574 "default action, don't know how to "
1575 "handle name clash" ) ),
1576 rContext.xProcessor,
1577 rContext.aArg.NameClash ) ),
1578 rContext.xOrigEnv );
1579 // Unreachable
1580 }
1581 }
1582 }
1583 }
1584 while ( bRetry );
1585
1586 //////////////////////////////////////////////////////////////////////
1587 //
1588 // (6) Process children of source.
1589 //
1590 //////////////////////////////////////////////////////////////////////
1591
1592 if ( xResultSet.is() )
1593 {
1594 try
1595 {
1596 // Iterate over children...
1597
1598 uno::Reference< sdbc::XRow > xChildRow(
1599 xResultSet, uno::UNO_QUERY );
1600
1601 if ( !xChildRow.is() )
1602 {
1603 uno::Any aProps
1604 = uno::makeAny(
1605 beans::PropertyValue(
1606 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1607 "Uri")),
1608 -1,
1609 uno::makeAny(rContext.aArg.SourceURL),
1610 beans::PropertyState_DIRECT_VALUE));
1611 ucbhelper::cancelCommandExecution(
1612 ucb::IOErrorCode_CANT_READ,
1613 uno::Sequence< uno::Any >(&aProps, 1),
1614 rContext.xOrigEnv,
1615 rtl::OUString::createFromAscii(
1616 "Unable to get properties from children of source!" ),
1617 rContext.xProcessor );
1618 // Unreachable
1619 }
1620
1621 uno::Reference< ucb::XContentAccess > xChildAccess(
1622 xResultSet, uno::UNO_QUERY );
1623
1624 if ( !xChildAccess.is() )
1625 {
1626 uno::Any aProps
1627 = uno::makeAny(
1628 beans::PropertyValue(
1629 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1630 "Uri")),
1631 -1,
1632 uno::makeAny(rContext.aArg.SourceURL),
1633 beans::PropertyState_DIRECT_VALUE));
1634 ucbhelper::cancelCommandExecution(
1635 ucb::IOErrorCode_CANT_READ,
1636 uno::Sequence< uno::Any >(&aProps, 1),
1637 rContext.xOrigEnv,
1638 rtl::OUString::createFromAscii(
1639 "Unable to get children of source!" ),
1640 rContext.xProcessor );
1641 // Unreachable
1642 }
1643
1644 if ( xResultSet->first() )
1645 {
1646 ucb::GlobalTransferCommandArgument aTransArg(
1647 rContext.aArg.Operation, // Operation
1648 rtl::OUString(), // SourceURL; filled later
1649 xNew->getIdentifier()
1650 ->getContentIdentifier(), // TargetURL
1651 rtl::OUString(), // NewTitle;
1652 rContext.aArg.NameClash ); // NameClash
1653
1654 TransferCommandContext aSubCtx(
1655 rContext.xSMgr,
1656 rContext.xProcessor,
1657 rContext.xEnv,
1658 rContext.xOrigEnv,
1659 aTransArg );
1660 do
1661 {
1662 uno::Reference< ucb::XContent > xChild
1663 = xChildAccess->queryContent();
1664 if ( xChild.is() )
1665 {
1666 // Recursion!
1667
1668 aSubCtx.aArg.SourceURL
1669 = xChild->getIdentifier()->getContentIdentifier();
1670
1671 globalTransfer_( aSubCtx,
1672 xChild,
1673 xNew,
1674 xChildRow );
1675 }
1676 }
1677 while ( xResultSet->next() );
1678 }
1679 }
1680 catch ( sdbc::SQLException const & )
1681 {
1682 }
1683 }
1684
1685 try {
1686 uno::Reference< ucb::XCommandProcessor > xcp(
1687 xTarget, uno::UNO_QUERY );
1688
1689 uno::Any aAny;
1690 uno::Reference< ucb::XCommandInfo > xci;
1691 if(xcp.is())
1692 aAny =
1693 xcp->execute(
1694 ucb::Command(
1695 rtl::OUString::createFromAscii("getCommandInfo"),
1696 -1,
1697 uno::Any()),
1698 0,
1699 rContext.xEnv );
1700
1701 const rtl::OUString cmdName =
1702 rtl::OUString::createFromAscii("flush");
1703 if((aAny >>= xci) && xci->hasCommandByName(cmdName))
1704 xcp->execute(
1705 ucb::Command(
1706 cmdName,
1707 -1,
1708 uno::Any()) ,
1709 0,
1710 rContext.xEnv );
1711 }
1712 catch( uno::Exception const & )
1713 {
1714 }
1715 }
1716
1717 } /* namescpace */
1718
1719 //=========================================================================
1720 //
1721 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1722 //
1723 //=========================================================================
1724
1725 uno::Reference< ucb::XCommandInfo >
getCommandInfo()1726 UniversalContentBroker::getCommandInfo()
1727 {
1728 return uno::Reference< ucb::XCommandInfo >( new CommandProcessorInfo() );
1729 }
1730
1731 //=========================================================================
globalTransfer(const ucb::GlobalTransferCommandArgument & rArg,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1732 void UniversalContentBroker::globalTransfer(
1733 const ucb::GlobalTransferCommandArgument & rArg,
1734 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1735 throw( uno::Exception )
1736 {
1737 // Use own command environment with own interaction handler intercepting
1738 // some interaction requests that shall not be handled by the user-supplied
1739 // interaction handler.
1740 uno::Reference< ucb::XCommandEnvironment > xLocalEnv;
1741 if (xEnv.is())
1742 {
1743 uno::Reference< beans::XPropertySet > const xProps(
1744 m_xSMgr, uno::UNO_QUERY_THROW );
1745 uno::Reference< uno::XComponentContext > xCtx;
1746 xCtx.set( xProps->getPropertyValue(
1747 rtl::OUString(
1748 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ),
1749 uno::UNO_QUERY_THROW );
1750
1751 xLocalEnv.set( ucb::CommandEnvironment::create(
1752 xCtx,
1753 new InteractionHandlerProxy( xEnv->getInteractionHandler() ),
1754 xEnv->getProgressHandler() ) );
1755 }
1756
1757 //////////////////////////////////////////////////////////////////////
1758 //
1759 // (1) Try to transfer the content using 'transfer' command.
1760 //
1761 //////////////////////////////////////////////////////////////////////
1762
1763 uno::Reference< ucb::XContent > xTarget;
1764 uno::Reference< ucb::XContentIdentifier > xId
1765 = createContentIdentifier( rArg.TargetURL );
1766 if ( xId.is() )
1767 {
1768 try
1769 {
1770 xTarget = queryContent( xId );
1771 }
1772 catch ( ucb::IllegalIdentifierException const & )
1773 {
1774 }
1775 }
1776
1777 if ( !xTarget.is() )
1778 {
1779 uno::Any aProps
1780 = uno::makeAny(beans::PropertyValue(
1781 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1782 "Uri")),
1783 -1,
1784 uno::makeAny(rArg.TargetURL),
1785 beans::PropertyState_DIRECT_VALUE));
1786 ucbhelper::cancelCommandExecution(
1787 ucb::IOErrorCode_CANT_READ,
1788 uno::Sequence< uno::Any >(&aProps, 1),
1789 xEnv,
1790 rtl::OUString::createFromAscii(
1791 "Can't instanciate target object!" ),
1792 this );
1793 // Unreachable
1794 }
1795
1796 if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) ||
1797 ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) )
1798 {
1799 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1800 xTarget, uno::UNO_QUERY );
1801 if ( !xCommandProcessor.is() )
1802 {
1803 uno::Any aProps
1804 = uno::makeAny(
1805 beans::PropertyValue(
1806 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1807 "Uri")),
1808 -1,
1809 uno::makeAny(rArg.TargetURL),
1810 beans::PropertyState_DIRECT_VALUE));
1811 ucbhelper::cancelCommandExecution(
1812 ucb::IOErrorCode_CANT_READ,
1813 uno::Sequence< uno::Any >(&aProps, 1),
1814 xEnv,
1815 rtl::OUString::createFromAscii(
1816 "Target content is not a XCommandProcessor!" ),
1817 this );
1818 // Unreachable
1819 }
1820
1821 ucb::TransferInfo aTransferArg(
1822 ( rArg.Operation
1823 == ucb::TransferCommandOperation_MOVE ), // MoveData
1824 rArg.SourceURL, // SourceURL
1825 rArg.NewTitle, // NewTitle
1826 rArg.NameClash ); // NameClash
1827
1828 bool bRetry;
1829 do
1830 {
1831 bRetry = false;
1832
1833 try
1834 {
1835 ucb::Command aCommand(
1836 rtl::OUString::createFromAscii( "transfer" ), // Name
1837 -1, // Handle
1838 uno::makeAny( aTransferArg ) ); // Argument
1839
1840 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
1841
1842 // Command succeeded. We're done.
1843 return;
1844 }
1845 catch ( ucb::InteractiveBadTransferURLException const & )
1846 {
1847 // Source URL is not supported by target. Try to transfer
1848 // the content "manually".
1849 }
1850 catch ( ucb::UnsupportedCommandException const & )
1851 {
1852 // 'transfer' command is not supported by commandprocessor.
1853 // Try to transfer manually.
1854 }
1855 catch ( ucb::UnsupportedNameClashException const & exc )
1856 {
1857 OSL_ENSURE( aTransferArg.NameClash == exc.NameClash,
1858 "nameclash mismatch!" );
1859 if ( exc.NameClash == ucb::NameClash::ASK )
1860 {
1861 // Try to detect a name clash by invoking "transfer" with
1862 // NameClash::ERROR.
1863 try
1864 {
1865 ucb::TransferInfo aTransferArg1(
1866 aTransferArg.MoveData,
1867 aTransferArg.SourceURL,
1868 aTransferArg.NewTitle,
1869 ucb::NameClash::ERROR );
1870
1871 ucb::Command aCommand1(
1872 rtl::OUString::createFromAscii( "transfer" ),
1873 -1,
1874 uno::makeAny( aTransferArg1 ) );
1875
1876 xCommandProcessor->execute( aCommand1, 0, xLocalEnv );
1877
1878 // Command succeeded. We're done.
1879 return;
1880 }
1881 catch ( ucb::UnsupportedNameClashException const & )
1882 {
1883 // No chance to solve name clashes, because I'm not
1884 // able to detect whether there is one.
1885 throw exc; // Not just 'throw;'!
1886 }
1887 catch ( ucb::NameClashException const & )
1888 {
1889 // There's a clash. Use interaction handler to solve it.
1890
1891 uno::Any aExc;
1892 rtl::OUString aNewTitle;
1893 NameClashContinuation eCont
1894 = interactiveNameClashResolve(
1895 xEnv, // always use original environment!
1896 rArg.TargetURL, // target folder URL
1897 createDesiredName(
1898 aTransferArg ), // clashing name
1899 aExc,
1900 aNewTitle );
1901
1902 switch ( eCont )
1903 {
1904 case NOT_HANDLED:
1905 // Not handled.
1906 cppu::throwException( aExc );
1907 // break;
1908
1909 case UNKNOWN:
1910 // Handled, but not clear, how...
1911 // fall-thru intended.
1912
1913 case ABORT:
1914 throw ucb::CommandFailedException(
1915 rtl::OUString(
1916 RTL_CONSTASCII_USTRINGPARAM(
1917 "abort requested via interaction "
1918 "handler" ) ),
1919 uno::Reference< uno::XInterface >(),
1920 aExc );
1921 // break;
1922
1923 case OVERWRITE:
1924 aTransferArg.NameClash
1925 = ucb::NameClash::OVERWRITE;
1926 bRetry = true;
1927 break;
1928
1929 case NEW_NAME:
1930 aTransferArg.NewTitle = aNewTitle;
1931 bRetry = true;
1932 break;
1933 }
1934
1935 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1936 }
1937 }
1938 else
1939 {
1940 throw;
1941 }
1942 }
1943 }
1944 while ( bRetry );
1945 }
1946
1947 //////////////////////////////////////////////////////////////////////
1948 //
1949 // (2) Try to transfer the content "manually".
1950 //
1951 //////////////////////////////////////////////////////////////////////
1952
1953 uno::Reference< ucb::XContent > xSource;
1954 try
1955 {
1956 uno::Reference< ucb::XContentIdentifier > xId2
1957 = createContentIdentifier( rArg.SourceURL );
1958 if ( xId2.is() )
1959 xSource = queryContent( xId2 );
1960 }
1961 catch ( ucb::IllegalIdentifierException const & )
1962 {
1963 // Error handling via "if ( !xSource.is() )" below.
1964 }
1965
1966 if ( !xSource.is() )
1967 {
1968 uno::Any aProps
1969 = uno::makeAny(beans::PropertyValue(
1970 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1971 "Uri")),
1972 -1,
1973 uno::makeAny(rArg.SourceURL),
1974 beans::PropertyState_DIRECT_VALUE));
1975 ucbhelper::cancelCommandExecution(
1976 ucb::IOErrorCode_CANT_READ,
1977 uno::Sequence< uno::Any >(&aProps, 1),
1978 xEnv,
1979 rtl::OUString::createFromAscii(
1980 "Can't instanciate source object!" ),
1981 this );
1982 // Unreachable
1983 }
1984
1985 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1986 xSource, uno::UNO_QUERY );
1987 if ( !xCommandProcessor.is() )
1988 {
1989 uno::Any aProps
1990 = uno::makeAny(beans::PropertyValue(
1991 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1992 "Uri")),
1993 -1,
1994 uno::makeAny(rArg.SourceURL),
1995 beans::PropertyState_DIRECT_VALUE));
1996 ucbhelper::cancelCommandExecution(
1997 ucb::IOErrorCode_CANT_READ,
1998 uno::Sequence< uno::Any >(&aProps, 1),
1999 xEnv,
2000 rtl::OUString::createFromAscii(
2001 "Source content is not a XCommandProcessor!" ),
2002 this );
2003 // Unreachable
2004 }
2005
2006 // Obtain interesting property values from source...
2007
2008 uno::Sequence< beans::Property > aProps( 4 );
2009
2010 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
2011 aProps[ 0 ].Handle = -1; /* unknown */
2012 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
2013 aProps[ 1 ].Handle = -1; /* unknown */
2014 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
2015 aProps[ 2 ].Handle = -1; /* unknown */
2016 aProps[ 3 ].Name = rtl::OUString::createFromAscii( "BaseURI" );
2017 aProps[ 3 ].Handle = -1; /* unknown */
2018
2019 ucb::Command aGetPropsCommand(
2020 rtl::OUString::createFromAscii( "getPropertyValues" ),
2021 -1,
2022 uno::makeAny( aProps ) );
2023
2024 uno::Reference< sdbc::XRow > xRow;
2025 xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow;
2026
2027 if ( !xRow.is() )
2028 {
2029 uno::Any aProps2
2030 = uno::makeAny(beans::PropertyValue(
2031 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2032 "Uri")),
2033 -1,
2034 uno::makeAny(rArg.SourceURL),
2035 beans::PropertyState_DIRECT_VALUE));
2036 ucbhelper::cancelCommandExecution(
2037 ucb::IOErrorCode_CANT_READ,
2038 uno::Sequence< uno::Any >(&aProps2, 1),
2039 xEnv,
2040 rtl::OUString::createFromAscii(
2041 "Unable to get properties from source object!" ),
2042 this );
2043 // Unreachable
2044 }
2045
2046 TransferCommandContext aTransferCtx(
2047 m_xSMgr, this, xLocalEnv, xEnv, rArg );
2048
2049 if ( rArg.NewTitle.getLength() == 0 )
2050 {
2051 // BaseURI: property is optional.
2052 rtl::OUString aBaseURI( xRow->getString( 4 ) );
2053 if ( aBaseURI.getLength() )
2054 {
2055 aTransferCtx.aArg.NewTitle
2056 = createDesiredName( aBaseURI, rtl::OUString() );
2057 }
2058 }
2059
2060 // Do it!
2061 globalTransfer_( aTransferCtx, xSource, xTarget, xRow );
2062
2063 //////////////////////////////////////////////////////////////////////
2064 //
2065 // (3) Delete source, if operation is MOVE.
2066 //
2067 //////////////////////////////////////////////////////////////////////
2068
2069 if ( rArg.Operation == ucb::TransferCommandOperation_MOVE )
2070 {
2071 try
2072 {
2073 ucb::Command aCommand(
2074 rtl::OUString::createFromAscii( "delete" ), // Name
2075 -1, // Handle
2076 uno::makeAny( sal_Bool( sal_True ) ) ); // Argument
2077
2078 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
2079 }
2080 catch ( uno::Exception const & )
2081 {
2082 OSL_ENSURE( sal_False, "Cannot delete source object!" );
2083 throw;
2084 }
2085 }
2086 }
2087