xref: /trunk/main/scripting/source/provider/ProviderCache.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scripting.hxx"
26 #include <cppuhelper/implementationentry.hxx>
27 #include <cppuhelper/factory.hxx>
28 #include <tools/diagnose_ex.h>
29 
30 #include <util/scriptingconstants.hxx>
31 #include <util/util.hxx>
32 
33 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
34 #include "ProviderCache.hxx"
35 
36 using namespace com::sun::star;
37 using namespace com::sun::star::uno;
38 using namespace com::sun::star::script;
39 
40 namespace func_provider
41 {
42 
ProviderCache(const Reference<XComponentContext> & xContext,const Sequence<Any> & scriptContext)43 ProviderCache::ProviderCache( const Reference< XComponentContext >& xContext, const Sequence< Any >& scriptContext ) : m_Sctx( scriptContext ), m_xContext( xContext )
44 {
45     // initialise m_hProviderDetailsCache with details of ScriptProviders
46     // will use createContentEnumeration
47 
48     m_xMgr = m_xContext->getServiceManager();
49     ENSURE_OR_THROW( m_xMgr.is(), "ProviderCache::ProviderCache() failed to obtain ServiceManager" );
50     populateCache();
51 }
52 
53 
ProviderCache(const Reference<XComponentContext> & xContext,const Sequence<Any> & scriptContext,const Sequence<::rtl::OUString> & blackList)54 ProviderCache::ProviderCache( const Reference< XComponentContext >& xContext, const Sequence< Any >& scriptContext, const Sequence< ::rtl::OUString >& blackList ) : m_sBlackList( blackList ), m_Sctx( scriptContext ), m_xContext( xContext )
55 
56 {
57     // initialise m_hProviderDetailsCache with details of ScriptProviders
58     // will use createContentEnumeration
59 
60     m_xMgr = m_xContext->getServiceManager();
61     ENSURE_OR_THROW( m_xMgr.is(), "ProviderCache::ProviderCache() failed to obtain ServiceManager" );
62     populateCache();
63 }
64 
~ProviderCache()65 ProviderCache::~ProviderCache()
66 {
67 }
68 
69 Reference< provider::XScriptProvider >
getProvider(const::rtl::OUString & providerName)70 ProviderCache::getProvider( const ::rtl::OUString& providerName )
71 {
72     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
73     Reference< provider::XScriptProvider > provider;
74     ProviderDetails_hash::iterator h_it = m_hProviderDetailsCache.find( providerName );
75     if ( h_it != m_hProviderDetailsCache.end() )
76     {
77         if (  h_it->second.provider.is() )
78         {
79             provider = h_it->second.provider;
80         }
81     else
82     {
83         // need to create provider and insert into hash
84             provider = createProvider( h_it->second );
85     }
86     }
87     return provider;
88 }
89 
90 Sequence < Reference< provider::XScriptProvider > >
getAllProviders()91 ProviderCache::getAllProviders()
92 {
93     Sequence < Reference< provider::XScriptProvider > > providers (  m_hProviderDetailsCache.size() );
94     // need to create providers that haven't been created already
95     // so check what providers exist and what ones don't
96 
97     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
98     ProviderDetails_hash::iterator h_itEnd =  m_hProviderDetailsCache.end();
99     ProviderDetails_hash::iterator h_it = m_hProviderDetailsCache.begin();
100     // should assert if size !>  0
101     if (  m_hProviderDetailsCache.size() )
102     {
103         sal_Int32 providerIndex = 0;
104     sal_Int32 index = 0;
105         for ( index = 0; h_it !=  h_itEnd; ++h_it, index++ )
106         {
107             Reference< provider::XScriptProvider > xScriptProvider  = h_it->second.provider;
108             if ( xScriptProvider.is() )
109             {
110                 providers[ providerIndex++ ] = xScriptProvider;
111             }
112             else
113             {
114                 // create provider
115                 try
116                 {
117                     xScriptProvider  = createProvider( h_it->second );
118                     providers[ providerIndex++ ] = xScriptProvider;
119                 }
120                 catch ( Exception& e )
121                 {
122                     ::rtl::OUString temp = OUSTR( "ProviderCache::getAllProviders: failed to create provider, " );
123                     temp.concat( e.Message );
124                     //throw RuntimeException( temp.concat( e.Message ),
125                     //    Reference< XInterface >() );
126                 }
127             }
128         }
129 
130         if ( providerIndex < index )
131         {
132             providers.realloc( providerIndex );
133         }
134 
135     }
136     else
137     {
138         OSL_TRACE("no available providers, something very wrong!!!");
139     }
140     return providers;
141 }
142 
143 void
populateCache()144 ProviderCache::populateCache()
145 {
146     // wrong name in services.rdb
147     ::rtl::OUString serviceName;
148     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
149     try
150     {
151         ::rtl::OUString languageProviderName( RTL_CONSTASCII_USTRINGPARAM(
152             "com.sun.star.script.provider.LanguageScriptProvider" ) );
153 
154         Reference< container::XContentEnumerationAccess > xEnumAccess = Reference< container::XContentEnumerationAccess >( m_xMgr, UNO_QUERY_THROW );
155         Reference< container::XEnumeration > xEnum = xEnumAccess->createContentEnumeration ( languageProviderName );
156 
157         while ( xEnum->hasMoreElements() )
158         {
159 
160             Reference< lang::XSingleComponentFactory > factory( xEnum->nextElement(), UNO_QUERY_THROW );
161             Reference< lang::XServiceInfo > xServiceInfo( factory, UNO_QUERY_THROW );
162 
163             Sequence< ::rtl::OUString > serviceNames = xServiceInfo->getSupportedServiceNames();
164 
165             if ( serviceNames.getLength() > 0 )
166             {
167                 ::rtl::OUString searchString( RTL_CONSTASCII_USTRINGPARAM (
168                     "com.sun.star.script.provider.ScriptProviderFor" ) );
169 
170                 for ( sal_Int32 index = 0; index < serviceNames.getLength(); index++ )
171                 {
172                     if ( serviceNames[ index ].indexOf( searchString ) == 0 && !isInBlackList(  serviceNames[ index ] ) )
173                     {
174                         serviceName = serviceNames[ index ];
175                         ProviderDetails details;
176                         details.factory = factory;
177                         m_hProviderDetailsCache[ serviceName ] = details;
178                         break;
179                     }
180                 }
181             }
182         }
183     }
184     catch ( Exception e )
185     {
186         ::rtl::OUString temp = OUSTR(
187             "ProviderCache::populateCache: couldn't obtain XSingleComponentFactory for " );
188         temp.concat( serviceName );
189         throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
190     }
191 }
192 
193 Reference< provider::XScriptProvider >
createProvider(ProviderDetails & details)194 ProviderCache::createProvider( ProviderDetails& details )
195 {
196     try
197     {
198         details.provider.set(
199             details.factory->createInstanceWithArgumentsAndContext( m_Sctx, m_xContext ), UNO_QUERY_THROW );
200     }
201     catch ( Exception& e )
202     {
203         ::rtl::OUString temp = ::rtl::OUString::createFromAscii("ProviderCache::createProvider() Error creating provider from factory!!!");
204         throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
205     }
206 
207     return details.provider;
208 }
209 } //end namespace
210