1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_scripting.hxx"
30 #include <cppuhelper/implementationentry.hxx>
31 #include <cppuhelper/factory.hxx>
32 #include <tools/diagnose_ex.h>
33 
34 #include <util/scriptingconstants.hxx>
35 #include <util/util.hxx>
36 
37 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
38 #include "ProviderCache.hxx"
39 
40 using namespace com::sun::star;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::script;
43 
44 namespace func_provider
45 {
46 
47 ProviderCache::ProviderCache( const Reference< XComponentContext >& xContext, const Sequence< Any >& scriptContext )
48     throw ( RuntimeException ) : m_Sctx( scriptContext ), m_xContext( xContext )
49 {
50     // initialise m_hProviderDetailsCache with details of ScriptProviders
51     // will use createContentEnumeration
52 
53     m_xMgr = m_xContext->getServiceManager();
54     ENSURE_OR_THROW( m_xMgr.is(), "ProviderCache::ProviderCache() failed to obtain ServiceManager" );
55     populateCache();
56 }
57 
58 
59 ProviderCache::ProviderCache( const Reference< XComponentContext >& xContext, const Sequence< Any >& scriptContext, const Sequence< ::rtl::OUString >& blackList )
60     throw ( RuntimeException ) : m_sBlackList( blackList ), m_Sctx( scriptContext ), m_xContext( xContext )
61 
62 {
63     // initialise m_hProviderDetailsCache with details of ScriptProviders
64     // will use createContentEnumeration
65 
66     m_xMgr = m_xContext->getServiceManager();
67     ENSURE_OR_THROW( m_xMgr.is(), "ProviderCache::ProviderCache() failed to obtain ServiceManager" );
68     populateCache();
69 }
70 
71 ProviderCache::~ProviderCache()
72 {
73 }
74 
75 Reference< provider::XScriptProvider >
76 ProviderCache::getProvider( const ::rtl::OUString& providerName )
77 {
78     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
79     Reference< provider::XScriptProvider > provider;
80     ProviderDetails_hash::iterator h_it = m_hProviderDetailsCache.find( providerName );
81     if ( h_it != m_hProviderDetailsCache.end() )
82     {
83         if (  h_it->second.provider.is() )
84         {
85             provider = h_it->second.provider;
86         }
87 	else
88 	{
89 	    // need to create provider and insert into hash
90             provider = createProvider( h_it->second );
91 	}
92     }
93     return provider;
94 }
95 
96 Sequence < Reference< provider::XScriptProvider > >
97 ProviderCache::getAllProviders() throw ( RuntimeException )
98 {
99     Sequence < Reference< provider::XScriptProvider > > providers (  m_hProviderDetailsCache.size() );
100     // need to create providers that haven't been created already
101     // so check what providers exist and what ones don't
102 
103     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
104     ProviderDetails_hash::iterator h_itEnd =  m_hProviderDetailsCache.end();
105     ProviderDetails_hash::iterator h_it = m_hProviderDetailsCache.begin();
106     // should assert if size !>  0
107     if (  m_hProviderDetailsCache.size() )
108     {
109         sal_Int32 providerIndex = 0;
110 	sal_Int32 index = 0;
111         for ( index = 0; h_it !=  h_itEnd; ++h_it, index++ )
112         {
113             Reference< provider::XScriptProvider > xScriptProvider  = h_it->second.provider;
114             if ( xScriptProvider.is() )
115             {
116                 providers[ providerIndex++ ] = xScriptProvider;
117             }
118             else
119             {
120                 // create provider
121                 try
122                 {
123                     xScriptProvider  = createProvider( h_it->second );
124                     providers[ providerIndex++ ] = xScriptProvider;
125                 }
126                 catch ( Exception& e )
127                 {
128                     ::rtl::OUString temp = OUSTR( "ProviderCache::getAllProviders: failed to create provider, " );
129                     temp.concat( e.Message );
130                     //throw RuntimeException( temp.concat( e.Message ),
131                     //    Reference< XInterface >() );
132                 }
133             }
134         }
135 
136         if ( providerIndex < index )
137         {
138             providers.realloc( providerIndex );
139         }
140 
141     }
142     else
143     {
144         OSL_TRACE("no available providers, something very wrong!!!");
145     }
146     return providers;
147 }
148 
149 void
150 ProviderCache::populateCache() throw ( RuntimeException )
151 {
152     // wrong name in services.rdb
153     ::rtl::OUString serviceName;
154     ::osl::Guard< osl::Mutex > aGuard( m_mutex );
155     try
156     {
157         ::rtl::OUString languageProviderName( RTL_CONSTASCII_USTRINGPARAM(
158             "com.sun.star.script.provider.LanguageScriptProvider" ) );
159 
160         Reference< container::XContentEnumerationAccess > xEnumAccess = Reference< container::XContentEnumerationAccess >( m_xMgr, UNO_QUERY_THROW );
161         Reference< container::XEnumeration > xEnum = xEnumAccess->createContentEnumeration ( languageProviderName );
162 
163         while ( xEnum->hasMoreElements() )
164         {
165 
166             Reference< lang::XSingleComponentFactory > factory( xEnum->nextElement(), UNO_QUERY_THROW );
167             Reference< lang::XServiceInfo > xServiceInfo( factory, UNO_QUERY_THROW );
168 
169             Sequence< ::rtl::OUString > serviceNames = xServiceInfo->getSupportedServiceNames();
170 
171             if ( serviceNames.getLength() > 0 )
172             {
173                 ::rtl::OUString searchString( RTL_CONSTASCII_USTRINGPARAM (
174                     "com.sun.star.script.provider.ScriptProviderFor" ) );
175 
176                 for ( sal_Int32 index = 0; index < serviceNames.getLength(); index++ )
177                 {
178                     if ( serviceNames[ index ].indexOf( searchString ) == 0 && !isInBlackList(  serviceNames[ index ] ) )
179                     {
180                         serviceName = serviceNames[ index ];
181                         ProviderDetails details;
182                         details.factory = factory;
183                         m_hProviderDetailsCache[ serviceName ] = details;
184                         break;
185                     }
186                 }
187             }
188         }
189     }
190     catch ( Exception e )
191     {
192         ::rtl::OUString temp = OUSTR(
193             "ProviderCache::populateCache: couldn't obtain XSingleComponentFactory for " );
194         temp.concat( serviceName );
195         throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
196     }
197 }
198 
199 Reference< provider::XScriptProvider >
200 ProviderCache::createProvider( ProviderDetails& details ) throw ( RuntimeException )
201 {
202     try
203     {
204         details.provider.set(
205             details.factory->createInstanceWithArgumentsAndContext( m_Sctx, m_xContext ), UNO_QUERY_THROW );
206     }
207     catch ( RuntimeException& e )
208     {
209         ::rtl::OUString temp = ::rtl::OUString::createFromAscii("ProviderCache::createProvider() Error creating provider from factory!!!");
210         throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
211     }
212 
213     return details.provider;
214 }
215 } //end namespace
216