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/implbase.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <unotools/mediadescriptor.hxx>
25 #include <com/sun/star/document/XEmbeddedScripts.hpp>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/reflection/ProxyFactory.hpp>
29 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
30 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
31 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
33 #include <comphelper/diagnose_ex.hxx>
35 #include "BrowseNodeFactoryImpl.hxx"
36 #include <util/MiscUtils.hxx>
42 #include <string_view>
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::script
;
47 using namespace ::sf_misc
;
49 namespace browsenodefactory
52 class BrowseNodeAggregator
:
53 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
57 std::vector
< Reference
< browse::XBrowseNode
> > m_Nodes
;
61 explicit BrowseNodeAggregator( const Reference
< browse::XBrowseNode
>& node
)
62 : m_Name(node
->getName())
68 void addBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
70 m_Nodes
.push_back( node
);
74 SAL_CALL
getName() override
79 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
80 getChildNodes() override
82 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > > seqs
;
83 seqs
.reserve( m_Nodes
.size() );
85 sal_Int32 numChildren
= 0;
87 for (Reference
<XBrowseNode
> & xNode
: m_Nodes
)
89 Sequence
< Reference
< browse::XBrowseNode
> > children
;
92 children
= xNode
->getChildNodes();
93 seqs
.push_back( children
);
94 numChildren
+= children
.getLength();
98 // some form of exception getting child nodes so they
103 Sequence
< Reference
< browse::XBrowseNode
> > result( numChildren
);
105 for ( const Sequence
< Reference
< browse::XBrowseNode
> >& children
: seqs
)
107 std::copy(children
.begin(), children
.end(), std::next(result
.getArray(), index
));
108 index
+= children
.getLength();
110 if (index
>= numChildren
)
116 virtual sal_Bool SAL_CALL
117 hasChildNodes() override
119 for (Reference
<XBrowseNode
> & xNode
: m_Nodes
)
123 if ( xNode
->hasChildNodes() )
130 // some form of exception getting child nodes so move
131 // on to the next one
138 virtual sal_Int16 SAL_CALL
getType() override
140 return browse::BrowseNodeTypes::CONTAINER
;
146 bool operator()( std::u16string_view a
, std::u16string_view b
)
148 return a
.compare( b
) < 0;
151 class LocationBrowseNode
:
152 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
155 std::optional
<std::unordered_map
< OUString
, Reference
< browse::XBrowseNode
> >> m_hBNA
;
156 std::vector
< OUString
> m_vStr
;
157 OUString m_sNodeName
;
158 Reference
< browse::XBrowseNode
> m_origNode
;
162 explicit LocationBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
163 : m_sNodeName(node
->getName())
165 m_origNode
.set( node
);
171 virtual OUString SAL_CALL
getName() override
176 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
177 getChildNodes() override
184 Sequence
< Reference
< browse::XBrowseNode
> > children( m_hBNA
->size() );
185 auto childrenRange
= asNonConstRange(children
);
188 for ( const auto& str
: m_vStr
)
190 childrenRange
[ index
].set( m_hBNA
->find( str
)->second
);
197 virtual sal_Bool SAL_CALL
hasChildNodes() override
202 virtual sal_Int16 SAL_CALL
getType() override
204 return browse::BrowseNodeTypes::CONTAINER
;
209 void loadChildNodes()
213 const Sequence
< Reference
< browse::XBrowseNode
> > langNodes
=
214 m_origNode
->getChildNodes();
216 for ( const auto& rLangNode
: langNodes
)
218 Reference
< browse::XBrowseNode
> xbn
;
219 if ( rLangNode
->getName() == "uno_packages" )
221 xbn
.set( new LocationBrowseNode( rLangNode
) );
225 xbn
.set( rLangNode
);
228 const Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
229 xbn
->getChildNodes();
231 for ( const Reference
< browse::XBrowseNode
>& grandchild
: grandchildren
)
234 m_hBNA
->find( grandchild
->getName() );
236 if ( h_it
!= m_hBNA
->end() )
238 BrowseNodeAggregator
* bna
= static_cast< BrowseNodeAggregator
* >( h_it
->second
.get() );
239 bna
->addBrowseNode( grandchild
);
243 Reference
< browse::XBrowseNode
> bna(
244 new BrowseNodeAggregator( grandchild
) );
245 (*m_hBNA
)[ grandchild
->getName() ].set( bna
);
246 m_vStr
.push_back( grandchild
->getName() );
250 // sort children alphabetically
251 ::std::sort( m_vStr
.begin(), m_vStr
.end(), alphaSort() );
255 std::vector
< Reference
< browse::XBrowseNode
> > getAllBrowseNodes( const Reference
< XComponentContext
>& xCtx
)
257 const Sequence
< OUString
> openDocs
=
258 MiscUtils::allOpenTDocUrls( xCtx
);
260 Reference
< provider::XScriptProviderFactory
> xFac
;
261 sal_Int32 initialSize
= openDocs
.getLength() + 2;
262 sal_Int32 mspIndex
= 0;
264 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs( initialSize
);
267 xFac
= provider::theMasterScriptProviderFactory::get( xCtx
);
269 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( Any( u
"user"_ustr
) ), UNO_QUERY_THROW
);
270 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( Any( u
"share"_ustr
) ), UNO_QUERY_THROW
);
272 // TODO proper exception handling, should throw
273 catch( const Exception
& )
275 TOOLS_WARN_EXCEPTION("scripting", "Caught" );
276 locnBNs
.resize( mspIndex
);
280 for ( const auto& rDoc
: openDocs
)
284 Reference
< frame::XModel
> model( MiscUtils::tDocUrlToModel( rDoc
), UNO_SET_THROW
);
286 // #i44599 Check if it's a real document or something special like Hidden/Preview
287 css::uno::Reference
< css::frame::XController
> xCurrentController
= model
->getCurrentController();
288 if( xCurrentController
.is() )
290 utl::MediaDescriptor
aMD( model
->getArgs() );
291 bool bDefault
= false;
292 bool bHidden
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_HIDDEN
, bDefault
);
293 bool bPreview
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_PREVIEW
, bDefault
);
294 if( !bHidden
&& !bPreview
)
296 Reference
< document::XEmbeddedScripts
> xScripts( model
, UNO_QUERY
);
298 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( Any( model
) ), UNO_QUERY_THROW
);
302 catch( const Exception
& )
304 DBG_UNHANDLED_EXCEPTION("scripting");
309 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs_Return( mspIndex
);
310 for ( sal_Int32 j
= 0; j
< mspIndex
; j
++ )
311 locnBNs_Return
[j
] = locnBNs
[j
];
313 return locnBNs_Return
;
318 typedef ::std::vector
< Reference
< browse::XBrowseNode
> > vXBrowseNodes
;
322 struct alphaSortForBNodes
324 bool operator()( const Reference
< browse::XBrowseNode
>& a
, const Reference
< browse::XBrowseNode
>& b
)
326 return a
->getName().compareTo( b
->getName() ) < 0;
332 typedef ::cppu::WeakImplHelper
< browse::XBrowseNode
> t_BrowseNodeBase
;
336 class DefaultBrowseNode
:
337 public t_BrowseNodeBase
341 Reference
< browse::XBrowseNode
> m_xWrappedBrowseNode
;
342 Reference
< lang::XTypeProvider
> m_xWrappedTypeProv
;
343 Reference
< XAggregation
> m_xAggProxy
;
344 Reference
< XComponentContext
> m_xCtx
;
347 DefaultBrowseNode( const Reference
< XComponentContext
>& xCtx
, const Reference
< browse::XBrowseNode
>& xNode
) : m_xWrappedBrowseNode( xNode
), m_xWrappedTypeProv( xNode
, UNO_QUERY
), m_xCtx( xCtx
)
349 OSL_ENSURE( m_xWrappedBrowseNode
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
350 OSL_ENSURE( m_xWrappedTypeProv
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
351 OSL_ENSURE( m_xCtx
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
352 // Use proxy factory service to create aggregatable proxy.
355 Reference
< reflection::XProxyFactory
> xProxyFac
=
356 reflection::ProxyFactory::create( m_xCtx
);
357 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedBrowseNode
);
359 catch( uno::Exception
& )
361 TOOLS_WARN_EXCEPTION( "scripting", "DefaultBrowseNode::DefaultBrowseNode" );
363 OSL_ENSURE( m_xAggProxy
.is(),
364 "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
366 if ( !m_xAggProxy
.is() )
369 osl_atomic_increment( &m_refCount
);
371 /* i35609 - Fix crash on Solaris. The setDelegator call needs
372 to be in its own block to ensure that all temporary Reference
373 instances that are acquired during the call are released
374 before m_refCount is decremented again */
376 m_xAggProxy
->setDelegator(
380 osl_atomic_decrement( &m_refCount
);
383 virtual ~DefaultBrowseNode() override
385 if ( m_xAggProxy
.is() )
387 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
391 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
392 getChildNodes() override
394 if ( hasChildNodes() )
396 vXBrowseNodes aVNodes
;
397 const Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
398 m_xWrappedBrowseNode
->getChildNodes();
399 for ( const Reference
< browse::XBrowseNode
>& xBrowseNode
: nodes
)
401 OSL_ENSURE( xBrowseNode
.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
402 if( xBrowseNode
.is() )
403 aVNodes
.push_back( new DefaultBrowseNode( m_xCtx
, xBrowseNode
) );
406 ::std::sort( aVNodes
.begin(), aVNodes
.end(), alphaSortForBNodes() );
407 Sequence
< Reference
< browse::XBrowseNode
> > children( aVNodes
.size() );
408 auto childrenRange
= asNonConstRange(children
);
410 for ( const auto& rxNode
: aVNodes
)
412 childrenRange
[ i
].set( rxNode
);
421 Sequence
< Reference
< browse::XBrowseNode
> > none
;
426 virtual sal_Int16 SAL_CALL
getType() override
428 return m_xWrappedBrowseNode
->getType();
432 SAL_CALL
getName() override
434 return m_xWrappedBrowseNode
->getName();
437 virtual sal_Bool SAL_CALL
438 hasChildNodes() override
440 return m_xWrappedBrowseNode
->hasChildNodes();
444 virtual Any SAL_CALL
queryInterface( const Type
& aType
) override
446 Any aRet
= t_BrowseNodeBase::queryInterface( aType
);
447 if ( aRet
.hasValue() )
451 if ( m_xAggProxy
.is() )
453 return m_xAggProxy
->queryAggregation( aType
);
461 // XTypeProvider (implemented by base, but needs to be overridden for
462 // delegating to aggregate)
463 virtual Sequence
< Type
> SAL_CALL
getTypes() override
465 return m_xWrappedTypeProv
->getTypes();
467 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId() override
469 return css::uno::Sequence
<sal_Int8
>();
473 class DefaultRootBrowseNode
:
474 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
478 vXBrowseNodes m_vNodes
;
482 explicit DefaultRootBrowseNode( const Reference
< XComponentContext
>& xCtx
)
484 std::vector
< Reference
< browse::XBrowseNode
> > nodes
=
485 getAllBrowseNodes( xCtx
);
487 for (Reference
< browse::XBrowseNode
> & xNode
: nodes
)
489 m_vNodes
.push_back( new DefaultBrowseNode( xCtx
, xNode
) );
494 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
495 getChildNodes() override
497 // no need to sort user, share, doc1...docN
498 //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
499 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
500 auto childrenRange
= asNonConstRange(children
);
502 for ( const auto& rxNode
: m_vNodes
)
504 childrenRange
[ i
].set( rxNode
);
510 virtual sal_Int16 SAL_CALL
getType() override
512 return browse::BrowseNodeTypes::ROOT
;
516 SAL_CALL
getName() override
521 virtual sal_Bool SAL_CALL
522 hasChildNodes() override
525 if ( m_vNodes
.empty() )
534 class SelectorBrowseNode
:
535 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
538 Reference
< XComponentContext
> m_xComponentContext
;
541 explicit SelectorBrowseNode( const Reference
< XComponentContext
>& xContext
)
542 : m_xComponentContext( xContext
)
546 virtual OUString SAL_CALL
getName() override
551 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
552 getChildNodes() override
555 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs
= getAllBrowseNodes( m_xComponentContext
);
557 Sequence
< Reference
< browse::XBrowseNode
> > children(
559 auto childrenRange
= asNonConstRange(children
);
561 for ( size_t j
= 0; j
< locnBNs
.size(); j
++ )
563 childrenRange
[j
] = new LocationBrowseNode( locnBNs
[j
] );
569 virtual sal_Bool SAL_CALL
hasChildNodes() override
571 return true; // will always be user and share
574 virtual sal_Int16 SAL_CALL
getType() override
576 return browse::BrowseNodeTypes::CONTAINER
;
582 BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
583 Reference
< XComponentContext
> const & xComponentContext
)
584 : m_xComponentContext( xComponentContext
)
588 BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
593 // Implementation of XBrowseNodeFactory
597 * The selector hierarchy is the standard hierarchy for organizers with the
598 * language nodes removed.
600 Reference
< browse::XBrowseNode
> SAL_CALL
601 BrowseNodeFactoryImpl::createView( sal_Int16 viewType
)
605 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
:
606 return new SelectorBrowseNode( m_xComponentContext
);
607 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER
:
608 return getOrganizerHierarchy();
610 throw RuntimeException( u
"Unknown view type"_ustr
);
614 Reference
< browse::XBrowseNode
>
615 BrowseNodeFactoryImpl::getOrganizerHierarchy() const
617 Reference
< browse::XBrowseNode
> xRet
= new DefaultRootBrowseNode( m_xComponentContext
);
621 // Implementation of XServiceInfo
625 BrowseNodeFactoryImpl::getImplementationName()
627 return u
"com.sun.star.script.browse.BrowseNodeFactory"_ustr
;
630 Sequence
< OUString
> SAL_CALL
631 BrowseNodeFactoryImpl::getSupportedServiceNames()
633 return { u
"com.sun.star.script.browse.BrowseNodeFactory"_ustr
};
636 sal_Bool
BrowseNodeFactoryImpl::supportsService(OUString
const & serviceName
)
638 return cppu::supportsService(this, serviceName
);
641 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
642 scripting_BrowseNodeFactoryImpl_get_implementation(
643 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
645 return cppu::acquire(new BrowseNodeFactoryImpl(context
));
648 } // namespace browsenodefactory
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */