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_extensions.hxx"
26 #include "res_services.hxx"
27
28 #include <vos/mutex.hxx>
29 #include <uno/lbnames.h> // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
30 #include <cppuhelper/factory.hxx> // helper for factories
31 #include <cppuhelper/implbase3.hxx> // helper for implementations
32
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/script/XInvocation.hpp>
35 #include <com/sun/star/script/XTypeConverter.hpp>
36 #include <com/sun/star/reflection/InvocationTargetException.hpp>
37 #include <com/sun/star/beans/XExactName.hpp>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <com/sun/star/beans/PropertyState.hpp>
40
41 #include <tools/resmgr.hxx>
42 #include <tools/rcid.h>
43 #include <tools/resary.hxx>
44 #include <vcl/svapp.hxx>
45
46 #include <rtl/ustring.hxx>
47 #include <rtl/strbuf.hxx>
48
49 using namespace vos;
50 using namespace rtl;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::registry;
54 using namespace com::sun::star::script;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::reflection;
57
58 //------------------------------------------------------------------------
59 //------------------------------------------------------------------------
60 //------------------------------------------------------------------------
61 class ResourceService : public cppu::WeakImplHelper3< XInvocation, XExactName, XServiceInfo >
62 {
63 public:
64 ResourceService( const Reference< XMultiServiceFactory > & );
65 ~ResourceService();
66
67 // XServiceInfo
68 OUString SAL_CALL getImplementationName() throw();
69 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
70 Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
71
72 static Sequence< OUString > getSupportedServiceNames_Static(void) throw();
getImplementationName_Static()73 static OUString getImplementationName_Static() throw()
74 {
75 return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.extensions.ResourceService"));
76 }
77 static Reference< XInterface > Create( const Reference< XComponentContext >& _rxContext );
78
79 // XExactName
80 OUString SAL_CALL getExactName( const OUString & ApproximateName );
81
82 // XInvokation
83 Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void);
84 Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam);
85 void SAL_CALL setValue(const OUString& PropertyName, const Any& Value);
86 Any SAL_CALL getValue(const OUString& PropertyName);
87 sal_Bool SAL_CALL hasMethod(const OUString& Name);
88 sal_Bool SAL_CALL hasProperty(const OUString& Name);
89 private:
90 Reference< XTypeConverter > getTypeConverter() const;
91 Reference< XInvocation > getDefaultInvocation() const;
92
93 Reference< XMultiServiceFactory > xSMgr;
94 Reference< XInvocation > xDefaultInvocation;
95 Reference< XTypeConverter > xTypeConverter;
96 OUString aFileName;
97 ResMgr * pResMgr;
98 };
99
100
101 //-----------------------------------------------------------------------------
ResourceService(const Reference<XMultiServiceFactory> & rSMgr)102 ResourceService::ResourceService( const Reference< XMultiServiceFactory > & rSMgr )
103 : xSMgr( rSMgr )
104 , pResMgr( NULL )
105 {
106 }
107
108 //-----------------------------------------------------------------------------
Create(const Reference<XComponentContext> & _rxContext)109 Reference< XInterface > ResourceService::Create( const Reference< XComponentContext >& _rxContext )
110 {
111 Reference< XMultiServiceFactory > xFactory( _rxContext->getServiceManager(), UNO_QUERY_THROW );
112 return *( new ResourceService( xFactory ) );
113 }
114
115 //-----------------------------------------------------------------------------
~ResourceService()116 ResourceService::~ResourceService()
117 {
118 delete pResMgr;
119 }
120
121 // XServiceInfo
getImplementationName()122 OUString ResourceService::getImplementationName() throw()
123 {
124 return getImplementationName_Static();
125 }
126
127 // XServiceInfo
supportsService(const OUString & ServiceName)128 sal_Bool SAL_CALL ResourceService::supportsService(const OUString& ServiceName) throw()
129 {
130 Sequence< OUString > aSNL = getSupportedServiceNames();
131 const OUString * pArray = aSNL.getConstArray();
132 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
133 if( pArray[i] == ServiceName )
134 return sal_True;
135 return sal_False;
136 }
137
138 // XServiceInfo
getSupportedServiceNames(void)139 Sequence< OUString > SAL_CALL ResourceService::getSupportedServiceNames(void) throw()
140 {
141 return getSupportedServiceNames_Static();
142 }
143
144 // ResourceService
getSupportedServiceNames_Static(void)145 Sequence< OUString > ResourceService::getSupportedServiceNames_Static(void) throw()
146 {
147 Sequence< OUString > aSNS( 1 );
148 aSNS.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.VclStringResourceLoader"));
149 return aSNS;
150 }
151
152 // ResourceService
getTypeConverter() const153 Reference< XTypeConverter > ResourceService::getTypeConverter() const
154 {
155 OGuard aGuard( Application::GetSolarMutex() );
156 if( xSMgr.is() )
157 {
158 Reference< XTypeConverter > xConv( xSMgr->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter" ))), UNO_QUERY );
159 ((ResourceService*)this)->xTypeConverter = xConv;
160 }
161 return xTypeConverter;
162 }
163
164 // ResourceService
getDefaultInvocation() const165 Reference< XInvocation > ResourceService::getDefaultInvocation() const
166 {
167 OGuard aGuard( Application::GetSolarMutex() );
168 /* f�hrt zur Zeit noch zu einer rekursion
169 if( xSMgr.is() )
170 {
171 Reference< XSingleServiceFactory > xFact( xSMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Invocation") ), UNO_QUERY );
172 if( xFact.is() )
173 {
174 Sequence< Any > aArgs( 1 );
175 Reference< XInterface > xThis( *this );
176 aArgs.getArray()[0].set( &xThis, XInterface_Reference< get >lection() );
177 Reference< XInvokation > xI( xFact->createInstanceWithArguments( aArgs ), UNO_QUERY );
178 ((ResourceService*)this)->xDefaultInvocation = xI;
179 }
180 }
181 */
182 return xDefaultInvocation;
183 }
184
185 // XExactName
getExactName(const OUString & ApproximateName)186 OUString SAL_CALL ResourceService::getExactName( const OUString & ApproximateName )
187 {
188 OUString aName( ApproximateName );
189 aName = aName.toAsciiLowerCase();
190 if( aName.equalsAscii("filename") )
191 return OUString(RTL_CONSTASCII_USTRINGPARAM("FileName"));
192 else if( aName.equalsAscii("getstring" ))
193 return OUString(RTL_CONSTASCII_USTRINGPARAM("getString"));
194 else if( aName.equalsAscii("getstrings" ))
195 return OUString(RTL_CONSTASCII_USTRINGPARAM("getStrings"));
196 else if( aName.equalsAscii("hasstring") )
197 return OUString(RTL_CONSTASCII_USTRINGPARAM("hasString"));
198 else if( aName.equalsAscii("hasstrings") )
199 return OUString(RTL_CONSTASCII_USTRINGPARAM("hasStrings"));
200 else if( aName.equalsAscii("getstringlist") )
201 return OUString(RTL_CONSTASCII_USTRINGPARAM("getStringList"));
202 else if( aName.equalsAscii("hasStringList") )
203 return OUString(RTL_CONSTASCII_USTRINGPARAM("hasStringList"));
204 Reference< XExactName > xEN( getDefaultInvocation(), UNO_QUERY );
205 if( xEN.is() )
206 return xEN->getExactName( ApproximateName );
207 return OUString();
208 }
209
210 // XInvokation
getIntrospection(void)211 Reference< XIntrospectionAccess > SAL_CALL ResourceService::getIntrospection(void)
212 {
213 Reference< XInvocation > xI = getDefaultInvocation();
214 if( xI.is() )
215 return xI->getIntrospection();
216 return Reference< XIntrospectionAccess >();
217 }
218
219 // XInvokation
invoke(const OUString & FunctionName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)220 Any SAL_CALL ResourceService::invoke
221 (
222 const OUString& FunctionName,
223 const Sequence< Any >& Params,
224 Sequence< sal_Int16 >& OutParamIndex,
225 Sequence< Any >& OutParam
226 )
227 {
228 Any aRet;
229 if( FunctionName.equalsAscii("getString")
230 || FunctionName.equalsAscii("getStrings" )
231 || FunctionName.equalsAscii("hasString" )
232 || FunctionName.equalsAscii("hasStrings" )
233 )
234 {
235 sal_Int32 nElements = Params.getLength();
236 if( nElements < 1 )
237 throw IllegalArgumentException();
238 if( nElements > 1 && (FunctionName.equalsAscii("getString") || FunctionName.equalsAscii("hasString") ) )
239 throw IllegalArgumentException();
240 if( !pResMgr )
241 throw IllegalArgumentException();
242
243 Sequence< OUString > aStrings( Params.getLength() );
244 Sequence< sal_Bool > aBools( Params.getLength() );
245 const Any* pIn = Params.getConstArray();
246 OUString* pOutString = aStrings.getArray();
247 sal_Bool* pOutBool = aBools.getArray();
248
249 Reference< XTypeConverter > xC = getTypeConverter();
250 bool bGetBranch = FunctionName.equalsAscii( "getString" ) || FunctionName.equalsAscii( "getStrings" );
251
252 OGuard aGuard( Application::GetSolarMutex() );
253 for( sal_Int32 n = 0; n < nElements; n++ )
254 {
255 sal_Int32 nId = 0;
256 if( !(pIn[n] >>= nId) )
257 {
258 if( xC.is() )
259 {
260 xC->convertToSimpleType( pIn[n], TypeClass_LONG ) >>= nId;
261 }
262 else
263 throw CannotConvertException();
264 }
265 if( nId > 0xFFFF || nId < 0 )
266 throw IllegalArgumentException();
267
268 if( bGetBranch )
269 {
270 ResId aId( (sal_uInt16)nId, *pResMgr );
271 aId.SetRT( RSC_STRING );
272 if( pResMgr->IsAvailable( aId ) )
273 {
274 String aStr( aId );
275 pOutString[n] = aStr;
276 }
277 else
278 throw IllegalArgumentException();
279 }
280 else // hasString(s)
281 {
282 sal_Bool bRet = sal_False;
283 if( pResMgr )
284 {
285 ResId aId( (sal_uInt16)nId, *pResMgr );
286 aId.SetRT( RSC_STRING );
287 bRet = pResMgr->IsAvailable( aId );
288 }
289 pOutBool[n] = bRet;
290 }
291 }
292 if( FunctionName.equalsAscii("getString") )
293 aRet <<= pOutString[0];
294 else if( FunctionName.equalsAscii("getStrings" ) )
295 aRet <<= aStrings;
296 else if( FunctionName.equalsAscii("hasString" ) )
297 aRet <<= pOutBool[0];
298 else
299 aRet <<= aBools;
300 }
301 else if( FunctionName.equalsAscii("getStringList") || FunctionName.equalsAscii("hasStringList" ) )
302 {
303 if( Params.getLength() != 1 )
304 throw IllegalArgumentException();
305 Reference< XTypeConverter > xC = getTypeConverter();
306 OGuard aGuard( Application::GetSolarMutex() );
307
308 sal_Int32 nId = 0;
309 if( !(Params.getConstArray()[0] >>= nId) )
310 {
311 if( xC.is() )
312 {
313 xC->convertToSimpleType( Params.getConstArray()[0], TypeClass_LONG ) >>= nId;
314 }
315 else
316 throw CannotConvertException();
317 }
318
319 if( FunctionName.equalsAscii("getStringList") )
320 {
321 ResId aId( (sal_uInt16)nId, *pResMgr );
322 aId.SetRT( RSC_STRINGARRAY );
323 if( pResMgr->IsAvailable( aId ) )
324 {
325 ResStringArray aStr( aId );
326 int nEntries = aStr.Count();
327 Sequence< PropertyValue > aPropSeq( nEntries );
328 PropertyValue* pOut = aPropSeq.getArray();
329 for( int i = 0; i < nEntries; i++ )
330 {
331 pOut[i].Name = aStr.GetString( i );
332 pOut[i].Handle = -1;
333 pOut[i].Value <<= aStr.GetValue( i );
334 pOut[i].State = PropertyState_DIRECT_VALUE;
335 }
336 aRet <<= aPropSeq;
337 }
338 else
339 throw IllegalArgumentException();
340 }
341 else // hasStringList
342 {
343 sal_Bool bRet = sal_False;
344 if( pResMgr )
345 {
346 ResId aId( (sal_uInt16)nId, *pResMgr );
347 aId.SetRT( RSC_STRINGARRAY );
348 bRet = pResMgr->IsAvailable( aId );
349 }
350 aRet <<= bRet;
351 }
352 }
353 else
354 {
355 Reference< XInvocation > xI = getDefaultInvocation();
356 if( xI.is() )
357 return xI->invoke( FunctionName, Params, OutParamIndex, OutParam );
358 else
359 throw IllegalArgumentException();
360 }
361 return aRet;
362 }
363
364 // XInvokation
setValue(const OUString & PropertyName,const Any & Value)365 void SAL_CALL ResourceService::setValue(const OUString& PropertyName, const Any& Value)
366 {
367 if( PropertyName.equalsAscii("FileName") )
368 {
369 OUString aName;
370 if( !(Value >>= aName) )
371 {
372 Reference< XTypeConverter > xC = getTypeConverter();
373 if( xC.is() )
374 xC->convertToSimpleType( Value, TypeClass_STRING ) >>= aName;
375 else
376 throw CannotConvertException();
377 }
378
379 OGuard aGuard( Application::GetSolarMutex() );
380 OStringBuffer aBuf( aName.getLength()+8 );
381 aBuf.append( OUStringToOString( aName, osl_getThreadTextEncoding() ) );
382 ResMgr * pRM = ResMgr::CreateResMgr( aBuf.getStr() );
383 if( !pRM )
384 throw InvocationTargetException();
385 if( pResMgr )
386 delete pResMgr;
387 pResMgr = pRM;
388 aFileName = OStringToOUString( aBuf.makeStringAndClear(), osl_getThreadTextEncoding() );
389 }
390 else
391 {
392 Reference< XInvocation > xI = getDefaultInvocation();
393 if( xI.is() )
394 xI->setValue( PropertyName, Value );
395 else
396 throw UnknownPropertyException();
397 }
398 }
399
400 // XInvokation
getValue(const OUString & PropertyName)401 Any SAL_CALL ResourceService::getValue(const OUString& PropertyName)
402 {
403 OGuard aGuard( Application::GetSolarMutex() );
404 if( PropertyName.equalsAscii("FileName" ))
405 return makeAny( aFileName );
406
407 Reference< XInvocation > xI = getDefaultInvocation();
408 if( xI.is() )
409 return xI->getValue( PropertyName );
410
411 throw UnknownPropertyException();
412 }
413
414 // XInvokation
hasMethod(const OUString & Name)415 sal_Bool SAL_CALL ResourceService::hasMethod(const OUString& Name)
416 {
417 if( Name.equalsAscii("getString") ||
418 Name.equalsAscii("getStrings") ||
419 Name.equalsAscii("hasString") ||
420 Name.equalsAscii("hasStrings") ||
421 Name.equalsAscii("getStringList") ||
422 Name.equalsAscii("hasStringList")
423 )
424 return sal_True;
425 else
426 {
427 Reference< XInvocation > xI = getDefaultInvocation();
428 if( xI.is() )
429 return xI->hasMethod( Name );
430 else
431 return sal_False;
432 }
433 }
434
435 // XInvokation
hasProperty(const OUString & Name)436 sal_Bool SAL_CALL ResourceService::hasProperty(const OUString& Name)
437 {
438 if( Name.equalsAscii("FileName") )
439 return sal_True;
440 else
441 {
442 Reference< XInvocation > xI = getDefaultInvocation();
443 if( xI.is() )
444 return xI->hasProperty( Name );
445 else
446 return sal_False;
447 }
448 }
449
450 namespace res
451 {
getComponentInfo_VclStringResourceLoader()452 ComponentInfo getComponentInfo_VclStringResourceLoader()
453 {
454 ComponentInfo aInfo;
455 aInfo.aSupportedServices = ResourceService::getSupportedServiceNames_Static();
456 aInfo.sImplementationName = ResourceService::getImplementationName_Static();
457 aInfo.pFactory = &ResourceService::Create;
458 return aInfo;
459 }
460 }
461