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