Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : *************************************************************************/
26 : #include <osl/diagnose.h>
27 : #include <comphelper/processfactory.hxx>
28 : #include <cppuhelper/interfacecontainer.hxx>
29 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 : #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
31 : #include <com/sun/star/ucb/XCommandInfo.hpp>
32 : #include <com/sun/star/ucb/XContentProvider.hpp>
33 : #include <com/sun/star/ucb/XContentProviderSupplier.hpp>
34 : #include <com/sun/star/ucb/XParameterizedContentProvider.hpp>
35 : #include <com/sun/star/ucb/XContentProviderFactory.hpp>
36 : #include <com/sun/star/beans/PropertyValue.hpp>
37 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
38 : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39 : #include <com/sun/star/container/XNameAccess.hpp>
40 : #include <com/sun/star/uno/Any.hxx>
41 : #include <ucbhelper/cancelcommandexecution.hxx>
42 : #include "identify.hxx"
43 : #include "ucbcmds.hxx"
44 :
45 : #include "ucb.hxx"
46 :
47 : using namespace cppu;
48 : using namespace com::sun::star::uno;
49 : using namespace com::sun::star::lang;
50 : using namespace com::sun::star::ucb;
51 : using namespace ucb_impl;
52 : using namespace com::sun::star;
53 : using namespace ucbhelper;
54 :
55 :
56 : #define CONFIG_CONTENTPROVIDERS_KEY \
57 : "/org.openoffice.ucb.Configuration/ContentProviders"
58 :
59 :
60 : namespace {
61 :
62 1980 : bool fillPlaceholders(OUString const & rInput,
63 : uno::Sequence< uno::Any > const & rReplacements,
64 : OUString * pOutput)
65 : {
66 1980 : sal_Unicode const * p = rInput.getStr();
67 1980 : sal_Unicode const * pEnd = p + rInput.getLength();
68 1980 : sal_Unicode const * pCopy = p;
69 1980 : OUStringBuffer aBuffer;
70 3960 : while (p != pEnd)
71 0 : switch (*p++)
72 : {
73 : case '&':
74 0 : if (pEnd - p >= 4
75 0 : && p[0] == 'a' && p[1] == 'm' && p[2] == 'p'
76 0 : && p[3] == ';')
77 : {
78 0 : aBuffer.append(pCopy, p - 1 - pCopy);
79 0 : aBuffer.append('&');
80 0 : p += 4;
81 0 : pCopy = p;
82 : }
83 0 : else if (pEnd - p >= 3
84 0 : && p[0] == 'l' && p[1] == 't' && p[2] == ';')
85 : {
86 0 : aBuffer.append(pCopy, p - 1 - pCopy);
87 0 : aBuffer.append('<');
88 0 : p += 3;
89 0 : pCopy = p;
90 : }
91 0 : else if (pEnd - p >= 3
92 0 : && p[0] == 'g' && p[1] == 't' && p[2] == ';')
93 : {
94 0 : aBuffer.append(pCopy, p - 1 - pCopy);
95 0 : aBuffer.append('>');
96 0 : p += 3;
97 0 : pCopy = p;
98 : }
99 0 : break;
100 :
101 : case '<':
102 0 : sal_Unicode const * q = p;
103 0 : while (q != pEnd && *q != '>')
104 0 : ++q;
105 0 : if (q == pEnd)
106 0 : break;
107 0 : OUString aKey(p, q - p);
108 0 : OUString aValue;
109 0 : bool bFound = false;
110 0 : for (sal_Int32 i = 2; i + 1 < rReplacements.getLength();
111 : i += 2)
112 : {
113 0 : OUString aReplaceKey;
114 0 : if ((rReplacements[i] >>= aReplaceKey)
115 0 : && aReplaceKey == aKey
116 0 : && (rReplacements[i + 1] >>= aValue))
117 : {
118 0 : bFound = true;
119 0 : break;
120 : }
121 0 : }
122 0 : if (!bFound)
123 0 : return false;
124 0 : aBuffer.append(pCopy, p - 1 - pCopy);
125 0 : aBuffer.append(aValue);
126 0 : p = q + 1;
127 0 : pCopy = p;
128 0 : break;
129 : }
130 1980 : aBuffer.append(pCopy, pEnd - pCopy);
131 1980 : *pOutput = aBuffer.makeStringAndClear();
132 1980 : return true;
133 : }
134 :
135 2244 : void makeAndAppendXMLName(
136 : OUStringBuffer & rBuffer, const OUString & rIn )
137 : {
138 2244 : sal_Int32 nCount = rIn.getLength();
139 22704 : for ( sal_Int32 n = 0; n < nCount; ++n )
140 : {
141 20460 : const sal_Unicode c = rIn[ n ];
142 20460 : switch ( c )
143 : {
144 : case '&':
145 0 : rBuffer.appendAscii( "&" );
146 0 : break;
147 :
148 : case '"':
149 0 : rBuffer.appendAscii( """ );
150 0 : break;
151 :
152 : case '\'':
153 0 : rBuffer.appendAscii( "'" );
154 0 : break;
155 :
156 : case '<':
157 0 : rBuffer.appendAscii( "<" );
158 0 : break;
159 :
160 : case '>':
161 0 : rBuffer.appendAscii( ">" );
162 0 : break;
163 :
164 : default:
165 20460 : rBuffer.append( c );
166 20460 : break;
167 : }
168 : }
169 2244 : }
170 :
171 1980 : bool createContentProviderData(
172 : const OUString & rProvider,
173 : const uno::Reference< container::XHierarchicalNameAccess >& rxHierNameAccess,
174 : ContentProviderData & rInfo)
175 : {
176 : // Obtain service name.
177 1980 : OUStringBuffer aKeyBuffer (rProvider);
178 1980 : aKeyBuffer.appendAscii( "/ServiceName" );
179 :
180 3960 : OUString aValue;
181 : try
182 : {
183 3960 : if ( !( rxHierNameAccess->getByHierarchicalName(
184 3960 : aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
185 : {
186 : OSL_FAIL( "UniversalContentBroker::getContentProviderData - "
187 : "Error getting item value!" );
188 : }
189 : }
190 0 : catch (const container::NoSuchElementException&)
191 : {
192 0 : return false;
193 : }
194 :
195 1980 : rInfo.ServiceName = aValue;
196 :
197 : // Obtain URL Template.
198 1980 : aKeyBuffer.append(rProvider);
199 1980 : aKeyBuffer.appendAscii( "/URLTemplate" );
200 :
201 3960 : if ( !( rxHierNameAccess->getByHierarchicalName(
202 3960 : aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
203 : {
204 : OSL_FAIL( "UniversalContentBroker::getContentProviderData - "
205 : "Error getting item value!" );
206 : }
207 :
208 1980 : rInfo.URLTemplate = aValue;
209 :
210 : // Obtain Arguments.
211 1980 : aKeyBuffer.append(rProvider);
212 1980 : aKeyBuffer.appendAscii( "/Arguments" );
213 :
214 3960 : if ( !( rxHierNameAccess->getByHierarchicalName(
215 3960 : aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
216 : {
217 : OSL_FAIL( "UniversalContentBroker::getContentProviderData - "
218 : "Error getting item value!" );
219 : }
220 :
221 1980 : rInfo.Arguments = aValue;
222 3960 : return true;
223 : }
224 :
225 : }
226 :
227 :
228 :
229 : // UniversalContentBroker Implementation.
230 :
231 :
232 :
233 222 : UniversalContentBroker::UniversalContentBroker(
234 : const Reference< com::sun::star::uno::XComponentContext >& xContext )
235 : : m_xContext( xContext ),
236 : m_pDisposeEventListeners( NULL ),
237 : m_nInitCount( 0 ), //@@@ see initialize() method
238 222 : m_nCommandId( 0 )
239 : {
240 : OSL_ENSURE( m_xContext.is(),
241 : "UniversalContentBroker ctor: No service manager" );
242 222 : }
243 :
244 :
245 : // virtual
246 660 : UniversalContentBroker::~UniversalContentBroker()
247 : {
248 220 : delete m_pDisposeEventListeners;
249 440 : }
250 :
251 :
252 :
253 : // XInterface methods.
254 1480756 : void SAL_CALL UniversalContentBroker::acquire()
255 : throw()
256 : {
257 1480756 : OWeakObject::acquire();
258 1480756 : }
259 :
260 1480754 : void SAL_CALL UniversalContentBroker::release()
261 : throw()
262 : {
263 1480754 : OWeakObject::release();
264 1480754 : }
265 :
266 296458 : css::uno::Any SAL_CALL UniversalContentBroker::queryInterface( const css::uno::Type & rType )
267 : throw( css::uno::RuntimeException, std::exception )
268 : {
269 : css::uno::Any aRet = cppu::queryInterface( rType,
270 : (static_cast< XUniversalContentBroker* >(this)),
271 : (static_cast< XTypeProvider* >(this)),
272 : (static_cast< XComponent* >(this)),
273 : (static_cast< XServiceInfo* >(this)),
274 : (static_cast< XInitialization* >(this)),
275 : (static_cast< XContentProviderManager* >(this)),
276 : (static_cast< XContentProvider* >(this)),
277 : (static_cast< XContentIdentifierFactory* >(this)),
278 : (static_cast< XCommandProcessor* >(this))
279 296458 : );
280 296458 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
281 : }
282 :
283 : // XTypeProvider methods.
284 :
285 :
286 :
287 0 : XTYPEPROVIDER_IMPL_9( UniversalContentBroker,
288 : XUniversalContentBroker,
289 : XTypeProvider,
290 : XComponent,
291 : XServiceInfo,
292 : XInitialization,
293 : XContentProviderManager,
294 : XContentProvider,
295 : XContentIdentifierFactory,
296 : XCommandProcessor );
297 :
298 :
299 :
300 : // XComponent methods.
301 :
302 :
303 :
304 : // virtual
305 222 : void SAL_CALL UniversalContentBroker::dispose()
306 : throw( com::sun::star::uno::RuntimeException, std::exception )
307 : {
308 222 : if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
309 : {
310 1 : EventObject aEvt;
311 1 : aEvt.Source = (static_cast< XComponent* >(this));
312 1 : m_pDisposeEventListeners->disposeAndClear( aEvt );
313 : }
314 :
315 222 : if ( m_xNotifier.is() )
316 133 : m_xNotifier->removeChangesListener( this );
317 222 : }
318 :
319 :
320 : // virtual
321 2 : void SAL_CALL UniversalContentBroker::addEventListener(
322 : const Reference< XEventListener >& Listener )
323 : throw( com::sun::star::uno::RuntimeException, std::exception )
324 : {
325 2 : if ( !m_pDisposeEventListeners )
326 1 : m_pDisposeEventListeners = new OInterfaceContainerHelper( m_aMutex );
327 :
328 2 : m_pDisposeEventListeners->addInterface( Listener );
329 2 : }
330 :
331 :
332 : // virtual
333 1 : void SAL_CALL UniversalContentBroker::removeEventListener(
334 : const Reference< XEventListener >& Listener )
335 : throw( com::sun::star::uno::RuntimeException, std::exception )
336 : {
337 1 : if ( m_pDisposeEventListeners )
338 1 : m_pDisposeEventListeners->removeInterface( Listener );
339 :
340 : // Note: Don't want to delete empty container here -> performance.
341 1 : }
342 :
343 :
344 :
345 : // XServiceInfo methods.
346 :
347 :
348 :
349 1434 : XSERVICEINFO_IMPL_1_CTX( UniversalContentBroker,
350 : OUString( "com.sun.star.comp.ucb.UniversalContentBroker" ),
351 : UCB_SERVICE_NAME );
352 :
353 :
354 :
355 : // Service factory implementation.
356 :
357 :
358 :
359 222 : ONE_INSTANCE_SERVICE_FACTORY_IMPL( UniversalContentBroker );
360 :
361 :
362 :
363 : // XInitialization methods.
364 :
365 :
366 :
367 : // virtual
368 134 : void SAL_CALL UniversalContentBroker::initialize(
369 : const com::sun::star::uno::Sequence< Any >& aArguments )
370 : throw( com::sun::star::uno::Exception,
371 : com::sun::star::uno::RuntimeException, std::exception )
372 : {
373 : {
374 134 : osl::MutexGuard aGuard(m_aMutex);
375 134 : if (m_aArguments.getLength() != 0)
376 : {
377 2 : if (aArguments.getLength() != 0
378 1 : && !(m_aArguments.getLength() == 2
379 0 : && aArguments.getLength() == 2
380 0 : && m_aArguments[0] == aArguments[0]
381 0 : && m_aArguments[1] == aArguments[1]))
382 : {
383 : throw IllegalArgumentException(
384 : "UCB reinitialized with different arguments",
385 0 : static_cast< cppu::OWeakObject * >(this), 0);
386 : }
387 135 : return;
388 : }
389 133 : if (aArguments.getLength() == 0)
390 : {
391 133 : m_aArguments.realloc(2);
392 133 : m_aArguments[0] <<= OUString("Local");
393 133 : m_aArguments[1] <<= OUString("Office");
394 : }
395 : else
396 : {
397 0 : m_aArguments = aArguments;
398 133 : }
399 : }
400 133 : configureUcb();
401 : }
402 :
403 :
404 :
405 : // XContentProviderManager methods.
406 :
407 :
408 :
409 : // virtual
410 : Reference< XContentProvider > SAL_CALL
411 5580 : UniversalContentBroker::registerContentProvider(
412 : const Reference< XContentProvider >& Provider,
413 : const OUString& Scheme,
414 : sal_Bool ReplaceExisting )
415 : throw( DuplicateProviderException, com::sun::star::uno::RuntimeException, std::exception )
416 : {
417 5580 : osl::MutexGuard aGuard(m_aMutex);
418 :
419 11160 : ProviderMap_Impl::iterator aIt;
420 : try
421 : {
422 5580 : aIt = m_aProviders.find(Scheme);
423 : }
424 0 : catch (const IllegalArgumentException&)
425 : {
426 0 : return 0; //@@@
427 : }
428 :
429 11160 : Reference< XContentProvider > xPrevious;
430 5580 : if (aIt == m_aProviders.end())
431 : {
432 2126 : ProviderList_Impl aList;
433 2126 : aList.push_front(Provider);
434 : try
435 : {
436 2126 : m_aProviders.add(Scheme, aList, false);
437 : }
438 0 : catch (const IllegalArgumentException&)
439 : {
440 0 : return 0; //@@@
441 2126 : }
442 : }
443 : else
444 : {
445 3454 : if (!ReplaceExisting)
446 1 : throw DuplicateProviderException();
447 :
448 3453 : ProviderList_Impl & rList = aIt->getValue();
449 3453 : xPrevious = rList.front().getProvider();
450 3453 : rList.push_front(Provider);
451 : }
452 :
453 11159 : return xPrevious;
454 : }
455 :
456 :
457 : // virtual
458 2 : void SAL_CALL UniversalContentBroker::deregisterContentProvider(
459 : const Reference< XContentProvider >& Provider,
460 : const OUString& Scheme )
461 : throw( com::sun::star::uno::RuntimeException, std::exception )
462 : {
463 2 : osl::MutexGuard aGuard(m_aMutex);
464 :
465 4 : ProviderMap_Impl::iterator aMapIt;
466 : try
467 : {
468 2 : aMapIt = m_aProviders.find(Scheme);
469 : }
470 0 : catch (const IllegalArgumentException&)
471 : {
472 2 : return; //@@@
473 : }
474 :
475 2 : if (aMapIt != m_aProviders.end())
476 : {
477 2 : ProviderList_Impl & rList = aMapIt->getValue();
478 :
479 2 : ProviderList_Impl::iterator aListEnd(rList.end());
480 2 : for (ProviderList_Impl::iterator aListIt(rList.begin());
481 : aListIt != aListEnd; ++aListIt)
482 : {
483 2 : if ((*aListIt).getProvider() == Provider)
484 : {
485 2 : rList.erase(aListIt);
486 2 : break;
487 : }
488 : }
489 :
490 2 : if (rList.empty())
491 1 : m_aProviders.erase(aMapIt);
492 2 : }
493 : }
494 :
495 :
496 : // virtual
497 : com::sun::star::uno::Sequence< ContentProviderInfo > SAL_CALL
498 3 : UniversalContentBroker::queryContentProviders()
499 : throw( com::sun::star::uno::RuntimeException, std::exception )
500 : {
501 : // Return a list with information about active(!) content providers.
502 :
503 3 : osl::MutexGuard aGuard(m_aMutex);
504 :
505 : com::sun::star::uno::Sequence< ContentProviderInfo > aSeq(
506 3 : m_aProviders.size() );
507 3 : ContentProviderInfo* pInfo = aSeq.getArray();
508 :
509 6 : ProviderMap_Impl::const_iterator end = m_aProviders.end();
510 50 : for (ProviderMap_Impl::const_iterator it(m_aProviders.begin()); it != end;
511 : ++it)
512 : {
513 : // Note: Active provider is always the first list element.
514 47 : pInfo->ContentProvider = it->getValue().front().getProvider();
515 47 : pInfo->Scheme = it->getRegexp();
516 47 : ++pInfo;
517 3 : }
518 :
519 6 : return aSeq;
520 : }
521 :
522 :
523 : // virtual
524 : Reference< XContentProvider > SAL_CALL
525 138181 : UniversalContentBroker::queryContentProvider( const OUString&
526 : Identifier )
527 : throw( com::sun::star::uno::RuntimeException, std::exception )
528 : {
529 138181 : return queryContentProvider( Identifier, false );
530 : }
531 :
532 :
533 :
534 : // XContentProvider methods.
535 :
536 :
537 :
538 : // virtual
539 133919 : Reference< XContent > SAL_CALL UniversalContentBroker::queryContent(
540 : const Reference< XContentIdentifier >& Identifier )
541 : throw( IllegalIdentifierException, com::sun::star::uno::RuntimeException, std::exception )
542 : {
543 :
544 : // Let the content provider for the scheme given with the content
545 : // identifier create the XContent instance.
546 :
547 :
548 133919 : if ( !Identifier.is() )
549 0 : return Reference< XContent >();
550 :
551 : Reference< XContentProvider > xProv =
552 133919 : queryContentProvider( Identifier->getContentIdentifier(), true );
553 133919 : if ( xProv.is() )
554 127010 : return xProv->queryContent( Identifier );
555 :
556 6909 : return Reference< XContent >();
557 : }
558 :
559 :
560 : // virtual
561 863 : sal_Int32 SAL_CALL UniversalContentBroker::compareContentIds(
562 : const Reference< XContentIdentifier >& Id1,
563 : const Reference< XContentIdentifier >& Id2 )
564 : throw( com::sun::star::uno::RuntimeException, std::exception )
565 : {
566 863 : OUString aURI1( Id1->getContentIdentifier() );
567 1726 : OUString aURI2( Id2->getContentIdentifier() );
568 :
569 : Reference< XContentProvider > xProv1
570 1726 : = queryContentProvider( aURI1, true );
571 : Reference< XContentProvider > xProv2
572 1726 : = queryContentProvider( aURI2, true );
573 :
574 : // When both identifiers belong to the same provider, let that provider
575 : // compare them; otherwise, simply compare the URI strings (which must
576 : // be different):
577 863 : if ( xProv1.is() && ( xProv1 == xProv2 ) )
578 862 : return xProv1->compareContentIds( Id1, Id2 );
579 : else
580 864 : return aURI1.compareTo( aURI2 );
581 : }
582 :
583 :
584 :
585 : // XContentIdentifierFactory methods.
586 :
587 :
588 :
589 : // virtual
590 : Reference< XContentIdentifier > SAL_CALL
591 135659 : UniversalContentBroker::createContentIdentifier(
592 : const OUString& ContentId )
593 : throw( com::sun::star::uno::RuntimeException, std::exception )
594 : {
595 :
596 : // Let the content provider for the scheme given with content
597 : // identifier create the XContentIdentifier instance, if he supports
598 : // the XContentIdentifierFactory interface. Otherwise create standard
599 : // implementation object for XContentIdentifier.
600 :
601 :
602 135659 : Reference< XContentIdentifier > xIdentifier;
603 :
604 : Reference< XContentProvider > xProv
605 271318 : = queryContentProvider( ContentId, true );
606 135659 : if ( xProv.is() )
607 : {
608 128750 : Reference< XContentIdentifierFactory > xFac( xProv, UNO_QUERY );
609 128750 : if ( xFac.is() )
610 115089 : xIdentifier = xFac->createContentIdentifier( ContentId );
611 : }
612 :
613 135659 : if ( !xIdentifier.is() )
614 20570 : xIdentifier = new ContentIdentifier( ContentId );
615 :
616 271318 : return xIdentifier;
617 : }
618 :
619 :
620 :
621 : // XCommandProcessor methods.
622 :
623 :
624 :
625 : // virtual
626 0 : sal_Int32 SAL_CALL UniversalContentBroker::createCommandIdentifier()
627 : throw( RuntimeException, std::exception )
628 : {
629 0 : osl::MutexGuard aGuard( m_aMutex );
630 :
631 : // Just increase counter on every call to generate an identifier.
632 0 : return ++m_nCommandId;
633 : }
634 :
635 :
636 : // virtual
637 3569 : Any SAL_CALL UniversalContentBroker::execute(
638 : const Command& aCommand,
639 : sal_Int32,
640 : const Reference< XCommandEnvironment >& Environment )
641 : throw( Exception, CommandAbortedException, RuntimeException, std::exception )
642 : {
643 3569 : Any aRet;
644 :
645 :
646 : // Note: Don't forget to adapt ucb_commands::CommandProcessorInfo
647 : // ctor in ucbcmds.cxx when adding new commands!
648 :
649 :
650 3569 : if ( ( aCommand.Handle == GETCOMMANDINFO_HANDLE ) || aCommand.Name == GETCOMMANDINFO_NAME )
651 : {
652 :
653 : // getCommandInfo
654 :
655 :
656 0 : aRet <<= getCommandInfo();
657 : }
658 3569 : else if ( ( aCommand.Handle == GLOBALTRANSFER_HANDLE ) || aCommand.Name == GLOBALTRANSFER_NAME )
659 : {
660 :
661 : // globalTransfer
662 :
663 :
664 3569 : GlobalTransferCommandArgument2 aTransferArg;
665 3569 : if ( !( aCommand.Argument >>= aTransferArg ) )
666 : {
667 0 : GlobalTransferCommandArgument aArg;
668 0 : if ( !( aCommand.Argument >>= aArg ) )
669 : {
670 : ucbhelper::cancelCommandExecution(
671 : makeAny( IllegalArgumentException(
672 : OUString( "Wrong argument type!" ),
673 : static_cast< cppu::OWeakObject * >( this ),
674 : -1 ) ),
675 0 : Environment );
676 : // Unreachable
677 : }
678 :
679 : // Copy infos into the new structure
680 0 : aTransferArg.Operation = aArg.Operation;
681 0 : aTransferArg.SourceURL = aArg.SourceURL;
682 0 : aTransferArg.TargetURL = aArg.TargetURL;
683 0 : aTransferArg.NewTitle = aArg.NewTitle;
684 0 : aTransferArg.NameClash = aArg.NameClash;
685 : }
686 :
687 3571 : globalTransfer( aTransferArg, Environment );
688 : }
689 0 : else if ( ( aCommand.Handle == CHECKIN_HANDLE ) || aCommand.Name == CHECKIN_NAME )
690 : {
691 0 : ucb::CheckinArgument aCheckinArg;
692 0 : if ( !( aCommand.Argument >>= aCheckinArg ) )
693 : {
694 : ucbhelper::cancelCommandExecution(
695 : makeAny( IllegalArgumentException(
696 : OUString( "Wrong argument type!" ),
697 : static_cast< cppu::OWeakObject * >( this ),
698 : -1 ) ),
699 0 : Environment );
700 : // Unreachable
701 : }
702 0 : aRet <<= checkIn( aCheckinArg, Environment );
703 : }
704 : else
705 : {
706 :
707 : // Unknown command
708 :
709 :
710 : ucbhelper::cancelCommandExecution(
711 : makeAny( UnsupportedCommandException(
712 : OUString(),
713 : static_cast< cppu::OWeakObject * >( this ) ) ),
714 0 : Environment );
715 : // Unreachable
716 : }
717 :
718 3567 : return aRet;
719 : }
720 :
721 :
722 :
723 : // XCommandProcessor2 methods.
724 :
725 :
726 :
727 : // virtual
728 0 : void SAL_CALL UniversalContentBroker::releaseCommandIdentifier(sal_Int32 /*aCommandId*/)
729 : throw( RuntimeException, std::exception )
730 : {
731 : // @@@ Not implemeted ( yet).
732 0 : }
733 :
734 :
735 : // virtual
736 0 : void SAL_CALL UniversalContentBroker::abort( sal_Int32 )
737 : throw( RuntimeException, std::exception )
738 : {
739 : // @@@ Not implemeted ( yet).
740 0 : }
741 :
742 :
743 :
744 : // XChangesListener methods
745 :
746 :
747 : // virtual
748 0 : void SAL_CALL UniversalContentBroker::changesOccurred( const util::ChangesEvent& Event )
749 : throw( uno::RuntimeException, std::exception )
750 : {
751 0 : sal_Int32 nCount = Event.Changes.getLength();
752 0 : if ( nCount )
753 : {
754 0 : uno::Reference< container::XHierarchicalNameAccess > xHierNameAccess;
755 0 : Event.Base >>= xHierNameAccess;
756 :
757 : OSL_ASSERT( xHierNameAccess.is() );
758 :
759 : const util::ElementChange* pElementChanges
760 0 : = Event.Changes.getConstArray();
761 :
762 0 : ContentProviderDataList aData;
763 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
764 : {
765 0 : const util::ElementChange& rElem = pElementChanges[ n ];
766 0 : OUString aKey;
767 0 : rElem.Accessor >>= aKey;
768 :
769 0 : ContentProviderData aInfo;
770 :
771 : // Removal of UCPs from the configuration leads to changesOccurred
772 : // notifications, too, but it is hard to tell for a given
773 : // ElementChange whether it is an addition or a removal, so as a
774 : // heuristic consider as removals those that cause a
775 : // NoSuchElementException in createContentProviderData.
776 :
777 : // For now, removal of UCPs from the configuration is simply ignored
778 : // (and not reflected in the UCB's data structures):
779 0 : if (createContentProviderData(aKey, xHierNameAccess, aInfo))
780 : {
781 0 : aData.push_back(aInfo);
782 : }
783 0 : }
784 :
785 0 : prepareAndRegister(aData);
786 : }
787 0 : }
788 :
789 :
790 :
791 : // XEventListener methods
792 :
793 :
794 : // virtual
795 0 : void SAL_CALL UniversalContentBroker::disposing(const lang::EventObject&)
796 : throw( uno::RuntimeException, std::exception )
797 : {
798 0 : if ( m_xNotifier.is() )
799 : {
800 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
801 :
802 0 : if ( m_xNotifier.is() )
803 0 : m_xNotifier.clear();
804 : }
805 0 : }
806 :
807 :
808 :
809 : // Non-interface methods
810 :
811 :
812 :
813 409485 : Reference< XContentProvider > UniversalContentBroker::queryContentProvider(
814 : const OUString& Identifier,
815 : bool bResolved )
816 : {
817 409485 : osl::MutexGuard aGuard( m_aMutex );
818 :
819 409485 : ProviderList_Impl const * pList = m_aProviders.map( Identifier );
820 257486 : return pList ? bResolved ? pList->front().getResolvedProvider()
821 110795 : : pList->front().getProvider()
822 777766 : : Reference< XContentProvider >();
823 : }
824 :
825 133 : bool UniversalContentBroker::configureUcb()
826 : throw (uno::RuntimeException)
827 : {
828 133 : OUString aKey1;
829 266 : OUString aKey2;
830 266 : if (m_aArguments.getLength() < 2
831 133 : || !(m_aArguments[0] >>= aKey1) || !(m_aArguments[1] >>= aKey2))
832 : {
833 : OSL_FAIL("UniversalContentBroker::configureUcb(): Bad arguments");
834 0 : return false;
835 : }
836 :
837 266 : ContentProviderDataList aData;
838 133 : if (!getContentProviderData(aKey1, aKey2, aData))
839 : {
840 : OSL_TRACE("UniversalContentBroker::configureUcb(): No configuration");
841 1 : return false;
842 : }
843 :
844 132 : prepareAndRegister(aData);
845 :
846 265 : return true;
847 : }
848 :
849 132 : void UniversalContentBroker::prepareAndRegister(
850 : const ContentProviderDataList& rData)
851 : {
852 132 : ContentProviderDataList::const_iterator aEnd(rData.end());
853 2112 : for (ContentProviderDataList::const_iterator aIt(rData.begin());
854 : aIt != aEnd; ++aIt)
855 : {
856 1980 : OUString aProviderArguments;
857 3960 : if (fillPlaceholders(aIt->Arguments,
858 : m_aArguments,
859 3960 : &aProviderArguments))
860 : {
861 : registerAtUcb(this,
862 : m_xContext,
863 1980 : aIt->ServiceName,
864 : aProviderArguments,
865 3960 : aIt->URLTemplate);
866 :
867 : }
868 : else
869 : OSL_FAIL("UniversalContentBroker::prepareAndRegister(): Bad argument placeholders");
870 1980 : }
871 132 : }
872 :
873 :
874 133 : bool UniversalContentBroker::getContentProviderData(
875 : const OUString & rKey1,
876 : const OUString & rKey2,
877 : ContentProviderDataList & rListToFill )
878 : {
879 133 : if ( !m_xContext.is() || rKey1.isEmpty() || rKey2.isEmpty() )
880 : {
881 : OSL_FAIL( "UniversalContentBroker::getContentProviderData - Invalid argument!" );
882 0 : return false;
883 : }
884 :
885 : try
886 : {
887 : uno::Reference< lang::XMultiServiceFactory > xConfigProv =
888 133 : configuration::theDefaultProvider::get( m_xContext );
889 :
890 264 : OUStringBuffer aFullPath;
891 132 : aFullPath.appendAscii( CONFIG_CONTENTPROVIDERS_KEY "/['" );
892 132 : makeAndAppendXMLName( aFullPath, rKey1 );
893 132 : aFullPath.appendAscii( "']/SecondaryKeys/['" );
894 132 : makeAndAppendXMLName( aFullPath, rKey2 );
895 132 : aFullPath.appendAscii( "']/ProviderData" );
896 :
897 264 : uno::Sequence< uno::Any > aArguments( 1 );
898 264 : beans::PropertyValue aProperty;
899 132 : aProperty.Name = "nodepath";
900 132 : aProperty.Value <<= aFullPath.makeStringAndClear();
901 132 : aArguments[ 0 ] <<= aProperty;
902 :
903 : uno::Reference< uno::XInterface > xInterface(
904 132 : xConfigProv->createInstanceWithArguments(
905 : OUString( "com.sun.star.configuration.ConfigurationAccess" ),
906 264 : aArguments ) );
907 :
908 132 : if ( !m_xNotifier.is() )
909 : {
910 264 : m_xNotifier = uno::Reference< util::XChangesNotifier >(
911 132 : xInterface, uno::UNO_QUERY_THROW );
912 :
913 132 : m_xNotifier->addChangesListener( this );
914 : }
915 :
916 : uno::Reference< container::XNameAccess > xNameAccess(
917 264 : xInterface, uno::UNO_QUERY_THROW );
918 :
919 264 : uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
920 132 : const OUString* pElems = aElems.getConstArray();
921 132 : sal_Int32 nCount = aElems.getLength();
922 :
923 132 : if ( nCount > 0 )
924 : {
925 : uno::Reference< container::XHierarchicalNameAccess >
926 132 : xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
927 :
928 : // Iterate over children.
929 2112 : for ( sal_Int32 n = 0; n < nCount; ++n )
930 : {
931 :
932 : try
933 : {
934 :
935 1980 : ContentProviderData aInfo;
936 :
937 3960 : OUStringBuffer aElemBuffer;
938 1980 : aElemBuffer.appendAscii( "['" );
939 1980 : makeAndAppendXMLName( aElemBuffer, pElems[ n ] );
940 1980 : aElemBuffer.appendAscii( "']" );
941 :
942 1980 : OSL_VERIFY(
943 : createContentProviderData(
944 : aElemBuffer.makeStringAndClear(), xHierNameAccess,
945 : aInfo));
946 :
947 3960 : rListToFill.push_back( aInfo );
948 : }
949 0 : catch (const container::NoSuchElementException&)
950 : {
951 : // getByHierarchicalName
952 : OSL_FAIL( "UniversalContentBroker::getContentProviderData - "
953 : "caught NoSuchElementException!" );
954 : }
955 132 : }
956 132 : }
957 : }
958 2 : catch (const uno::RuntimeException&)
959 : {
960 : OSL_TRACE( "UniversalContentBroker::getContentProviderData - caught RuntimeException!" );
961 1 : return false;
962 : }
963 0 : catch (const uno::Exception&)
964 : {
965 : // createInstance, createInstanceWithArguments
966 :
967 : OSL_TRACE( "UniversalContentBroker::getContentProviderData - caught Exception!" );
968 0 : return false;
969 : }
970 :
971 132 : return true;
972 : }
973 :
974 :
975 :
976 : // ProviderListEntry_Impl implementation.
977 :
978 :
979 :
980 2317 : Reference< XContentProvider > ProviderListEntry_Impl::resolveProvider() const
981 : {
982 2317 : if ( !m_xResolvedProvider.is() )
983 : {
984 : Reference< XContentProviderSupplier > xSupplier(
985 2317 : m_xProvider, UNO_QUERY );
986 2317 : if ( xSupplier.is() )
987 320 : m_xResolvedProvider = xSupplier->getContentProvider();
988 :
989 2317 : if ( !m_xResolvedProvider.is() )
990 1997 : m_xResolvedProvider = m_xProvider;
991 : }
992 :
993 2317 : return m_xResolvedProvider;
994 : }
995 :
996 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|