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 6 : 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 6 : 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 6 : xOrigEnv( rxOrigEnv ), aArg( rArg ) {}
93 : };
94 :
95 : //=========================================================================
96 : //
97 : // class InteractionHandlerProxy.
98 : //
99 : //=========================================================================
100 :
101 6 : class InteractionHandlerProxy :
102 : public cppu::WeakImplHelper1< task::XInteractionHandler >
103 : {
104 : uno::Reference< task::XInteractionHandler > m_xOrig;
105 :
106 : public:
107 3 : InteractionHandlerProxy(
108 : const uno::Reference< task::XInteractionHandler > & xOrig )
109 3 : : 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 2 : void SAL_CALL InteractionHandlerProxy::handle(
120 : const uno::Reference< task::XInteractionRequest >& Request )
121 : throw ( uno::RuntimeException )
122 : {
123 2 : if ( !m_xOrig.is() )
124 3 : return;
125 :
126 : // Filter unwanted requests by just not handling them.
127 1 : uno::Any aRequest = Request->getRequest();
128 :
129 : // "transfer"
130 1 : ucb::InteractiveBadTransferURLException aBadTransferURLEx;
131 1 : if ( aRequest >>= aBadTransferURLEx )
132 : {
133 1 : 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 18 : 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 6 : void SAL_CALL ActiveDataSink::setInputStream(
191 : const uno::Reference< io::XInputStream >& aStream )
192 : throw( uno::RuntimeException )
193 : {
194 6 : m_xStream = aStream;
195 6 : }
196 :
197 : //=========================================================================
198 : // virtual
199 6 : uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream()
200 : throw( uno::RuntimeException )
201 : {
202 6 : 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 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 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 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 )
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 )
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 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 10 : OUString createDesiredName(
341 : const OUString & rSourceURL, const OUString & rNewTitle )
342 : {
343 10 : OUString aName( rNewTitle );
344 10 : 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 8 : sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' );
357 8 : bool bTrailingSlash = false;
358 8 : if ( nLastSlash == rSourceURL.getLength() - 1 )
359 : {
360 0 : nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash );
361 0 : bTrailingSlash = true;
362 : }
363 :
364 8 : if ( nLastSlash != -1 )
365 : {
366 8 : if ( bTrailingSlash )
367 0 : aName = rSourceURL.copy(
368 : nLastSlash + 1,
369 0 : rSourceURL.getLength() - nLastSlash - 2 );
370 : else
371 8 : aName = rSourceURL.copy( nLastSlash + 1 );
372 : }
373 : else
374 : {
375 0 : aName = rSourceURL;
376 : }
377 :
378 : // query, fragment present?
379 8 : sal_Int32 nPos = aName.indexOf( '?' );
380 8 : if ( nPos == -1 )
381 8 : nPos = aName.indexOf( '#' );
382 :
383 8 : if ( nPos != -1 )
384 0 : aName = aName.copy( 0, nPos );
385 : }
386 10 : return OUString( aName );
387 : }
388 :
389 10 : OUString createDesiredName(
390 : const ucb::GlobalTransferCommandArgument & rArg )
391 : {
392 10 : 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 : 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 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 : = OUString( "Title" );
489 0 : aPropValues[ 0 ].Handle = -1;
490 0 : aPropValues[ 0 ].Value = uno::makeAny( rNewTitle );
491 :
492 : ucb::Command aSetPropsCommand(
493 : 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 10 : 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 10 : xTarget, uno::UNO_QUERY );
545 10 : if ( !xCommandProcessorT.is() )
546 : {
547 : uno::Any aProps
548 : = uno::makeAny(beans::PropertyValue(
549 : 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 : OUString("Target is no XCommandProcessor!"),
558 0 : rContext.xProcessor );
559 : // Unreachable
560 : }
561 :
562 20 : uno::Sequence< beans::Property > aPropsToObtain( 1 );
563 10 : aPropsToObtain[ 0 ].Name
564 20 : = OUString("CreatableContentsInfo");
565 10 : aPropsToObtain[ 0 ].Handle
566 10 : = -1;
567 :
568 : ucb::Command aGetPropsCommand(
569 : OUString("getPropertyValues"),
570 : -1,
571 20 : uno::makeAny( aPropsToObtain ) );
572 :
573 20 : uno::Reference< sdbc::XRow > xRow;
574 10 : xCommandProcessorT->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
575 :
576 20 : uno::Sequence< ucb::ContentInfo > aTypesInfo;
577 10 : bool bGotTypesInfo = false;
578 :
579 10 : if ( xRow.is() )
580 : {
581 10 : uno::Any aValue = xRow->getObject(
582 10 : 1, uno::Reference< container::XNameAccess >() );
583 10 : if ( aValue.hasValue() && ( aValue >>= aTypesInfo ) )
584 : {
585 10 : bGotTypesInfo = true;
586 10 : }
587 : }
588 :
589 20 : uno::Reference< ucb::XContentCreator > xCreator;
590 :
591 10 : 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 : 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 : OUString("Target is no XContentCreator!"),
611 0 : rContext.xProcessor );
612 : // Unreachable
613 : }
614 :
615 0 : aTypesInfo = xCreator->queryCreatableContentsInfo();
616 : }
617 :
618 10 : sal_Int32 nCount = aTypesInfo.getLength();
619 10 : if ( !nCount )
620 : {
621 : uno::Any aProps
622 : = uno::makeAny(beans::PropertyValue(
623 : 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 : 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 10 : uno::Reference< ucb::XContent > xNew;
643 14 : for ( sal_Int32 n = 0; n < nCount; ++n )
644 : {
645 14 : sal_Int32 nAttribs = aTypesInfo[ n ].Attributes;
646 14 : sal_Bool bMatch = sal_False;
647 :
648 14 : 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 14 : else if ( ( rContext.aArg.Operation
659 14 : == ucb::TransferCommandOperation_COPY ) ||
660 : ( rContext.aArg.Operation
661 0 : == ucb::TransferCommandOperation_MOVE ) )
662 : {
663 : // Copy / Move
664 :
665 : // Is source a link? Create link in target folder then.
666 28 : 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 28 : if ( ( !!bSourceIsFolder ==
680 : !!( nAttribs
681 14 : & ucb::ContentInfoAttribute::KIND_FOLDER ) )
682 10 : &&
683 20 : ( !!bSourceIsDocument ==
684 : !!( nAttribs
685 10 : & ucb::ContentInfoAttribute::KIND_DOCUMENT ) )
686 : )
687 : {
688 : // Match!
689 10 : bMatch = sal_True;
690 : }
691 : }
692 : }
693 : else
694 : {
695 : ucbhelper::cancelCommandExecution(
696 : uno::makeAny( lang::IllegalArgumentException(
697 : OUString( "Unknown transfer operation!" ),
698 : rContext.xProcessor,
699 0 : -1 ) ),
700 0 : rContext.xOrigEnv );
701 : // Unreachable
702 : }
703 :
704 14 : if ( bMatch )
705 : {
706 : //////////////////////////////////////////////////////////////
707 : //
708 : // (3) Create a new, empty object of matched type.
709 : //
710 : //////////////////////////////////////////////////////////////
711 :
712 10 : if ( !xCreator.is() )
713 : {
714 : // First, try it using "CreatabeleContentsInfo" property and
715 : // "createNewContent" command -> the "new" way.
716 : ucb::Command aCreateNewCommand(
717 : OUString("createNewContent"),
718 : -1,
719 10 : uno::makeAny( aTypesInfo[ n ] ) );
720 :
721 10 : xCommandProcessorT->execute( aCreateNewCommand, 0, rContext.xEnv )
722 10 : >>= 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 10 : if ( !xNew.is() )
733 : {
734 : uno::Any aProps
735 : = uno::makeAny(
736 : beans::PropertyValue(
737 : 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 : OUString( "createNewContent failed!" ),
746 0 : rContext.xProcessor );
747 : // Unreachable
748 : }
749 10 : break; // escape from 'for' loop
750 : }
751 : } // for
752 :
753 20 : return xNew;
754 : }
755 :
756 : //=========================================================================
757 10 : 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 : OUString("getPropertySetInfo"),
765 : -1,
766 10 : uno::Any() );
767 :
768 20 : uno::Reference< beans::XPropertySetInfo > xInfo;
769 10 : xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv )
770 10 : >>= xInfo;
771 :
772 10 : if ( !xInfo.is() )
773 : {
774 : uno::Any aProps
775 : = uno::makeAny(beans::PropertyValue(
776 : 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 : OUString( "Unable to get propertyset info from source object!" ),
785 0 : rContext.xProcessor );
786 : // Unreachable
787 : }
788 :
789 20 : uno::Sequence< beans::Property > aAllProps = xInfo->getProperties();
790 :
791 : ucb::Command aGetPropsCommand1(
792 : OUString("getPropertyValues"),
793 : -1,
794 20 : uno::makeAny( aAllProps ) );
795 :
796 20 : uno::Reference< sdbc::XRow > xRow1;
797 10 : xCommandProcessorS->execute(
798 10 : aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1;
799 :
800 10 : if ( !xRow1.is() )
801 : {
802 : uno::Any aProps
803 : = uno::makeAny(beans::PropertyValue(
804 : 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 : 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 20 : aAllProps.getLength() + 2 );
822 :
823 10 : sal_Bool bHasTitle = rContext.aArg.NewTitle.isEmpty();
824 : sal_Bool bHasTargetURL = ( rContext.aArg.Operation
825 10 : != ucb::TransferCommandOperation_LINK );
826 :
827 10 : sal_Int32 nWritePos = 0;
828 90 : for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m )
829 : {
830 80 : const beans::Property & rCurrProp = aAllProps[ m ];
831 80 : beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ];
832 :
833 80 : uno::Any aValue;
834 :
835 80 : if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 )
836 : {
837 : // Supply new title, if given.
838 10 : if ( !bHasTitle )
839 : {
840 2 : bHasTitle = sal_True;
841 2 : aValue <<= rContext.aArg.NewTitle;
842 : }
843 : }
844 70 : 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 80 : if ( !aValue.hasValue() )
855 : {
856 : try
857 : {
858 234 : aValue = xRow1->getObject(
859 156 : 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 80 : if ( aValue.hasValue() )
869 : {
870 80 : rCurrValue.Name = rCurrProp.Name;
871 80 : rCurrValue.Handle = rCurrProp.Handle;
872 80 : rCurrValue.Value = aValue;
873 : // rCurrValue.State =
874 :
875 80 : nWritePos++;
876 : }
877 80 : }
878 :
879 : // Title needed, but not set yet?
880 10 : if ( !bHasTitle && !rContext.aArg.NewTitle.isEmpty() )
881 : {
882 0 : aPropValues[ nWritePos ].Name
883 0 : = 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 10 : if ( !bHasTargetURL && ( rContext.aArg.Operation
892 0 : == ucb::TransferCommandOperation_LINK ) )
893 : {
894 0 : aPropValues[ nWritePos ].Name
895 0 : = OUString("TargetURL");
896 0 : aPropValues[ nWritePos ].Handle = -1;
897 0 : aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL;
898 :
899 0 : nWritePos++;
900 : }
901 :
902 10 : aPropValues.realloc( nWritePos );
903 :
904 : // Set properties at new object.
905 :
906 : ucb::Command aSetPropsCommand(
907 : OUString("setPropertyValues"),
908 : -1,
909 20 : uno::makeAny( aPropValues ) );
910 :
911 20 : 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 10 : }
916 :
917 : //=========================================================================
918 6 : uno::Reference< io::XInputStream > getInputStream(
919 : const TransferCommandContext & rContext,
920 : const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
921 : throw( uno::Exception )
922 : {
923 6 : 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 6 : uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink;
934 :
935 12 : ucb::OpenCommandArgument2 aArg;
936 6 : aArg.Mode = ucb::OpenMode::DOCUMENT;
937 6 : aArg.Priority = 0; // unused
938 6 : aArg.Sink = xSink;
939 6 : aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused
940 :
941 : ucb::Command aOpenCommand(
942 : OUString("open"),
943 : -1,
944 12 : uno::makeAny( aArg ) );
945 :
946 6 : xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
947 12 : 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 6 : 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(rContext.m_xContext), 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 : OUString("open"),
978 : -1,
979 0 : uno::makeAny( aArg ) );
980 :
981 0 : xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
982 :
983 0 : 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 6 : return xInputStream;
997 : }
998 :
999 : //=========================================================================
1000 4 : uno::Reference< sdbc::XResultSet > getResultSet(
1001 : const TransferCommandContext & rContext,
1002 : const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
1003 : throw( uno::Exception )
1004 : {
1005 4 : uno::Reference< sdbc::XResultSet > xResultSet;
1006 :
1007 8 : uno::Sequence< beans::Property > aProps( 3 );
1008 :
1009 4 : aProps[ 0 ].Name = OUString("IsFolder");
1010 4 : aProps[ 0 ].Handle = -1; /* unknown */
1011 4 : aProps[ 1 ].Name = OUString("IsDocument");
1012 4 : aProps[ 1 ].Handle = -1; /* unknown */
1013 4 : aProps[ 2 ].Name = OUString("TargetURL");
1014 4 : aProps[ 2 ].Handle = -1; /* unknown */
1015 :
1016 8 : ucb::OpenCommandArgument2 aArg;
1017 4 : aArg.Mode = ucb::OpenMode::ALL;
1018 4 : aArg.Priority = 0; // unused
1019 4 : aArg.Sink = 0;
1020 4 : aArg.Properties = aProps;
1021 :
1022 : ucb::Command aOpenCommand( OUString("open"),
1023 : -1,
1024 8 : uno::makeAny( aArg ) );
1025 : try
1026 : {
1027 4 : uno::Reference< ucb::XDynamicResultSet > xSet;
1028 4 : xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet;
1029 :
1030 4 : if ( xSet.is() )
1031 4 : 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 8 : 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 = OUString("Title");
1061 0 : aProps[ 0 ].Handle = -1;
1062 :
1063 : ucb::Command aGetPropsCommand(
1064 : 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 : 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 : OUString( "Unable to get properties from new object!" ),
1086 0 : rContext.xProcessor );
1087 : // Unreachable
1088 : }
1089 :
1090 0 : OUString aOldTitle = xRow->getString( 1 );
1091 0 : if ( aOldTitle.isEmpty() )
1092 : {
1093 : ucbhelper::cancelCommandExecution(
1094 : uno::makeAny( beans::UnknownPropertyException(
1095 : 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 : OUString aOldTitlePre;
1103 0 : 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 += OUString("_");
1115 :
1116 0 : sal_Bool bContinue = sal_True;
1117 0 : do
1118 : {
1119 0 : nTry++;
1120 :
1121 0 : OUString aNewTitle = aOldTitlePre;
1122 0 : aNewTitle += 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 : 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 : 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 : 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 0 : while ( bContinue && ( nTry < 50 ) );
1204 :
1205 0 : if ( nTry == 50 )
1206 : {
1207 : ucbhelper::cancelCommandExecution(
1208 : uno::makeAny(
1209 : ucb::UnsupportedNameClashException(
1210 : 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 10 : 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 10 : sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 );
1228 10 : if ( !bSourceIsFolder && xSourceProps->wasNull() )
1229 : {
1230 : ucbhelper::cancelCommandExecution(
1231 : uno::makeAny( beans::UnknownPropertyException(
1232 : 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 10 : sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 );
1241 10 : if ( !bSourceIsDocument && xSourceProps->wasNull() )
1242 : {
1243 : ucbhelper::cancelCommandExecution(
1244 : uno::makeAny( beans::UnknownPropertyException(
1245 : 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 10 : 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 10 : bSourceIsLink );
1267 10 : if ( !xNew.is() )
1268 : {
1269 : uno::Any aProps
1270 : = uno::makeAny(beans::PropertyValue(
1271 : 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 : 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 20 : xNew, uno::UNO_QUERY );
1292 10 : if ( !xCommandProcessorN.is() )
1293 : {
1294 : uno::Any aProps
1295 : = uno::makeAny(beans::PropertyValue(
1296 : 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 : 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 20 : xSource, uno::UNO_QUERY );
1315 10 : if ( !xCommandProcessorS.is() )
1316 : {
1317 : uno::Any aProps
1318 : = uno::makeAny(beans::PropertyValue(
1319 : 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 : OUString( "Source content is not a XCommandProcessor!" ),
1328 0 : rContext.xProcessor );
1329 : // Unreachable
1330 : }
1331 :
1332 10 : transferProperties( rContext, xCommandProcessorS, xCommandProcessorN );
1333 :
1334 : //////////////////////////////////////////////////////////////////////
1335 : //
1336 : // (3) Try to obtain a data stream from source.
1337 : //
1338 : //////////////////////////////////////////////////////////////////////
1339 :
1340 20 : uno::Reference< io::XInputStream > xInputStream;
1341 :
1342 16 : if ( bSourceIsDocument && ( rContext.aArg.Operation
1343 6 : != ucb::TransferCommandOperation_LINK ) )
1344 6 : xInputStream = getInputStream( rContext, xCommandProcessorS );
1345 :
1346 : //////////////////////////////////////////////////////////////////////
1347 : //
1348 : // (4) Try to obtain a resultset (children) from source.
1349 : //
1350 : //////////////////////////////////////////////////////////////////////
1351 :
1352 20 : uno::Reference< sdbc::XResultSet > xResultSet;
1353 :
1354 14 : if ( bSourceIsFolder && ( rContext.aArg.Operation
1355 4 : != ucb::TransferCommandOperation_LINK ) )
1356 4 : xResultSet = getResultSet( rContext, xCommandProcessorS );
1357 :
1358 : //////////////////////////////////////////////////////////////////////
1359 : //
1360 : // (5) Insert (store) new content.
1361 : //
1362 : //////////////////////////////////////////////////////////////////////
1363 :
1364 20 : ucb::InsertCommandArgument2 aArg;
1365 10 : aArg.Data = xInputStream;
1366 10 : aArg.MimeType = rContext.aArg.MimeType;
1367 :
1368 10 : switch ( rContext.aArg.NameClash )
1369 : {
1370 : case ucb::NameClash::OVERWRITE:
1371 10 : aArg.ReplaceExisting = sal_True;
1372 10 : 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 10 : OUString aDesiredName = createDesiredName( rContext.aArg );
1388 :
1389 : bool bRetry;
1390 10 : do
1391 : {
1392 10 : bRetry = false;
1393 :
1394 : try
1395 : {
1396 : ucb::Command aInsertCommand(
1397 : OUString("insert"),
1398 : -1,
1399 10 : uno::makeAny( aArg ) );
1400 :
1401 10 : 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 : 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 : 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 : 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 : 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 : 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 : 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 10 : if ( xResultSet.is() )
1561 : {
1562 : try
1563 : {
1564 : // Iterate over children...
1565 :
1566 : uno::Reference< sdbc::XRow > xChildRow(
1567 4 : xResultSet, uno::UNO_QUERY );
1568 :
1569 4 : if ( !xChildRow.is() )
1570 : {
1571 : uno::Any aProps
1572 : = uno::makeAny(
1573 : beans::PropertyValue(
1574 : 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 : OUString( "Unable to get properties from children of source!" ),
1583 0 : rContext.xProcessor );
1584 : // Unreachable
1585 : }
1586 :
1587 : uno::Reference< ucb::XContentAccess > xChildAccess(
1588 8 : xResultSet, uno::UNO_QUERY );
1589 :
1590 4 : if ( !xChildAccess.is() )
1591 : {
1592 : uno::Any aProps
1593 : = uno::makeAny(
1594 : beans::PropertyValue(
1595 : 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 : OUString( "Unable to get children of source!" ),
1604 0 : rContext.xProcessor );
1605 : // Unreachable
1606 : }
1607 :
1608 4 : if ( xResultSet->first() )
1609 : {
1610 : ucb::GlobalTransferCommandArgument2 aTransArg(
1611 : rContext.aArg.Operation,
1612 : OUString(), // SourceURL; filled later
1613 4 : xNew->getIdentifier()
1614 8 : ->getContentIdentifier(), // TargetURL
1615 : OUString(), // NewTitle;
1616 : rContext.aArg.NameClash,
1617 12 : rContext.aArg.MimeType );
1618 :
1619 : TransferCommandContext aSubCtx(
1620 : rContext.m_xContext,
1621 : rContext.xProcessor,
1622 : rContext.xEnv,
1623 : rContext.xOrigEnv,
1624 8 : aTransArg );
1625 8 : do
1626 : {
1627 : uno::Reference< ucb::XContent > xChild
1628 8 : = xChildAccess->queryContent();
1629 8 : if ( xChild.is() )
1630 : {
1631 : // Recursion!
1632 :
1633 : aSubCtx.aArg.SourceURL
1634 8 : = xChild->getIdentifier()->getContentIdentifier();
1635 :
1636 : globalTransfer_( aSubCtx,
1637 : xChild,
1638 : xNew,
1639 8 : xChildRow );
1640 8 : }
1641 : }
1642 12 : while ( xResultSet->next() );
1643 4 : }
1644 : }
1645 0 : catch ( sdbc::SQLException const & )
1646 : {
1647 : }
1648 : }
1649 :
1650 : try {
1651 : uno::Reference< ucb::XCommandProcessor > xcp(
1652 10 : xTarget, uno::UNO_QUERY );
1653 :
1654 20 : uno::Any aAny;
1655 20 : uno::Reference< ucb::XCommandInfo > xci;
1656 10 : if(xcp.is())
1657 20 : aAny =
1658 10 : xcp->execute(
1659 : ucb::Command(
1660 : OUString("getCommandInfo"),
1661 : -1,
1662 : uno::Any()),
1663 : 0,
1664 20 : rContext.xEnv );
1665 :
1666 20 : const OUString cmdName("flush");
1667 10 : if((aAny >>= xci) && xci->hasCommandByName(cmdName))
1668 0 : xcp->execute(
1669 : ucb::Command(
1670 : cmdName,
1671 : -1,
1672 : uno::Any()) ,
1673 : 0,
1674 10 : rContext.xEnv );
1675 : }
1676 0 : catch( uno::Exception const & )
1677 : {
1678 20 : }
1679 10 : }
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 675 : 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 675 : uno::Reference< ucb::XCommandEnvironment > xLocalEnv;
1705 675 : if (xEnv.is())
1706 : {
1707 : xLocalEnv.set( ucb::CommandEnvironment::create(
1708 : m_xContext,
1709 6 : new InteractionHandlerProxy( xEnv->getInteractionHandler() ),
1710 9 : xEnv->getProgressHandler() ) );
1711 : }
1712 :
1713 : //////////////////////////////////////////////////////////////////////
1714 : //
1715 : // (1) Try to transfer the content using 'transfer' command.
1716 : //
1717 : //////////////////////////////////////////////////////////////////////
1718 :
1719 679 : uno::Reference< ucb::XContent > xTarget;
1720 : uno::Reference< ucb::XContentIdentifier > xId
1721 679 : = createContentIdentifier( rArg.TargetURL );
1722 675 : if ( xId.is() )
1723 : {
1724 : try
1725 : {
1726 675 : xTarget = queryContent( xId );
1727 : }
1728 0 : catch ( ucb::IllegalIdentifierException const & )
1729 : {
1730 : }
1731 : }
1732 :
1733 675 : if ( !xTarget.is() )
1734 : {
1735 : uno::Any aProps
1736 : = uno::makeAny(beans::PropertyValue(
1737 : OUString( "Uri"),
1738 : -1,
1739 : uno::makeAny(rArg.TargetURL),
1740 0 : beans::PropertyState_DIRECT_VALUE));
1741 : ucbhelper::cancelCommandExecution(
1742 : ucb::IOErrorCode_CANT_READ,
1743 : uno::Sequence< uno::Any >(&aProps, 1),
1744 : xEnv,
1745 : OUString( "Can't instanciate target object!" ),
1746 0 : this );
1747 : // Unreachable
1748 : }
1749 :
1750 675 : if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) ||
1751 0 : ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) )
1752 : {
1753 : uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1754 675 : xTarget, uno::UNO_QUERY );
1755 675 : if ( !xCommandProcessor.is() )
1756 : {
1757 : uno::Any aProps
1758 : = uno::makeAny(
1759 : beans::PropertyValue(
1760 : OUString( "Uri"),
1761 : -1,
1762 : uno::makeAny(rArg.TargetURL),
1763 0 : beans::PropertyState_DIRECT_VALUE));
1764 : ucbhelper::cancelCommandExecution(
1765 : ucb::IOErrorCode_CANT_READ,
1766 : uno::Sequence< uno::Any >(&aProps, 1),
1767 : xEnv,
1768 : OUString( "Target content is not a XCommandProcessor!" ),
1769 0 : this );
1770 : // Unreachable
1771 : }
1772 :
1773 : ucb::TransferInfo2 aTransferArg(
1774 : ( rArg.Operation
1775 675 : == ucb::TransferCommandOperation_MOVE ), // MoveData
1776 : rArg.SourceURL,
1777 : rArg.NewTitle,
1778 : rArg.NameClash,
1779 1354 : rArg.MimeType );
1780 :
1781 : bool bRetry;
1782 2 : do
1783 : {
1784 675 : bRetry = false;
1785 :
1786 : try
1787 : {
1788 : ucb::Command aCommand(
1789 : OUString( "transfer" ), // Name
1790 : -1, // Handle
1791 675 : uno::makeAny( aTransferArg ) ); // Argument
1792 :
1793 675 : xCommandProcessor->execute( aCommand, 0, xLocalEnv );
1794 :
1795 : // Command succeeded. We're done.
1796 675 : return;
1797 : }
1798 2 : catch ( ucb::InteractiveBadTransferURLException const & )
1799 : {
1800 : // Source URL is not supported by target. Try to transfer
1801 : // the content "manually".
1802 : }
1803 0 : catch ( ucb::UnsupportedCommandException const & )
1804 : {
1805 : // 'transfer' command is not supported by commandprocessor.
1806 : // Try to transfer manually.
1807 : }
1808 0 : catch ( ucb::UnsupportedNameClashException const & exc )
1809 : {
1810 : OSL_ENSURE( aTransferArg.NameClash == exc.NameClash,
1811 : "nameclash mismatch!" );
1812 0 : if ( exc.NameClash == ucb::NameClash::ASK )
1813 : {
1814 : // Try to detect a name clash by invoking "transfer" with
1815 : // NameClash::ERROR.
1816 : try
1817 : {
1818 : ucb::TransferInfo2 aTransferArg1(
1819 : aTransferArg.MoveData,
1820 : aTransferArg.SourceURL,
1821 : aTransferArg.NewTitle,
1822 : ucb::NameClash::ERROR,
1823 0 : aTransferArg.MimeType );
1824 :
1825 : ucb::Command aCommand1(
1826 : OUString("transfer"),
1827 : -1,
1828 0 : uno::makeAny( aTransferArg1 ) );
1829 :
1830 0 : xCommandProcessor->execute( aCommand1, 0, xLocalEnv );
1831 :
1832 : // Command succeeded. We're done.
1833 0 : return;
1834 : }
1835 0 : catch ( ucb::UnsupportedNameClashException const & )
1836 : {
1837 : // No chance to solve name clashes, because I'm not
1838 : // able to detect whether there is one.
1839 0 : throw exc; // Not just 'throw;'!
1840 : }
1841 0 : catch ( ucb::NameClashException const & )
1842 : {
1843 : // There's a clash. Use interaction handler to solve it.
1844 :
1845 0 : uno::Any aExc;
1846 0 : OUString aNewTitle;
1847 : NameClashContinuation eCont
1848 : = interactiveNameClashResolve(
1849 : xEnv, // always use original environment!
1850 : rArg.TargetURL, // target folder URL
1851 : createDesiredName(
1852 : aTransferArg ), // clashing name
1853 : aExc,
1854 0 : aNewTitle );
1855 :
1856 0 : switch ( eCont )
1857 : {
1858 : case NOT_HANDLED:
1859 : // Not handled.
1860 0 : cppu::throwException( aExc );
1861 : // break;
1862 :
1863 : case UNKNOWN:
1864 : // Handled, but not clear, how...
1865 : // fall-thru intended.
1866 :
1867 : case ABORT:
1868 : throw ucb::CommandFailedException(
1869 : OUString(
1870 : "abort requested via interaction "
1871 : "handler" ),
1872 : uno::Reference< uno::XInterface >(),
1873 0 : aExc );
1874 : // break;
1875 :
1876 : case OVERWRITE:
1877 : aTransferArg.NameClash
1878 0 : = ucb::NameClash::OVERWRITE;
1879 0 : bRetry = true;
1880 0 : break;
1881 :
1882 : case NEW_NAME:
1883 0 : aTransferArg.NewTitle = aNewTitle;
1884 0 : bRetry = true;
1885 0 : break;
1886 : }
1887 :
1888 0 : OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1889 : }
1890 : }
1891 : else
1892 : {
1893 0 : throw;
1894 : }
1895 0 : }
1896 : }
1897 4 : while ( bRetry );
1898 : }
1899 :
1900 : //////////////////////////////////////////////////////////////////////
1901 : //
1902 : // (2) Try to transfer the content "manually".
1903 : //
1904 : //////////////////////////////////////////////////////////////////////
1905 :
1906 2 : uno::Reference< ucb::XContent > xSource;
1907 : try
1908 : {
1909 : uno::Reference< ucb::XContentIdentifier > xId2
1910 2 : = createContentIdentifier( rArg.SourceURL );
1911 2 : if ( xId2.is() )
1912 2 : xSource = queryContent( xId2 );
1913 : }
1914 0 : catch ( ucb::IllegalIdentifierException const & )
1915 : {
1916 : // Error handling via "if ( !xSource.is() )" below.
1917 : }
1918 :
1919 2 : if ( !xSource.is() )
1920 : {
1921 : uno::Any aProps
1922 : = uno::makeAny(beans::PropertyValue(
1923 : OUString( "Uri"),
1924 : -1,
1925 : uno::makeAny(rArg.SourceURL),
1926 0 : beans::PropertyState_DIRECT_VALUE));
1927 : ucbhelper::cancelCommandExecution(
1928 : ucb::IOErrorCode_CANT_READ,
1929 : uno::Sequence< uno::Any >(&aProps, 1),
1930 : xEnv,
1931 : OUString( "Can't instanciate source object!" ),
1932 0 : this );
1933 : // Unreachable
1934 : }
1935 :
1936 : uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1937 4 : xSource, uno::UNO_QUERY );
1938 2 : if ( !xCommandProcessor.is() )
1939 : {
1940 : uno::Any aProps
1941 : = uno::makeAny(beans::PropertyValue(
1942 : OUString( "Uri"),
1943 : -1,
1944 : uno::makeAny(rArg.SourceURL),
1945 0 : beans::PropertyState_DIRECT_VALUE));
1946 : ucbhelper::cancelCommandExecution(
1947 : ucb::IOErrorCode_CANT_READ,
1948 : uno::Sequence< uno::Any >(&aProps, 1),
1949 : xEnv,
1950 : OUString( "Source content is not a XCommandProcessor!" ),
1951 0 : this );
1952 : // Unreachable
1953 : }
1954 :
1955 : // Obtain interesting property values from source...
1956 :
1957 4 : uno::Sequence< beans::Property > aProps( 4 );
1958 :
1959 2 : aProps[ 0 ].Name = OUString("IsFolder");
1960 2 : aProps[ 0 ].Handle = -1; /* unknown */
1961 2 : aProps[ 1 ].Name = OUString("IsDocument");
1962 2 : aProps[ 1 ].Handle = -1; /* unknown */
1963 2 : aProps[ 2 ].Name = OUString("TargetURL");
1964 2 : aProps[ 2 ].Handle = -1; /* unknown */
1965 2 : aProps[ 3 ].Name = OUString("BaseURI");
1966 2 : aProps[ 3 ].Handle = -1; /* unknown */
1967 :
1968 : ucb::Command aGetPropsCommand(
1969 : OUString("getPropertyValues"),
1970 : -1,
1971 4 : uno::makeAny( aProps ) );
1972 :
1973 4 : uno::Reference< sdbc::XRow > xRow;
1974 2 : xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow;
1975 :
1976 2 : if ( !xRow.is() )
1977 : {
1978 : uno::Any aProps2
1979 : = uno::makeAny(beans::PropertyValue(
1980 : OUString( "Uri"),
1981 : -1,
1982 : uno::makeAny(rArg.SourceURL),
1983 0 : beans::PropertyState_DIRECT_VALUE));
1984 : ucbhelper::cancelCommandExecution(
1985 : ucb::IOErrorCode_CANT_READ,
1986 : uno::Sequence< uno::Any >(&aProps2, 1),
1987 : xEnv,
1988 : OUString( "Unable to get properties from source object!" ),
1989 0 : this );
1990 : // Unreachable
1991 : }
1992 :
1993 : TransferCommandContext aTransferCtx(
1994 4 : m_xContext, this, xLocalEnv, xEnv, rArg );
1995 :
1996 2 : if ( rArg.NewTitle.isEmpty() )
1997 : {
1998 : // BaseURI: property is optional.
1999 0 : OUString aBaseURI( xRow->getString( 4 ) );
2000 0 : if ( !aBaseURI.isEmpty() )
2001 : {
2002 : aTransferCtx.aArg.NewTitle
2003 0 : = createDesiredName( aBaseURI, OUString() );
2004 0 : }
2005 : }
2006 :
2007 : // Do it!
2008 2 : globalTransfer_( aTransferCtx, xSource, xTarget, xRow );
2009 :
2010 : //////////////////////////////////////////////////////////////////////
2011 : //
2012 : // (3) Delete source, if operation is MOVE.
2013 : //
2014 : //////////////////////////////////////////////////////////////////////
2015 :
2016 2 : if ( rArg.Operation == ucb::TransferCommandOperation_MOVE )
2017 : {
2018 : try
2019 : {
2020 : ucb::Command aCommand(
2021 : OUString("delete"), // Name
2022 : -1, // Handle
2023 0 : uno::makeAny( sal_Bool( sal_True ) ) ); // Argument
2024 :
2025 0 : xCommandProcessor->execute( aCommand, 0, xLocalEnv );
2026 : }
2027 0 : catch ( uno::Exception const & )
2028 : {
2029 : OSL_FAIL( "Cannot delete source object!" );
2030 0 : throw;
2031 : }
2032 6 : }
2033 : }
2034 :
2035 0 : uno::Any UniversalContentBroker::checkIn( const ucb::CheckinArgument& rArg,
2036 : const uno::Reference< ucb::XCommandEnvironment >& xEnv ) throw ( uno::Exception )
2037 : {
2038 0 : uno::Any aRet;
2039 : // Use own command environment with own interaction handler intercepting
2040 : // some interaction requests that shall not be handled by the user-supplied
2041 : // interaction handler.
2042 0 : uno::Reference< ucb::XCommandEnvironment > xLocalEnv;
2043 0 : if (xEnv.is())
2044 : {
2045 : xLocalEnv.set( ucb::CommandEnvironment::create(
2046 : m_xContext,
2047 0 : new InteractionHandlerProxy( xEnv->getInteractionHandler() ),
2048 0 : xEnv->getProgressHandler() ) );
2049 : }
2050 :
2051 0 : uno::Reference< ucb::XContent > xTarget;
2052 : uno::Reference< ucb::XContentIdentifier > xId
2053 0 : = createContentIdentifier( rArg.TargetURL );
2054 0 : if ( xId.is() )
2055 : {
2056 : try
2057 : {
2058 0 : xTarget = queryContent( xId );
2059 : }
2060 0 : catch ( ucb::IllegalIdentifierException const & )
2061 : {
2062 : }
2063 : }
2064 :
2065 0 : if ( !xTarget.is() )
2066 : {
2067 : uno::Any aProps
2068 : = uno::makeAny(beans::PropertyValue(
2069 : OUString( "Uri" ), -1,
2070 : uno::makeAny( rArg.TargetURL ),
2071 0 : beans::PropertyState_DIRECT_VALUE ) );
2072 : ucbhelper::cancelCommandExecution(
2073 : ucb::IOErrorCode_CANT_READ,
2074 : uno::Sequence< uno::Any >( &aProps, 1 ),
2075 : xEnv,
2076 : OUString( "Can't instanciate target object!" ),
2077 0 : this );
2078 : // Unreachable
2079 : }
2080 :
2081 : uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
2082 0 : xTarget, uno::UNO_QUERY );
2083 0 : if ( !xCommandProcessor.is() )
2084 : {
2085 : uno::Any aProps
2086 : = uno::makeAny(
2087 : beans::PropertyValue(
2088 : OUString( "Uri" ), -1,
2089 : uno::makeAny( rArg.TargetURL ),
2090 0 : beans::PropertyState_DIRECT_VALUE ) );
2091 : ucbhelper::cancelCommandExecution(
2092 : ucb::IOErrorCode_CANT_READ,
2093 : uno::Sequence< uno::Any >( &aProps, 1 ),
2094 : xEnv,
2095 : OUString( "Target content is not a XCommandProcessor!" ),
2096 0 : this );
2097 : // Unreachable
2098 : }
2099 :
2100 : try
2101 : {
2102 : ucb::Command aCommand(
2103 : OUString( "checkin" ), -1,
2104 0 : uno::makeAny( rArg ) );
2105 :
2106 0 : aRet = xCommandProcessor->execute( aCommand, 0, xLocalEnv );
2107 : }
2108 0 : catch ( ucb::UnsupportedCommandException const & )
2109 : {
2110 : // 'checkin' command is not supported by commandprocessor:
2111 : // ignore.
2112 : }
2113 0 : return aRet;
2114 : }
2115 :
2116 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|