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 ) throw(RuntimeException);
81 
82 	// XInvokation
83     Reference< XIntrospectionAccess >  SAL_CALL getIntrospection(void)  throw(RuntimeException);
84     Any  SAL_CALL				invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) throw(IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException);
85     void  SAL_CALL				setValue(const OUString& PropertyName, const Any& Value) throw(UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException);
86     Any  SAL_CALL				getValue(const OUString& PropertyName) throw(UnknownPropertyException, RuntimeException);
87     sal_Bool  SAL_CALL				hasMethod(const OUString& Name)  throw(RuntimeException);
88     sal_Bool  SAL_CALL				hasProperty(const OUString& Name)  throw(RuntimeException);
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 ) throw(RuntimeException)
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 	throw(RuntimeException)
213 {
214 	Reference< XInvocation > xI = getDefaultInvocation();
215 	if( xI.is() )
216 		return xI->getIntrospection();
217 	return Reference< XIntrospectionAccess >();
218 }
219 
220 // XInvokation
invoke(const OUString & FunctionName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)221 Any SAL_CALL ResourceService::invoke
222 (
223 	const OUString& FunctionName,
224 	const Sequence< Any >& Params,
225 	Sequence< sal_Int16 >& OutParamIndex,
226 	Sequence< Any >& OutParam
227 )
228 	throw(IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException)
229 {
230     Any aRet;
231 	if( FunctionName.equalsAscii("getString")
232         || FunctionName.equalsAscii("getStrings" )
233         || FunctionName.equalsAscii("hasString" )
234         || FunctionName.equalsAscii("hasStrings" )
235         )
236 	{
237         sal_Int32 nElements = Params.getLength();
238         if( nElements < 1 )
239             throw IllegalArgumentException();
240         if( nElements > 1 && (FunctionName.equalsAscii("getString") || FunctionName.equalsAscii("hasString") ) )
241             throw IllegalArgumentException();
242         if( !pResMgr )
243             throw IllegalArgumentException();
244 
245         Sequence< OUString > aStrings( Params.getLength() );
246         Sequence< sal_Bool > aBools( Params.getLength() );
247         const Any* pIn = Params.getConstArray();
248         OUString* pOutString = aStrings.getArray();
249         sal_Bool* pOutBool = aBools.getArray();
250 
251         Reference< XTypeConverter > xC = getTypeConverter();
252         bool bGetBranch = FunctionName.equalsAscii( "getString" ) || FunctionName.equalsAscii( "getStrings" );
253 
254         OGuard aGuard( Application::GetSolarMutex() );
255         for( sal_Int32 n = 0; n < nElements; n++ )
256         {
257             sal_Int32 nId = 0;
258             if( !(pIn[n] >>= nId) )
259             {
260                 if( xC.is() )
261                 {
262                     xC->convertToSimpleType( pIn[n], TypeClass_LONG ) >>= nId;
263                 }
264                 else
265                     throw CannotConvertException();
266             }
267             if( nId > 0xFFFF || nId < 0 )
268                 throw IllegalArgumentException();
269 
270             if( bGetBranch )
271             {
272                 ResId aId( (sal_uInt16)nId, *pResMgr );
273                 aId.SetRT( RSC_STRING );
274                 if( pResMgr->IsAvailable( aId ) )
275                 {
276                     String aStr( aId );
277                     pOutString[n] = aStr;
278                 }
279                 else
280                     throw IllegalArgumentException();
281             }
282             else // hasString(s)
283             {
284                 sal_Bool bRet = sal_False;
285                 if( pResMgr )
286                 {
287                     ResId aId( (sal_uInt16)nId, *pResMgr );
288                     aId.SetRT( RSC_STRING );
289                     bRet = pResMgr->IsAvailable( aId );
290                 }
291                 pOutBool[n] = bRet;
292             }
293         }
294         if( FunctionName.equalsAscii("getString") )
295             aRet <<= pOutString[0];
296         else if( FunctionName.equalsAscii("getStrings" ) )
297             aRet <<= aStrings;
298         else if( FunctionName.equalsAscii("hasString" ) )
299             aRet <<= pOutBool[0];
300         else
301             aRet <<= aBools;
302     }
303     else if( FunctionName.equalsAscii("getStringList") || FunctionName.equalsAscii("hasStringList" ) )
304     {
305         if( Params.getLength() != 1 )
306             throw IllegalArgumentException();
307         Reference< XTypeConverter > xC = getTypeConverter();
308         OGuard aGuard( Application::GetSolarMutex() );
309 
310         sal_Int32 nId = 0;
311         if( !(Params.getConstArray()[0] >>= nId) )
312         {
313             if( xC.is() )
314             {
315                 xC->convertToSimpleType( Params.getConstArray()[0], TypeClass_LONG ) >>= nId;
316             }
317             else
318                 throw CannotConvertException();
319         }
320 
321         if( FunctionName.equalsAscii("getStringList") )
322         {
323             ResId aId( (sal_uInt16)nId, *pResMgr );
324             aId.SetRT( RSC_STRINGARRAY );
325             if( pResMgr->IsAvailable( aId ) )
326             {
327                 ResStringArray aStr( aId );
328                 int nEntries = aStr.Count();
329                 Sequence< PropertyValue > aPropSeq( nEntries );
330                 PropertyValue* pOut = aPropSeq.getArray();
331                 for( int i = 0; i < nEntries; i++ )
332                 {
333                     pOut[i].Name        = aStr.GetString( i );
334                     pOut[i].Handle      = -1;
335                     pOut[i].Value     <<= aStr.GetValue( i );
336                     pOut[i].State       = PropertyState_DIRECT_VALUE;
337                 }
338                 aRet <<= aPropSeq;
339             }
340             else
341                 throw IllegalArgumentException();
342         }
343         else // hasStringList
344         {
345             sal_Bool bRet = sal_False;
346             if( pResMgr )
347             {
348                 ResId aId( (sal_uInt16)nId, *pResMgr );
349                 aId.SetRT( RSC_STRINGARRAY );
350                 bRet = pResMgr->IsAvailable( aId );
351             }
352             aRet <<= bRet;
353         }
354     }
355 	else
356 	{
357 		Reference< XInvocation > xI = getDefaultInvocation();
358 		if( xI.is() )
359 			return xI->invoke( FunctionName, Params, OutParamIndex, OutParam );
360 		else
361 			throw IllegalArgumentException();
362 	}
363 	return aRet;
364 }
365 
366 // XInvokation
setValue(const OUString & PropertyName,const Any & Value)367 void SAL_CALL ResourceService::setValue(const OUString& PropertyName, const Any& Value)
368 	throw(UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException)
369 {
370 	if( PropertyName.equalsAscii("FileName") )
371 	{
372 		OUString aName;
373 		if( !(Value >>= aName) )
374 		{
375 			Reference< XTypeConverter > xC = getTypeConverter();
376 			if( xC.is() )
377 				xC->convertToSimpleType( Value, TypeClass_STRING ) >>= aName;
378 			else
379 				throw CannotConvertException();
380 		}
381 
382 		OGuard aGuard( Application::GetSolarMutex() );
383         OStringBuffer aBuf( aName.getLength()+8 );
384         aBuf.append( OUStringToOString( aName, osl_getThreadTextEncoding() ) );
385 		ResMgr * pRM = ResMgr::CreateResMgr( aBuf.getStr() );
386 		if( !pRM )
387 			throw InvocationTargetException();
388 		if( pResMgr )
389 			delete pResMgr;
390 		pResMgr = pRM;
391 		aFileName = OStringToOUString( aBuf.makeStringAndClear(), osl_getThreadTextEncoding() );
392 	}
393 	else
394 	{
395 		Reference< XInvocation > xI = getDefaultInvocation();
396 		if( xI.is() )
397 			xI->setValue( PropertyName, Value );
398 		else
399 			throw UnknownPropertyException();
400 	}
401 }
402 
403 // XInvokation
getValue(const OUString & PropertyName)404 Any SAL_CALL ResourceService::getValue(const OUString& PropertyName)
405 	throw(UnknownPropertyException, RuntimeException)
406 {
407 	OGuard aGuard( Application::GetSolarMutex() );
408 	if( PropertyName.equalsAscii("FileName" ))
409 		return makeAny( aFileName );
410 
411 	Reference< XInvocation > xI = getDefaultInvocation();
412 	if( xI.is() )
413 		return xI->getValue( PropertyName );
414 
415 	throw UnknownPropertyException();
416 }
417 
418 // XInvokation
hasMethod(const OUString & Name)419 sal_Bool SAL_CALL ResourceService::hasMethod(const OUString& Name)
420 	throw(RuntimeException)
421 {
422 	if( Name.equalsAscii("getString")     ||
423         Name.equalsAscii("getStrings")    ||
424         Name.equalsAscii("hasString")     ||
425         Name.equalsAscii("hasStrings")    ||
426         Name.equalsAscii("getStringList") ||
427         Name.equalsAscii("hasStringList")
428         )
429 		return sal_True;
430 	else
431 	{
432 		Reference< XInvocation > xI = getDefaultInvocation();
433 		if( xI.is() )
434 			return xI->hasMethod( Name );
435 		else
436 			return sal_False;
437 	}
438 }
439 
440 // XInvokation
hasProperty(const OUString & Name)441 sal_Bool SAL_CALL ResourceService::hasProperty(const OUString& Name)
442 	throw(RuntimeException)
443 {
444 	if( Name.equalsAscii("FileName") )
445 		return sal_True;
446 	else
447 	{
448 		Reference< XInvocation > xI = getDefaultInvocation();
449 		if( xI.is() )
450 			return xI->hasProperty( Name );
451 		else
452 			return sal_False;
453 	}
454 }
455 
456 namespace res
457 {
getComponentInfo_VclStringResourceLoader()458     ComponentInfo getComponentInfo_VclStringResourceLoader()
459     {
460         ComponentInfo aInfo;
461         aInfo.aSupportedServices = ResourceService::getSupportedServiceNames_Static();
462         aInfo.sImplementationName = ResourceService::getImplementationName_Static();
463         aInfo.pFactory = &ResourceService::Create;
464         return aInfo;
465     }
466 }
467 
468