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