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