nss: upgrade to release 3.73
[LibreOffice.git] / scripting / source / provider / BrowseNodeFactoryImpl.cxx
blob26fc13331ec593341de23c323a7f330773684af8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
38 #include <vector>
39 #include <algorithm>
40 #include <memory>
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
49 namespace {
50 class BrowseNodeAggregator :
51 public ::cppu::WeakImplHelper< browse::XBrowseNode >
53 private:
54 OUString m_Name;
55 std::vector< Reference< browse::XBrowseNode > > m_Nodes;
57 public:
59 explicit BrowseNodeAggregator( const Reference< browse::XBrowseNode >& node )
60 : m_Name(node->getName())
62 m_Nodes.resize( 1 );
63 m_Nodes[ 0 ] = node;
66 void addBrowseNode( const Reference< browse::XBrowseNode>& node )
68 m_Nodes.push_back( node );
71 virtual OUString
72 SAL_CALL getName() override
74 return m_Name;
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;
88 try
90 children = xNode->getChildNodes();
91 seqs.push_back( children );
92 numChildren += children.getLength();
94 catch ( Exception& )
96 // some form of exception getting child nodes so they
97 // won't be displayed
101 Sequence< Reference < browse::XBrowseNode > > result( numChildren );
102 sal_Int32 index = 0;
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)
109 break;
111 return result;
114 virtual sal_Bool SAL_CALL
115 hasChildNodes() override
117 for (Reference<XBrowseNode> & xNode : m_Nodes)
121 if ( xNode->hasChildNodes() )
123 return true;
126 catch ( Exception& )
128 // some form of exception getting child nodes so move
129 // on to the next one
133 return false;
136 virtual sal_Int16 SAL_CALL getType() override
138 return browse::BrowseNodeTypes::CONTAINER;
142 struct alphaSort
144 bool operator()( const OUString& a, const OUString& b )
146 return a.compareTo( b ) < 0;
149 class LocationBrowseNode :
150 public ::cppu::WeakImplHelper< browse::XBrowseNode >
152 private:
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;
158 public:
160 explicit LocationBrowseNode( const Reference< browse::XBrowseNode >& node )
161 : m_sNodeName(node->getName())
163 m_origNode.set( node );
167 // XBrowseNode
169 virtual OUString SAL_CALL getName() override
171 return m_sNodeName;
174 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
175 getChildNodes() override
177 if ( m_hBNA == nullptr )
179 loadChildNodes();
182 Sequence< Reference< browse::XBrowseNode > > children( m_hBNA->size() );
183 sal_Int32 index = 0;
185 for ( const auto& str : m_vStr )
187 children[ index ].set( m_hBNA->find( str )->second );
188 ++index;
191 return children;
194 virtual sal_Bool SAL_CALL hasChildNodes() override
196 return true;
199 virtual sal_Int16 SAL_CALL getType() override
201 return browse::BrowseNodeTypes::CONTAINER;
204 private:
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 ) );
220 else
222 xbn.set( rLangNode );
225 const Sequence< Reference< browse::XBrowseNode > > grandchildren =
226 xbn->getChildNodes();
228 for ( const Reference< browse::XBrowseNode >& grandchild : grandchildren )
230 auto h_it =
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 );
238 else
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 );
274 return locnBNs;
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 );
294 if ( xScripts.is() )
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;
313 } // namespace
315 typedef ::std::vector< Reference< browse::XBrowseNode > > vXBrowseNodes;
317 namespace {
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;
331 namespace {
333 class DefaultBrowseNode :
334 public t_BrowseNodeBase
337 private:
338 Reference< browse::XBrowseNode > m_xWrappedBrowseNode;
339 Reference< lang::XTypeProvider > m_xWrappedTypeProv;
340 Reference< XAggregation > m_xAggProxy;
341 Reference< XComponentContext > m_xCtx;
343 public:
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() )
364 return;
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() );
405 sal_Int32 i = 0;
406 for ( const auto& rxNode : aVNodes )
408 children[ i ].set( rxNode );
409 i++;
411 return children;
413 else
415 // no nodes
417 Sequence < Reference< browse::XBrowseNode > > none;
418 return none;
422 virtual sal_Int16 SAL_CALL getType() override
424 return m_xWrappedBrowseNode->getType();
427 virtual OUString
428 SAL_CALL getName() override
430 return m_xWrappedBrowseNode->getName();
433 virtual sal_Bool SAL_CALL
434 hasChildNodes() override
436 return m_xWrappedBrowseNode->hasChildNodes();
439 // XInterface
440 virtual Any SAL_CALL queryInterface( const Type& aType ) override
442 Any aRet = t_BrowseNodeBase::queryInterface( aType );
443 if ( aRet.hasValue() )
445 return aRet;
447 if ( m_xAggProxy.is() )
449 return m_xAggProxy->queryAggregation( aType );
451 else
453 return Any();
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 >
473 private:
474 vXBrowseNodes m_vNodes;
475 OUString m_Name;
477 public:
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 ) );
487 m_Name = "Root";
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() );
496 sal_Int32 i = 0;
497 for ( const auto& rxNode : m_vNodes )
499 children[ i ].set( rxNode );
500 i++;
502 return children;
505 virtual sal_Int16 SAL_CALL getType() override
507 return browse::BrowseNodeTypes::ROOT;
510 virtual OUString
511 SAL_CALL getName() override
513 return m_Name;
516 virtual sal_Bool SAL_CALL
517 hasChildNodes() override
519 bool result = true;
520 if ( m_vNodes.empty() )
522 result = false;
524 return result;
529 class SelectorBrowseNode :
530 public ::cppu::WeakImplHelper< browse::XBrowseNode >
532 private:
533 Reference< XComponentContext > m_xComponentContext;
535 public:
536 explicit SelectorBrowseNode( const Reference< XComponentContext >& xContext )
537 : m_xComponentContext( xContext )
541 virtual OUString SAL_CALL getName() override
543 return "Root";
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(
553 locnBNs.size() );
555 for ( size_t j = 0; j < locnBNs.size(); j++ )
557 children[j] = new LocationBrowseNode( locnBNs[j] );
560 return children;
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 )
597 switch( viewType )
599 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR:
600 return new SelectorBrowseNode( m_xComponentContext );
601 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER:
602 return getOrganizerHierarchy();
603 default:
604 throw RuntimeException( "Unknown view type" );
608 Reference< browse::XBrowseNode >
609 BrowseNodeFactoryImpl::getOrganizerHierarchy() const
611 Reference< browse::XBrowseNode > xRet = new DefaultRootBrowseNode( m_xComponentContext );
612 return xRet;
615 // Implementation of XServiceInfo
618 OUString SAL_CALL
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: */