1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <cppuhelper/weakref.hxx>
22 #include <cppuhelper/implementationentry.hxx>
23 #include <cppuhelper/factory.hxx>
24 #include <cppuhelper/exc_hlp.hxx>
25 #include <cppuhelper/implbase1.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <unotools/mediadescriptor.hxx>
29 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/reflection/ProxyFactory.hpp>
33 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
34 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
35 #include <com/sun/star/document/XScriptInvocationContext.hpp>
37 #include <tools/diagnose_ex.h>
39 #include "BrowseNodeFactoryImpl.hxx"
40 #include "MasterScriptProvider.hxx"
41 #include "ActiveMSPList.hxx"
42 #include <util/MiscUtils.hxx>
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
48 using namespace ::com::sun::star::script
;
49 using namespace ::sf_misc
;
51 namespace browsenodefactory
53 class BrowseNodeAggregator
:
54 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
58 Sequence
< Reference
< browse::XBrowseNode
> > m_Nodes
;
62 BrowseNodeAggregator( const Reference
< browse::XBrowseNode
>& node
)
64 m_Name
= node
->getName();
69 virtual ~BrowseNodeAggregator()
73 void addBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
75 sal_Int32 index
= m_Nodes
.getLength();
77 m_Nodes
.realloc( index
+ 1 );
78 m_Nodes
[ index
] = node
;
83 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
88 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
90 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
92 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > > seqs
;
93 seqs
.reserve( m_Nodes
.getLength() );
95 sal_Int32 numChildren
= 0;
97 for ( sal_Int32 i
= 0; i
< m_Nodes
.getLength(); i
++ )
99 Sequence
< Reference
< browse::XBrowseNode
> > children
;
102 children
= m_Nodes
[ i
]->getChildNodes();
103 seqs
.push_back( children
);
104 numChildren
+= children
.getLength();
108 // some form of exception getting child nodes so they
109 // won't be displayed
113 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > >::const_iterator it
= seqs
.begin();
114 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > >::const_iterator it_end
= seqs
.end();
116 Sequence
< Reference
< browse::XBrowseNode
> > result( numChildren
);
117 for ( sal_Int32 index
= 0; it
!= it_end
&& index
< numChildren
; ++it
)
119 Sequence
< Reference
< browse::XBrowseNode
> > children
= *it
;
120 for ( sal_Int32 j
= 0; j
< children
.getLength(); j
++ )
122 result
[ index
++ ] = children
[ j
];
128 virtual sal_Bool SAL_CALL
130 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
132 if ( m_Nodes
.getLength() != 0 )
134 for ( sal_Int32 i
= 0 ; i
< m_Nodes
.getLength(); i
++ )
138 if ( m_Nodes
[ i
]->hasChildNodes() )
145 // some form of exception getting child nodes so move
146 // on to the next one
154 virtual sal_Int16 SAL_CALL
getType()
155 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
157 return browse::BrowseNodeTypes::CONTAINER
;
161 //typedef std::map< OUString, Reference< browse::XBrowseNode > >
162 typedef std::unordered_map
< OUString
, Reference
< browse::XBrowseNode
>,
163 OUStringHash
, ::std::equal_to
< OUString
> >
164 BrowseNodeAggregatorHash
;
165 typedef std::vector
< OUString
> vString
;
169 bool operator()( const OUString
& a
, const OUString
& b
)
171 return a
.compareTo( b
) < 0;
174 class LocationBrowseNode
:
175 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
178 BrowseNodeAggregatorHash
* m_hBNA
;
180 OUString m_sNodeName
;
181 Reference
< browse::XBrowseNode
> m_origNode
;
185 LocationBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
187 m_sNodeName
= node
->getName();
189 m_origNode
.set( node
);
192 virtual ~LocationBrowseNode()
204 virtual OUString SAL_CALL
getName()
205 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
210 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
212 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
214 if ( m_hBNA
== NULL
)
219 Sequence
< Reference
< browse::XBrowseNode
> > children( m_hBNA
->size() );
222 vString::const_iterator it
= m_vStr
.begin();
224 for ( ; it
!= m_vStr
.end(); ++it
, index
++ )
226 children
[ index
].set( m_hBNA
->find( *it
)->second
);
232 virtual sal_Bool SAL_CALL
hasChildNodes()
233 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
238 virtual sal_Int16 SAL_CALL
getType()
239 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
241 return browse::BrowseNodeTypes::CONTAINER
;
246 void loadChildNodes()
248 m_hBNA
= new BrowseNodeAggregatorHash();
250 Sequence
< Reference
< browse::XBrowseNode
> > langNodes
=
251 m_origNode
->getChildNodes();
253 for ( sal_Int32 i
= 0; i
< langNodes
.getLength(); i
++ )
255 Reference
< browse::XBrowseNode
> xbn
;
256 if ( langNodes
[ i
]->getName() == "uno_packages" )
258 xbn
.set( new LocationBrowseNode( langNodes
[ i
] ) );
262 xbn
.set( langNodes
[ i
] );
265 Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
266 xbn
->getChildNodes();
268 for ( sal_Int32 j
= 0; j
< grandchildren
.getLength(); j
++ )
270 Reference
< browse::XBrowseNode
> grandchild(grandchildren
[j
]);
272 BrowseNodeAggregatorHash::iterator h_it
=
273 m_hBNA
->find( grandchild
->getName() );
275 if ( h_it
!= m_hBNA
->end() )
277 BrowseNodeAggregator
* bna
= static_cast< BrowseNodeAggregator
* >( h_it
->second
.get() );
278 bna
->addBrowseNode( grandchild
);
282 Reference
< browse::XBrowseNode
> bna(
283 new BrowseNodeAggregator( grandchild
) );
284 (*m_hBNA
)[ grandchild
->getName() ].set( bna
);
285 m_vStr
.push_back( grandchild
->getName() );
289 // sort children alpahbetically
290 ::std::sort( m_vStr
.begin(), m_vStr
.end(), alphaSort() );
297 Sequence
< Reference
< browse::XBrowseNode
> > getAllBrowseNodes( const Reference
< XComponentContext
>& xCtx
)
299 Sequence
< OUString
> openDocs
=
300 MiscUtils::allOpenTDocUrls( xCtx
);
302 Reference
< provider::XScriptProviderFactory
> xFac
;
303 sal_Int32 initialSize
= openDocs
.getLength() + 2;
304 sal_Int32 mspIndex
= 0;
306 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs( initialSize
);
309 xFac
= provider::theMasterScriptProviderFactory::get( xCtx
);
311 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>( xFac
->createScriptProvider( makeAny( OUString("user") ) ), UNO_QUERY_THROW
);
312 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>( xFac
->createScriptProvider( makeAny( OUString("share") ) ), UNO_QUERY_THROW
);
314 // TODO proper exception handling, should throw
315 catch( const Exception
& e
)
318 OSL_TRACE("Caught Exception %s",
319 OUStringToOString( e
.Message
, RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
320 locnBNs
.realloc( mspIndex
);
324 for ( sal_Int32 i
= 0; i
< openDocs
.getLength(); i
++ )
328 Reference
< frame::XModel
> model( MiscUtils::tDocUrlToModel( openDocs
[ i
] ), UNO_QUERY_THROW
);
330 // #i44599 Check if it's a real document or something special like Hidden/Preview
331 css::uno::Reference
< css::frame::XController
> xCurrentController
= model
->getCurrentController();
332 if( xCurrentController
.is() )
334 utl::MediaDescriptor
aMD( model
->getArgs() );
335 bool bDefault
= false;
336 bool bHidden
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_HIDDEN(), bDefault
);
337 bool bPreview
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_PREVIEW(), bDefault
);
338 if( !bHidden
&& !bPreview
)
340 Reference
< document::XEmbeddedScripts
> xScripts( model
, UNO_QUERY
);
342 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>(
343 xFac
->createScriptProvider( makeAny( model
) ), UNO_QUERY_THROW
);
347 catch( const Exception
& )
349 DBG_UNHANDLED_EXCEPTION();
354 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs_Return( mspIndex
);
355 for ( sal_Int32 j
= 0; j
< mspIndex
; j
++ )
356 locnBNs_Return
[j
] = locnBNs
[j
];
358 return locnBNs_Return
;
363 typedef ::std::vector
< Reference
< browse::XBrowseNode
> > vXBrowseNodes
;
365 struct alphaSortForBNodes
367 bool operator()( const Reference
< browse::XBrowseNode
>& a
, const Reference
< browse::XBrowseNode
>& b
)
369 return a
->getName().compareTo( b
->getName() ) < 0;
373 typedef ::cppu::WeakImplHelper1
< browse::XBrowseNode
> t_BrowseNodeBase
;
374 class DefaultBrowseNode
:
375 public t_BrowseNodeBase
379 Reference
< browse::XBrowseNode
> m_xWrappedBrowseNode
;
380 Reference
< lang::XTypeProvider
> m_xWrappedTypeProv
;
381 Reference
< XAggregation
> m_xAggProxy
;
382 Reference
< XComponentContext
> m_xCtx
;
385 DefaultBrowseNode( const Reference
< XComponentContext
>& xCtx
, const Reference
< browse::XBrowseNode
>& xNode
) : m_xWrappedBrowseNode( xNode
), m_xWrappedTypeProv( xNode
, UNO_QUERY
), m_xCtx( xCtx
)
387 OSL_ENSURE( m_xWrappedBrowseNode
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
388 OSL_ENSURE( m_xWrappedTypeProv
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
389 OSL_ENSURE( m_xCtx
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
390 // Use proxy factory service to create aggregatable proxy.
393 Reference
< reflection::XProxyFactory
> xProxyFac
=
394 reflection::ProxyFactory::create( m_xCtx
);
395 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedBrowseNode
);
397 catch( uno::Exception
& )
399 OSL_FAIL( "DefaultBrowseNode::DefaultBrowseNode: Caught exception!" );
401 OSL_ENSURE( m_xAggProxy
.is(),
402 "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
404 if ( m_xAggProxy
.is() )
406 osl_atomic_increment( &m_refCount
);
408 /* i35609 - Fix crash on Solaris. The setDelegator call needs
409 to be in its own block to ensure that all temporary Reference
410 instances that are acquired during the call are released
411 before m_refCount is decremented again */
413 m_xAggProxy
->setDelegator(
414 static_cast< cppu::OWeakObject
* >( this ) );
417 osl_atomic_decrement( &m_refCount
);
421 virtual ~DefaultBrowseNode()
423 if ( m_xAggProxy
.is() )
425 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
429 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
431 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
433 if ( hasChildNodes() )
435 vXBrowseNodes m_vNodes
;
436 Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
437 m_xWrappedBrowseNode
->getChildNodes();
438 for ( sal_Int32 i
=0; i
<nodes
.getLength(); i
++ )
440 Reference
< browse::XBrowseNode
> xBrowseNode
= nodes
[ i
];
441 OSL_ENSURE( xBrowseNode
.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
442 if( xBrowseNode
.is() )
443 m_vNodes
.push_back( new DefaultBrowseNode( m_xCtx
, xBrowseNode
) );
446 ::std::sort( m_vNodes
.begin(), m_vNodes
.end(), alphaSortForBNodes() );
447 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
448 vXBrowseNodes::const_iterator it
= m_vNodes
.begin();
449 for ( sal_Int32 i
=0; it
!= m_vNodes
.end() && i
<children
.getLength(); i
++, ++it
)
451 children
[ i
].set( *it
);
459 Sequence
< Reference
< browse::XBrowseNode
> > none
;
464 virtual sal_Int16 SAL_CALL
getType()
465 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
467 return m_xWrappedBrowseNode
->getType();
472 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
474 return m_xWrappedBrowseNode
->getName();
477 virtual sal_Bool SAL_CALL
479 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
481 return m_xWrappedBrowseNode
->hasChildNodes();
485 virtual Any SAL_CALL
queryInterface( const Type
& aType
)
486 throw ( com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
488 Any aRet
= t_BrowseNodeBase::queryInterface( aType
);
489 if ( aRet
.hasValue() )
493 if ( m_xAggProxy
.is() )
495 return m_xAggProxy
->queryAggregation( aType
);
503 virtual void SAL_CALL
acquire()
504 throw () SAL_OVERRIDE
507 osl_atomic_increment( &m_refCount
);
509 virtual void SAL_CALL
release()
510 throw () SAL_OVERRIDE
512 if ( osl_atomic_decrement( &m_refCount
) == 0 )
517 // XTypeProvider (implemnented by base, but needs to be overridden for
518 // delegating to aggregate)
519 virtual Sequence
< Type
> SAL_CALL
getTypes()
520 throw ( com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
522 return m_xWrappedTypeProv
->getTypes();
524 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId()
525 throw ( com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
527 return css::uno::Sequence
<sal_Int8
>();
531 class DefaultRootBrowseNode
:
532 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
536 vXBrowseNodes m_vNodes
;
540 DefaultRootBrowseNode( const Reference
< XComponentContext
>& xCtx
)
542 Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
543 getAllBrowseNodes( xCtx
);
545 for ( sal_Int32 i
=0; i
<nodes
.getLength(); i
++ )
547 m_vNodes
.push_back( new DefaultBrowseNode( xCtx
, nodes
[ i
] ) );
552 virtual ~DefaultRootBrowseNode()
556 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
558 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
560 // no need to sort user, share, doc1...docN
561 //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
562 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
563 vXBrowseNodes::const_iterator it
= m_vNodes
.begin();
564 for ( sal_Int32 i
=0; it
!= m_vNodes
.end() && i
<children
.getLength(); i
++, ++it
)
566 children
[ i
].set( *it
);
571 virtual sal_Int16 SAL_CALL
getType()
572 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
574 return browse::BrowseNodeTypes::ROOT
;
579 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
584 virtual sal_Bool SAL_CALL
586 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
589 if ( !m_vNodes
.size() )
598 class SelectorBrowseNode
:
599 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
602 Reference
< XComponentContext
> m_xComponentContext
;
605 SelectorBrowseNode( const Reference
< XComponentContext
>& xContext
)
606 : m_xComponentContext( xContext
)
610 virtual ~SelectorBrowseNode()
614 virtual OUString SAL_CALL
getName()
615 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
617 return OUString("Root");
620 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
622 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
625 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs
= getAllBrowseNodes( m_xComponentContext
);
627 Sequence
< Reference
< browse::XBrowseNode
> > children(
628 locnBNs
.getLength() );
630 for ( sal_Int32 j
= 0; j
< locnBNs
.getLength(); j
++ )
632 children
[j
] = new LocationBrowseNode( locnBNs
[j
] );
638 virtual sal_Bool SAL_CALL
hasChildNodes()
639 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
641 return sal_True
; // will always be user and share
644 virtual sal_Int16 SAL_CALL
getType()
645 throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
647 return browse::BrowseNodeTypes::CONTAINER
;
651 BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
652 Reference
< XComponentContext
> const & xComponentContext
)
653 : m_xComponentContext( xComponentContext
)
657 BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
663 // Implementation of XBrowseNodeFactory
667 * The selector hierarchy is the standard hierarchy for organizers with the
668 * language nodes removed.
670 Reference
< browse::XBrowseNode
> SAL_CALL
671 BrowseNodeFactoryImpl::createView( sal_Int16 viewType
)
672 throw (RuntimeException
, std::exception
)
676 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
:
677 return getSelectorHierarchy();
678 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER
:
679 return getOrganizerHierarchy();
681 throw RuntimeException( "Unknown view type" );
685 Reference
< browse::XBrowseNode
>
686 BrowseNodeFactoryImpl::getSelectorHierarchy()
687 throw (RuntimeException
)
689 /*if ( !m_xSelectorBrowseNode.is() )
691 m_xSelectorBrowseNode = new SelectorBrowseNode( m_xComponentContext );
693 return new SelectorBrowseNode( m_xComponentContext
);
696 Reference
< browse::XBrowseNode
>
697 BrowseNodeFactoryImpl::getOrganizerHierarchy()
698 throw (RuntimeException
)
700 Reference
< browse::XBrowseNode
> xRet
= new DefaultRootBrowseNode( m_xComponentContext
);
708 // Namespace global methods for setting up BrowseNodeFactory service
711 Sequence
< OUString
> SAL_CALL
712 bnf_getSupportedServiceNames( )
715 "com.sun.star.script.browse.BrowseNodeFactory");
717 return Sequence
< OUString
>( &str_name
, 1 );
721 bnf_getImplementationName( )
724 "com.sun.star.script.browse.BrowseNodeFactory" );
727 Reference
< XInterface
> SAL_CALL
728 bnf_create( Reference
< XComponentContext
> const & xComponentContext
)
730 return static_cast< ::cppu::OWeakObject
* >(
731 new BrowseNodeFactoryImpl( xComponentContext
) );
735 // Implementation of XServiceInfo
739 BrowseNodeFactoryImpl::getImplementationName()
740 throw (RuntimeException
, std::exception
)
742 return bnf_getImplementationName();
745 Sequence
< OUString
> SAL_CALL
746 BrowseNodeFactoryImpl::getSupportedServiceNames()
747 throw (RuntimeException
, std::exception
)
749 return bnf_getSupportedServiceNames();
752 sal_Bool
BrowseNodeFactoryImpl::supportsService(OUString
const & serviceName
)
753 throw (RuntimeException
, std::exception
)
755 return cppu::supportsService(this, serviceName
);
758 } // namespace browsenodefactory
760 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */