1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: BrowseNodeFactoryImpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_scripting.hxx"
34 #include <cppuhelper/weakref.hxx>
35 #include <cppuhelper/implementationentry.hxx>
36 #include <cppuhelper/factory.hxx>
37 #include <cppuhelper/exc_hlp.hxx>
38 #include <cppuhelper/implbase1.hxx>
39 #include <comphelper/mediadescriptor.hxx>
41 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
43 #include <com/sun/star/reflection/XProxyFactory.hpp>
45 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
46 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
47 #include <com/sun/star/document/XScriptInvocationContext.hpp>
49 #include <tools/diagnose_ex.h>
51 #include "BrowseNodeFactoryImpl.hxx"
52 #include "ActiveMSPList.hxx"
53 #include <util/MiscUtils.hxx>
54 #include <util/util.hxx>
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::script
;
61 using namespace ::sf_misc
;
63 namespace browsenodefactory
65 class BrowseNodeAggregator
:
66 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
69 ::rtl::OUString m_Name
;
70 Sequence
< Reference
< browse::XBrowseNode
> > m_Nodes
;
74 BrowseNodeAggregator( const Reference
< browse::XBrowseNode
>& node
)
76 m_Name
= node
->getName();
81 ~BrowseNodeAggregator()
85 void addBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
87 sal_Int32 index
= m_Nodes
.getLength();
89 m_Nodes
.realloc( index
+ 1 );
90 m_Nodes
[ index
] = node
;
93 virtual ::rtl::OUString
95 throw ( RuntimeException
)
100 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
102 throw ( RuntimeException
)
104 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > > seqs
;
105 seqs
.reserve( m_Nodes
.getLength() );
107 sal_Int32 numChildren
= 0;
109 for ( sal_Int32 i
= 0; i
< m_Nodes
.getLength(); i
++ )
111 Sequence
< Reference
< browse::XBrowseNode
> > childs
;
114 childs
= m_Nodes
[ i
]->getChildNodes();
115 seqs
.push_back( childs
);
116 numChildren
+= childs
.getLength();
120 // some form of exception getting child nodes so they
121 // won't be displayed
125 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > >::const_iterator it
= seqs
.begin();
126 std::vector
< Sequence
< Reference
< browse::XBrowseNode
> > >::const_iterator it_end
= seqs
.end();
128 Sequence
< Reference
< browse::XBrowseNode
> > result( numChildren
);
129 for ( sal_Int32 index
= 0; it
!= it_end
&& index
< numChildren
; ++it
)
131 Sequence
< Reference
< browse::XBrowseNode
> > childs
= *it
;
132 for ( sal_Int32 j
= 0; j
< childs
.getLength(); j
++ )
134 result
[ index
++ ] = childs
[ j
];
140 virtual sal_Bool SAL_CALL
142 throw ( RuntimeException
)
144 if ( m_Nodes
.getLength() != 0 )
146 for ( sal_Int32 i
= 0 ; i
< m_Nodes
.getLength(); i
++ )
150 if ( m_Nodes
[ i
]->hasChildNodes() )
157 // some form of exception getting child nodes so move
158 // on to the next one
166 virtual sal_Int16 SAL_CALL
getType()
167 throw ( RuntimeException
)
169 return browse::BrowseNodeTypes::CONTAINER
;
174 //typedef ::std::map< ::rtl::OUString, Reference< browse::XBrowseNode > >
175 typedef ::std::hash_map
< ::rtl::OUString
, Reference
< browse::XBrowseNode
>,
176 ::rtl::OUStringHash
, ::std::equal_to
< ::rtl::OUString
> >
177 BrowseNodeAggregatorHash
;
178 typedef ::std::vector
< ::rtl::OUString
> vString
;
183 bool operator()( const ::rtl::OUString
& a
, const ::rtl::OUString
& b
)
185 return a
.compareTo( b
) < 0;
188 class LocationBrowseNode
:
189 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
192 BrowseNodeAggregatorHash
* m_hBNA
;
194 ::rtl::OUString m_sNodeName
;
195 Reference
< browse::XBrowseNode
> m_origNode
;
199 LocationBrowseNode( const Reference
< browse::XBrowseNode
>& node
)
201 m_sNodeName
= node
->getName();
203 m_origNode
.set( node
);
206 ~LocationBrowseNode()
214 // -------------------------------------------------------------------------
216 // -------------------------------------------------------------------------
218 virtual ::rtl::OUString SAL_CALL
getName()
219 throw ( RuntimeException
)
224 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
226 throw ( RuntimeException
)
228 if ( m_hBNA
== NULL
)
233 Sequence
< Reference
< browse::XBrowseNode
> > children( m_hBNA
->size() );
236 vString::const_iterator it
= m_vStr
.begin();
238 for ( ; it
!= m_vStr
.end(); ++it
, index
++ )
240 children
[ index
].set( m_hBNA
->find( *it
)->second
);
246 virtual sal_Bool SAL_CALL
hasChildNodes()
247 throw ( RuntimeException
)
252 virtual sal_Int16 SAL_CALL
getType()
253 throw ( RuntimeException
)
255 return browse::BrowseNodeTypes::CONTAINER
;
260 void loadChildNodes()
262 m_hBNA
= new BrowseNodeAggregatorHash();
264 Sequence
< Reference
< browse::XBrowseNode
> > langNodes
=
265 m_origNode
->getChildNodes();
267 for ( sal_Int32 i
= 0; i
< langNodes
.getLength(); i
++ )
269 Reference
< browse::XBrowseNode
> xbn
;
270 if ( langNodes
[ i
]->getName().equals(::rtl::OUString::createFromAscii("uno_packages")) )
272 xbn
.set( new LocationBrowseNode( langNodes
[ i
] ) );
276 xbn
.set( langNodes
[ i
] );
279 Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
280 xbn
->getChildNodes();
282 for ( sal_Int32 j
= 0; j
< grandchildren
.getLength(); j
++ )
284 Reference
< browse::XBrowseNode
> grandchild(grandchildren
[j
]);
286 BrowseNodeAggregatorHash::iterator h_it
=
287 m_hBNA
->find( grandchild
->getName() );
289 if ( h_it
!= m_hBNA
->end() )
291 BrowseNodeAggregator
* bna
= static_cast< BrowseNodeAggregator
* >( h_it
->second
.get() );
292 bna
->addBrowseNode( grandchild
);
296 Reference
< browse::XBrowseNode
> bna(
297 new BrowseNodeAggregator( grandchild
) );
298 (*m_hBNA
)[ grandchild
->getName() ].set( bna
);
299 m_vStr
.push_back( grandchild
->getName() );
303 // sort children alpahbetically
304 ::std::sort( m_vStr
.begin(), m_vStr
.end(), alphaSort() );
311 Sequence
< Reference
< browse::XBrowseNode
> > getAllBrowseNodes( const Reference
< XComponentContext
>& xCtx
)
313 Reference
< lang::XMultiComponentFactory
> mcf
=
314 xCtx
->getServiceManager();
316 Sequence
< ::rtl::OUString
> openDocs
=
317 MiscUtils::allOpenTDocUrls( xCtx
);
319 Reference
< provider::XScriptProviderFactory
> xFac
;
320 sal_Int32 initialSize
= openDocs
.getLength() + 2;
321 sal_Int32 mspIndex
= 0;
323 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs( initialSize
);
327 xCtx
->getValueByName(
328 OUSTR("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") ), UNO_QUERY_THROW
);
330 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>( xFac
->createScriptProvider( makeAny( ::rtl::OUString::createFromAscii("user") ) ), UNO_QUERY_THROW
);
331 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>( xFac
->createScriptProvider( makeAny( ::rtl::OUString::createFromAscii("share") ) ), UNO_QUERY_THROW
);
333 // TODO proper exception handling, should throw
334 catch( Exception
& e
)
337 OSL_TRACE("Caught Exception %s",
338 ::rtl::OUStringToOString( e
.Message
, RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
339 locnBNs
.realloc( mspIndex
);
343 for ( sal_Int32 i
= 0; i
< openDocs
.getLength(); i
++ )
347 Reference
< frame::XModel
> model( MiscUtils::tDocUrlToModel( openDocs
[ i
] ), UNO_QUERY_THROW
);
349 // #i44599 Check if it's a real document or something special like Hidden/Preview
350 css::uno::Reference
< css::frame::XController
> xCurrentController
= model
->getCurrentController();
351 if( xCurrentController
.is() )
353 comphelper::MediaDescriptor
aMD( model
->getArgs() );
354 sal_Bool bDefault
= false;
355 sal_Bool bHidden
= aMD
.getUnpackedValueOrDefault( comphelper::MediaDescriptor::PROP_HIDDEN(), bDefault
);
356 sal_Bool bPreview
= aMD
.getUnpackedValueOrDefault( comphelper::MediaDescriptor::PROP_PREVIEW(), bDefault
);
357 if( !bHidden
&& !bPreview
)
359 Reference
< document::XEmbeddedScripts
> xScripts( model
, UNO_QUERY
);
361 locnBNs
[ mspIndex
++ ] = Reference
< browse::XBrowseNode
>(
362 xFac
->createScriptProvider( makeAny( model
) ), UNO_QUERY_THROW
);
366 catch( const Exception
& )
368 DBG_UNHANDLED_EXCEPTION();
373 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs_Return( mspIndex
);
374 for ( sal_Int32 j
= 0; j
< mspIndex
; j
++ )
375 locnBNs_Return
[j
] = locnBNs
[j
];
377 return locnBNs_Return
;
382 typedef ::std::vector
< Reference
< browse::XBrowseNode
> > vXBrowseNodes
;
384 struct alphaSortForBNodes
386 bool operator()( const Reference
< browse::XBrowseNode
>& a
, const Reference
< browse::XBrowseNode
>& b
)
388 return a
->getName().compareTo( b
->getName() ) < 0;
392 typedef ::cppu::WeakImplHelper1
< browse::XBrowseNode
> t_BrowseNodeBase
;
393 class DefaultBrowseNode
:
394 public t_BrowseNodeBase
398 Reference
< browse::XBrowseNode
> m_xWrappedBrowseNode
;
399 Reference
< lang::XTypeProvider
> m_xWrappedTypeProv
;
400 Reference
< XAggregation
> m_xAggProxy
;
401 Reference
< XComponentContext
> m_xCtx
;
405 DefaultBrowseNode( const Reference
< XComponentContext
>& xCtx
, const Reference
< browse::XBrowseNode
>& xNode
) : m_xWrappedBrowseNode( xNode
), m_xWrappedTypeProv( xNode
, UNO_QUERY
), m_xCtx( xCtx
, UNO_QUERY
)
407 OSL_ENSURE( m_xWrappedBrowseNode
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
408 OSL_ENSURE( m_xWrappedTypeProv
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
409 OSL_ENSURE( m_xCtx
.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
410 // Use proxy factory service to create aggregatable proxy.
413 Reference
< lang::XMultiComponentFactory
> xMFac( m_xCtx
->getServiceManager(), UNO_QUERY_THROW
);
414 Reference
< reflection::XProxyFactory
> xProxyFac(
415 xMFac
->createInstanceWithContext(
416 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
417 "com.sun.star.reflection.ProxyFactory" ) ),
418 m_xCtx
), UNO_QUERY_THROW
);
419 m_xAggProxy
= xProxyFac
->createProxy( m_xWrappedBrowseNode
);
421 catch( uno::Exception
& )
423 OSL_ENSURE( false, "DefaultBrowseNode::DefaultBrowseNode: Caught exception!" );
425 OSL_ENSURE( m_xAggProxy
.is(),
426 "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
428 if ( m_xAggProxy
.is() )
430 osl_incrementInterlockedCount( &m_refCount
);
432 /* i35609 - Fix crash on Solaris. The setDelegator call needs
433 to be in its own block to ensure that all temporary Reference
434 instances that are acquired during the call are released
435 before m_refCount is decremented again */
437 m_xAggProxy
->setDelegator(
438 static_cast< cppu::OWeakObject
* >( this ) );
441 osl_decrementInterlockedCount( &m_refCount
);
447 if ( m_xAggProxy
.is() )
449 m_xAggProxy
->setDelegator( uno::Reference
< uno::XInterface
>() );
453 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
455 throw ( RuntimeException
)
457 if ( hasChildNodes() )
459 vXBrowseNodes m_vNodes
;
460 Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
461 m_xWrappedBrowseNode
->getChildNodes();
462 for ( sal_Int32 i
=0; i
<nodes
.getLength(); i
++ )
464 Reference
< browse::XBrowseNode
> xBrowseNode
= nodes
[ i
];
465 OSL_ENSURE( xBrowseNode
.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
466 if( xBrowseNode
.is() )
467 m_vNodes
.push_back( new DefaultBrowseNode( m_xCtx
, xBrowseNode
) );
470 ::std::sort( m_vNodes
.begin(), m_vNodes
.end(), alphaSortForBNodes() );
471 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
472 vXBrowseNodes::const_iterator it
= m_vNodes
.begin();
473 for ( sal_Int32 i
=0; it
!= m_vNodes
.end() && i
<children
.getLength(); i
++, ++it
)
475 children
[ i
].set( *it
);
483 Sequence
< Reference
< browse::XBrowseNode
> > none
;
488 virtual sal_Int16 SAL_CALL
getType()
489 throw ( RuntimeException
)
491 return m_xWrappedBrowseNode
->getType();
494 virtual ::rtl::OUString
496 throw ( RuntimeException
)
498 return m_xWrappedBrowseNode
->getName();
501 virtual sal_Bool SAL_CALL
503 throw ( RuntimeException
)
505 return m_xWrappedBrowseNode
->hasChildNodes();
509 virtual Any SAL_CALL
queryInterface( const Type
& aType
)
510 throw ( com::sun::star::uno::RuntimeException
)
512 Any aRet
= t_BrowseNodeBase::queryInterface( aType
);
513 if ( aRet
.hasValue() )
517 if ( m_xAggProxy
.is() )
519 return m_xAggProxy
->queryAggregation( aType
);
527 virtual void SAL_CALL
acquire()
531 osl_incrementInterlockedCount( &m_refCount
);
533 virtual void SAL_CALL
release()
536 if ( osl_decrementInterlockedCount( &m_refCount
) == 0 )
541 // XTypeProvider (implemnented by base, but needs to be overridden for
542 // delegating to aggregate)
543 virtual Sequence
< Type
> SAL_CALL
getTypes()
544 throw ( com::sun::star::uno::RuntimeException
)
546 return m_xWrappedTypeProv
->getTypes();
548 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId()
549 throw ( com::sun::star::uno::RuntimeException
)
551 return m_xWrappedTypeProv
->getImplementationId();
556 class DefaultRootBrowseNode
:
557 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
561 vXBrowseNodes m_vNodes
;
562 ::rtl::OUString m_Name
;
564 DefaultRootBrowseNode();
566 DefaultRootBrowseNode( const Reference
< XComponentContext
>& xCtx
)
568 Sequence
< Reference
< browse::XBrowseNode
> > nodes
=
569 getAllBrowseNodes( xCtx
);
571 for ( sal_Int32 i
=0; i
<nodes
.getLength(); i
++ )
573 m_vNodes
.push_back( new DefaultBrowseNode( xCtx
, nodes
[ i
] ) );
575 m_Name
= ::rtl::OUString::createFromAscii( "Root" );
578 ~DefaultRootBrowseNode()
582 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
584 throw ( RuntimeException
)
586 // no need to sort user, share, doc1...docN
587 //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
588 Sequence
< Reference
< browse::XBrowseNode
> > children( m_vNodes
.size() );
589 vXBrowseNodes::const_iterator it
= m_vNodes
.begin();
590 for ( sal_Int32 i
=0; it
!= m_vNodes
.end() && i
<children
.getLength(); i
++, ++it
)
592 children
[ i
].set( *it
);
597 virtual sal_Int16 SAL_CALL
getType()
598 throw ( RuntimeException
)
600 return browse::BrowseNodeTypes::ROOT
;
603 virtual ::rtl::OUString
605 throw ( RuntimeException
)
610 virtual sal_Bool SAL_CALL
612 throw ( RuntimeException
)
614 sal_Bool result
= sal_True
;
615 if ( !m_vNodes
.size() )
624 class SelectorBrowseNode
:
625 public ::cppu::WeakImplHelper1
< browse::XBrowseNode
>
628 Reference
< XComponentContext
> m_xComponentContext
;
631 SelectorBrowseNode( const Reference
< XComponentContext
>& xContext
)
632 : m_xComponentContext( xContext
)
636 ~SelectorBrowseNode()
640 virtual ::rtl::OUString SAL_CALL
getName()
641 throw ( RuntimeException
)
643 return ::rtl::OUString::createFromAscii( "Root" );
646 virtual Sequence
< Reference
< browse::XBrowseNode
> > SAL_CALL
648 throw ( RuntimeException
)
651 Sequence
< Reference
< browse::XBrowseNode
> > locnBNs
= getAllBrowseNodes( m_xComponentContext
);
653 Sequence
< Reference
< browse::XBrowseNode
> > children(
654 locnBNs
.getLength() );
656 for ( sal_Int32 j
= 0; j
< locnBNs
.getLength(); j
++ )
658 children
[j
] = new LocationBrowseNode( locnBNs
[j
] );
664 virtual sal_Bool SAL_CALL
hasChildNodes()
665 throw ( RuntimeException
)
667 return sal_True
; // will always be user and share
670 virtual sal_Int16 SAL_CALL
getType()
671 throw ( RuntimeException
)
673 return browse::BrowseNodeTypes::CONTAINER
;
677 BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
678 Reference
< XComponentContext
> const & xComponentContext
)
679 : m_xComponentContext( xComponentContext
)
683 BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
688 //############################################################################
689 // Implementation of XBrowseNodeFactory
690 //############################################################################
693 * The selector hierarchy is the standard hierarchy for organizers with the
694 * language nodes removed.
696 Reference
< browse::XBrowseNode
> SAL_CALL
697 BrowseNodeFactoryImpl::createView( sal_Int16 viewType
)
698 throw (RuntimeException
)
702 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
:
703 return getSelectorHierarchy();
704 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER
:
705 return getOrganizerHierarchy();
707 throw RuntimeException( OUSTR("Unknown view type" ), Reference
< XInterface
>() );
711 Reference
< browse::XBrowseNode
>
712 BrowseNodeFactoryImpl::getSelectorHierarchy()
713 throw (RuntimeException
)
715 /*if ( !m_xSelectorBrowseNode.is() )
717 m_xSelectorBrowseNode = new SelectorBrowseNode( m_xComponentContext );
719 return new SelectorBrowseNode( m_xComponentContext
);
722 Reference
< browse::XBrowseNode
>
723 BrowseNodeFactoryImpl::getOrganizerHierarchy()
724 throw (RuntimeException
)
726 Reference
< browse::XBrowseNode
> xRet
= new DefaultRootBrowseNode( m_xComponentContext
);
729 //############################################################################
731 //############################################################################
733 //############################################################################
734 // Namespace global methods for setting up BrowseNodeFactory service
735 //############################################################################
737 Sequence
< ::rtl::OUString
> SAL_CALL
738 bnf_getSupportedServiceNames( )
741 ::rtl::OUString str_name
= ::rtl::OUString::createFromAscii(
742 "com.sun.star.script.browse.BrowseNodeFactory");
744 return Sequence
< ::rtl::OUString
>( &str_name
, 1 );
747 ::rtl::OUString SAL_CALL
748 bnf_getImplementationName( )
751 return ::rtl::OUString::createFromAscii(
752 "com.sun.star.script.browse.BrowseNodeFactory" );
755 Reference
< XInterface
> SAL_CALL
756 bnf_create( Reference
< XComponentContext
> const & xComponentContext
)
757 SAL_THROW( (Exception
) )
759 return static_cast< ::cppu::OWeakObject
* >(
760 new BrowseNodeFactoryImpl( xComponentContext
) );
763 //############################################################################
764 // Implementation of XServiceInfo
765 //############################################################################
767 ::rtl::OUString SAL_CALL
768 BrowseNodeFactoryImpl::getImplementationName()
769 throw (RuntimeException
)
771 return bnf_getImplementationName();
774 Sequence
< ::rtl::OUString
> SAL_CALL
775 BrowseNodeFactoryImpl::getSupportedServiceNames()
776 throw (RuntimeException
)
778 return bnf_getSupportedServiceNames();
781 sal_Bool
BrowseNodeFactoryImpl::supportsService(
782 ::rtl::OUString
const & serviceName
)
783 throw (RuntimeException
)
787 Sequence
< ::rtl::OUString
> supported_services(
788 getSupportedServiceNames() );
790 ::rtl::OUString
const * ar
= supported_services
.getConstArray();
792 for ( sal_Int32 pos
= supported_services
.getLength(); pos
--; )
794 if (ar
[ pos
].equals( serviceName
))
800 } // namespace browsenodefactory