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