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