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/frame/XModel.hpp>
26 #include <com/sun/star/reflection/ProxyFactory.hpp>
28 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
29 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
30 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
32 #include <tools/diagnose_ex.h>
34 #include "BrowseNodeFactoryImpl.hxx"
35 #include "MasterScriptProvider.hxx"
36 #include <util/MiscUtils.hxx>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::script
;
45 using namespace ::sf_misc
;
47 namespace browsenodefactory
50 class BrowseNodeAggregator
:
51 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
55 std::vector
< Reference
< browse::XBrowseNode
> > m_Nodes
;
59 explicit BrowseNodeAggregator( const Reference
< browse::XBrowseNode
>& node
)
60 : m_Name(node
->getName())
66 void addBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
68 m_Nodes
.push_back( node
);
72 SAL_CALL
getName() override
77 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
78 getChildNodes() override
80 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > > seqs
;
81 seqs
.reserve( m_Nodes
.size() );
83 sal_Int32 numChildren
= 0;
85 for (Reference
<XBrowseNode
> & xNode
: m_Nodes
)
87 Sequence
< Reference
< browse::XBrowseNode
> > children
;
90 children
= xNode
->getChildNodes();
91 seqs
.push_back( children
);
92 numChildren
+= children
.getLength();
96 // some form of exception getting child nodes so they
101 Sequence
< Reference
< browse::XBrowseNode
> > result( numChildren
);
103 for ( Sequence
< Reference
< browse::XBrowseNode
> >& children
: seqs
)
105 std::copy(children
.begin(), children
.end(), std::next(result
.begin(), index
));
106 index
+= children
.getLength();
108 if (index
>= numChildren
)
114 virtual sal_Bool SAL_CALL
115 hasChildNodes() override
117 for (Reference
<XBrowseNode
> & xNode
: m_Nodes
)
121 if ( xNode
->hasChildNodes() )
128 // some form of exception getting child nodes so move
129 // on to the next one
136 virtual sal_Int16 SAL_CALL
getType() override
138 return browse::BrowseNodeTypes::CONTAINER
;
144 bool operator()( const OUString
& a
, const OUString
& b
)
146 return a
.compareTo( b
) < 0;
149 class LocationBrowseNode
:
150 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
153 std::unique_ptr
<std::unordered_map
< OUString
, Reference
< browse::XBrowseNode
> >> m_hBNA
;
154 std::vector
< OUString
> m_vStr
;
155 OUString m_sNodeName
;
156 Reference
< browse::XBrowseNode
> m_origNode
;
160 explicit LocationBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
161 : m_sNodeName(node
->getName())
163 m_origNode
.set( node
);
169 virtual OUString SAL_CALL
getName() override
174 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
175 getChildNodes() override
177 if ( m_hBNA
== nullptr )
182 Sequence
< Reference
< browse::XBrowseNode
> > children( m_hBNA
->size() );
185 for ( const auto& str
: m_vStr
)
187 children
[ index
].set( m_hBNA
->find( str
)->second
);
194 virtual sal_Bool SAL_CALL
hasChildNodes() override
199 virtual sal_Int16 SAL_CALL
getType() override
201 return browse::BrowseNodeTypes::CONTAINER
;
206 void loadChildNodes()
208 m_hBNA
.reset( new std::unordered_map
< OUString
, Reference
< browse::XBrowseNode
> > );
210 const Sequence
< Reference
< browse::XBrowseNode
> > langNodes
=
211 m_origNode
->getChildNodes();
213 for ( const auto& rLangNode
: langNodes
)
215 Reference
< browse::XBrowseNode
> xbn
;
216 if ( rLangNode
->getName() == "uno_packages" )
218 xbn
.set( new LocationBrowseNode( rLangNode
) );
222 xbn
.set( rLangNode
);
225 const Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
226 xbn
->getChildNodes();
228 for ( const Reference
< browse::XBrowseNode
>& grandchild
: grandchildren
)
231 m_hBNA
->find( grandchild
->getName() );
233 if ( h_it
!= m_hBNA
->end() )
235 BrowseNodeAggregator
* bna
= static_cast< BrowseNodeAggregator
* >( h_it
->second
.get() );
236 bna
->addBrowseNode( grandchild
);
240 Reference
< browse::XBrowseNode
> bna(
241 new BrowseNodeAggregator( grandchild
) );
242 (*m_hBNA
)[ grandchild
->getName() ].set( bna
);
243 m_vStr
.push_back( grandchild
->getName() );
247 // sort children alphabetically
248 ::std::sort( m_vStr
.begin(), m_vStr
.end(), alphaSort() );
252 std::vector
< Reference
< browse::XBrowseNode
> > getAllBrowseNodes( const Reference
< XComponentContext
>& xCtx
)
254 const Sequence
< OUString
> openDocs
=
255 MiscUtils::allOpenTDocUrls( xCtx
);
257 Reference
< provider::XScriptProviderFactory
> xFac
;
258 sal_Int32 initialSize
= openDocs
.getLength() + 2;
259 sal_Int32 mspIndex
= 0;
261 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs( initialSize
);
264 xFac
= provider::theMasterScriptProviderFactory::get( xCtx
);
266 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( makeAny( OUString("user") ) ), UNO_QUERY_THROW
);
267 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( makeAny( OUString("share") ) ), UNO_QUERY_THROW
);
269 // TODO proper exception handling, should throw
270 catch( const Exception
& )
272 TOOLS_WARN_EXCEPTION("scripting", "Caught" );
273 locnBNs
.resize( mspIndex
);
277 for ( const auto& rDoc
: openDocs
)
281 Reference
< frame::XModel
> model( MiscUtils::tDocUrlToModel( rDoc
), UNO_SET_THROW
);
283 // #i44599 Check if it's a real document or something special like Hidden/Preview
284 css::uno::Reference
< css::frame::XController
> xCurrentController
= model
->getCurrentController();
285 if( xCurrentController
.is() )
287 utl::MediaDescriptor
aMD( model
->getArgs() );
288 bool bDefault
= false;
289 bool bHidden
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_HIDDEN(), bDefault
);
290 bool bPreview
= aMD
.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_PREVIEW(), bDefault
);
291 if( !bHidden
&& !bPreview
)
293 Reference
< document::XEmbeddedScripts
> xScripts( model
, UNO_QUERY
);
295 locnBNs
[ mspIndex
++ ].set( xFac
->createScriptProvider( makeAny( model
) ), UNO_QUERY_THROW
);
299 catch( const Exception
& )
301 DBG_UNHANDLED_EXCEPTION("scripting");
306 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs_Return( mspIndex
);
307 for ( sal_Int32 j
= 0; j
< mspIndex
; j
++ )
308 locnBNs_Return
[j
] = locnBNs
[j
];
310 return locnBNs_Return
;
315 typedef ::std::vector
< Reference
< browse::XBrowseNode
> > vXBrowseNodes
;
319 struct alphaSortForBNodes
321 bool operator()( const Reference
< browse::XBrowseNode
>& a
, const Reference
< browse::XBrowseNode
>& b
)
323 return a
->getName().compareTo( b
->getName() ) < 0;
329 typedef ::cppu::WeakImplHelper
< browse::XBrowseNode
> t_BrowseNodeBase
;
333 class DefaultBrowseNode
:
334 public t_BrowseNodeBase
338 Reference
< browse::XBrowseNode
> m_xWrappedBrowseNode
;
339 Reference
< lang::XTypeProvider
> m_xWrappedTypeProv
;
340 Reference
< XAggregation
> m_xAggProxy
;
341 Reference
< XComponentContext
> m_xCtx
;
344 DefaultBrowseNode( const Reference
< XComponentContext
>& xCtx
, const Reference
< browse::XBrowseNode
>& xNode
) : m_xWrappedBrowseNode( xNode
), m_xWrappedTypeProv( xNode
, UNO_QUERY
), m_xCtx( xCtx
)
346 OSL_ENSURE( m_xWrappedBrowseNode
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
347 OSL_ENSURE( m_xWrappedTypeProv
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
348 OSL_ENSURE( m_xCtx
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
349 // Use proxy factory service to create aggregatable proxy.
352 Reference
< reflection::XProxyFactory
> xProxyFac
=
353 reflection::ProxyFactory::create( m_xCtx
);
354 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedBrowseNode
);
356 catch( uno::Exception
& )
358 OSL_FAIL( "DefaultBrowseNode::DefaultBrowseNode: Caught exception!" );
360 OSL_ENSURE( m_xAggProxy
.is(),
361 "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
363 if ( !m_xAggProxy
.is() )
366 osl_atomic_increment( &m_refCount
);
368 /* i35609 - Fix crash on Solaris. The setDelegator call needs
369 to be in its own block to ensure that all temporary Reference
370 instances that are acquired during the call are released
371 before m_refCount is decremented again */
373 m_xAggProxy
->setDelegator(
374 static_cast< cppu::OWeakObject
* >( this ) );
377 osl_atomic_decrement( &m_refCount
);
380 virtual ~DefaultBrowseNode() override
382 if ( m_xAggProxy
.is() )
384 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
388 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
389 getChildNodes() override
391 if ( hasChildNodes() )
393 vXBrowseNodes aVNodes
;
394 const Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
395 m_xWrappedBrowseNode
->getChildNodes();
396 for ( const Reference
< browse::XBrowseNode
>& xBrowseNode
: nodes
)
398 OSL_ENSURE( xBrowseNode
.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
399 if( xBrowseNode
.is() )
400 aVNodes
.push_back( new DefaultBrowseNode( m_xCtx
, xBrowseNode
) );
403 ::std::sort( aVNodes
.begin(), aVNodes
.end(), alphaSortForBNodes() );
404 Sequence
< Reference
< browse::XBrowseNode
> > children( aVNodes
.size() );
406 for ( const auto& rxNode
: aVNodes
)
408 children
[ i
].set( rxNode
);
417 Sequence
< Reference
< browse::XBrowseNode
> > none
;
422 virtual sal_Int16 SAL_CALL
getType() override
424 return m_xWrappedBrowseNode
->getType();
428 SAL_CALL
getName() override
430 return m_xWrappedBrowseNode
->getName();
433 virtual sal_Bool SAL_CALL
434 hasChildNodes() override
436 return m_xWrappedBrowseNode
->hasChildNodes();
440 virtual Any SAL_CALL
queryInterface( const Type
& aType
) override
442 Any aRet
= t_BrowseNodeBase::queryInterface( aType
);
443 if ( aRet
.hasValue() )
447 if ( m_xAggProxy
.is() )
449 return m_xAggProxy
->queryAggregation( aType
);
457 // XTypeProvider (implemnented by base, but needs to be overridden for
458 // delegating to aggregate)
459 virtual Sequence
< Type
> SAL_CALL
getTypes() override
461 return m_xWrappedTypeProv
->getTypes();
463 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId() override
465 return css::uno::Sequence
<sal_Int8
>();
469 class DefaultRootBrowseNode
:
470 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
474 vXBrowseNodes m_vNodes
;
478 explicit DefaultRootBrowseNode( const Reference
< XComponentContext
>& xCtx
)
480 std::vector
< Reference
< browse::XBrowseNode
> > nodes
=
481 getAllBrowseNodes( xCtx
);
483 for (Reference
< browse::XBrowseNode
> & xNode
: nodes
)
485 m_vNodes
.push_back( new DefaultBrowseNode( xCtx
, xNode
) );
490 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
491 getChildNodes() override
493 // no need to sort user, share, doc1...docN
494 //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
495 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
497 for ( const auto& rxNode
: m_vNodes
)
499 children
[ i
].set( rxNode
);
505 virtual sal_Int16 SAL_CALL
getType() override
507 return browse::BrowseNodeTypes::ROOT
;
511 SAL_CALL
getName() override
516 virtual sal_Bool SAL_CALL
517 hasChildNodes() override
520 if ( m_vNodes
.empty() )
529 class SelectorBrowseNode
:
530 public ::cppu::WeakImplHelper
< browse::XBrowseNode
>
533 Reference
< XComponentContext
> m_xComponentContext
;
536 explicit SelectorBrowseNode( const Reference
< XComponentContext
>& xContext
)
537 : m_xComponentContext( xContext
)
541 virtual OUString SAL_CALL
getName() override
546 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
547 getChildNodes() override
550 std::vector
< Reference
< browse::XBrowseNode
> > locnBNs
= getAllBrowseNodes( m_xComponentContext
);
552 Sequence
< Reference
< browse::XBrowseNode
> > children(
555 for ( size_t j
= 0; j
< locnBNs
.size(); j
++ )
557 children
[j
] = new LocationBrowseNode( locnBNs
[j
] );
563 virtual sal_Bool SAL_CALL
hasChildNodes() override
565 return true; // will always be user and share
568 virtual sal_Int16 SAL_CALL
getType() override
570 return browse::BrowseNodeTypes::CONTAINER
;
576 BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
577 Reference
< XComponentContext
> const & xComponentContext
)
578 : m_xComponentContext( xComponentContext
)
582 BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
587 // Implementation of XBrowseNodeFactory
591 * The selector hierarchy is the standard hierarchy for organizers with the
592 * language nodes removed.
594 Reference
< browse::XBrowseNode
> SAL_CALL
595 BrowseNodeFactoryImpl::createView( sal_Int16 viewType
)
599 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
:
600 return new SelectorBrowseNode( m_xComponentContext
);
601 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER
:
602 return getOrganizerHierarchy();
604 throw RuntimeException( "Unknown view type" );
608 Reference
< browse::XBrowseNode
>
609 BrowseNodeFactoryImpl::getOrganizerHierarchy() const
611 Reference
< browse::XBrowseNode
> xRet
= new DefaultRootBrowseNode( m_xComponentContext
);
615 // Implementation of XServiceInfo
619 BrowseNodeFactoryImpl::getImplementationName()
621 return "com.sun.star.script.browse.BrowseNodeFactory";
624 Sequence
< OUString
> SAL_CALL
625 BrowseNodeFactoryImpl::getSupportedServiceNames()
627 return { "com.sun.star.script.browse.BrowseNodeFactory" };
630 sal_Bool
BrowseNodeFactoryImpl::supportsService(OUString
const & serviceName
)
632 return cppu::supportsService(this, serviceName
);
635 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
636 scripting_BrowseNodeFactoryImpl_get_implementation(
637 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
639 return cppu::acquire(new BrowseNodeFactoryImpl(context
));
642 } // namespace browsenodefactory
644 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */