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_stoc.hxx"
30 
31 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
32 #include "com/sun/star/container/XSet.hpp"
33 #include "com/sun/star/lang/XMain.hpp"
34 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
35 #include "com/sun/star/lang/IllegalArgumentException.hpp"
36 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
37 #include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
38 #include "com/sun/star/reflection/XPublished.hpp"
39 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
40 #include "com/sun/star/reflection/XTypeDescription.hpp"
41 #include "com/sun/star/registry/InvalidRegistryException.hpp"
42 #include "com/sun/star/registry/XRegistryKey.hpp"
43 #include "com/sun/star/registry/XSimpleRegistry.hpp"
44 #include "com/sun/star/uno/Exception.hpp"
45 #include "com/sun/star/uno/Reference.hxx"
46 #include "com/sun/star/uno/RuntimeException.hpp"
47 #include "com/sun/star/uno/Sequence.hxx"
48 #include "com/sun/star/uno/TypeClass.hpp"
49 #include "com/sun/star/uno/XComponentContext.hpp"
50 #include "com/sun/star/uno/XInterface.hpp"
51 #include "cppuhelper/factory.hxx"
52 #include "cppuhelper/implbase1.hxx"
53 #include "cppuhelper/weak.hxx"
54 #include "osl/file.h"
55 #include "osl/thread.h"
56 #include "rtl/textenc.h"
57 #include "rtl/ustring.h"
58 #include "rtl/ustring.hxx"
59 #include "sal/types.h"
60 #include "uno/environment.h"
61 #include "uno/lbnames.h"
62 
63 #include /*MSVC trouble: <cstdlib>*/ <stdlib.h>
64 #include <iostream>
65 #include <ostream>
66 
67 namespace css = com::sun::star;
68 
69 namespace {
70 
71 class Service: public cppu::WeakImplHelper1< css::lang::XMain > {
72 public:
73     virtual sal_Int32 SAL_CALL
74     run(css::uno::Sequence< rtl::OUString > const & arguments)
75         throw (css::uno::RuntimeException);
76 
77     static rtl::OUString getImplementationName();
78 
79     static css::uno::Sequence< rtl::OUString > getSupportedServiceNames();
80 
81     static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
82         css::uno::Reference< css::uno::XComponentContext > const & context)
83         throw (css::uno::Exception);
84 
85 private:
86     explicit Service(
87         css::uno::Reference< css::uno::XComponentContext > const & context):
88         m_context(context)
89     {}
90 
91     css::uno::Reference< css::uno::XComponentContext > m_context;
92 };
93 
94 }
95 
96 namespace {
97 
98 std::ostream & operator <<(std::ostream & out, rtl::OUString const & value) {
99     return out << rtl::OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr();
100 }
101 
102 void assertTrue(bool argument) {
103     if (!argument) {
104         std::cerr
105             << "assertTrue(" << argument << ") failed" << std::endl;
106         /*MSVC trouble: std::*/abort();
107     }
108 }
109 
110 void assertFalse(bool argument) {
111     if (argument) {
112         std::cerr
113             << "assertFalse(" << argument << ") failed" << std::endl;
114         /*MSVC trouble: std::*/abort();
115     }
116 }
117 
118 template< typename T > void assertEqual(T const & value, T const & argument) {
119     if (argument != value) {
120         std::cerr
121             << "assertEqual(" << value << ", " << argument << ") failed"
122             << std::endl;
123         /*MSVC trouble: std::*/abort();
124     }
125 }
126 
127 }
128 
129 sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const & arguments)
130     throw (css::uno::RuntimeException)
131 {
132     css::uno::Reference< css::lang::XMultiComponentFactory > factory(
133         m_context->getServiceManager());
134     assertTrue(factory.is());
135     css::uno::Reference< css::container::XHierarchicalNameAccess > manager(
136         m_context->getValueByName(
137             rtl::OUString(
138                 RTL_CONSTASCII_USTRINGPARAM(
139                     "/singletons/"
140                     "com.sun.star.reflection.theTypeDescriptionManager"))),
141         css::uno::UNO_QUERY_THROW);
142 
143     ////////////////////////////////////////
144     // test: add cmd line rdbs to manager
145     ////////////////////////////////////////
146 
147     OSL_ASSERT( arguments.getLength() > 0 );
148     css::uno::Reference<css::container::XSet> xSet(
149         manager, css::uno::UNO_QUERY_THROW );
150     for ( sal_Int32 argPos = 0; argPos < arguments.getLength(); ++argPos ) {
151         rtl::OUString url;
152         OSL_VERIFY( osl_File_E_None == osl_getFileURLFromSystemPath(
153                         arguments[argPos].pData, &url.pData ) );
154         bool supposedToBeCompatible = ! url.endsWithIgnoreAsciiCaseAsciiL(
155             RTL_CONSTASCII_STRINGPARAM("_incomp.rdb") );
156 
157         css::uno::Reference<css::registry::XSimpleRegistry> xReg(
158             m_context->getServiceManager()->createInstanceWithContext(
159                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
160                                    "com.sun.star.registry.SimpleRegistry") ),
161                 m_context ), css::uno::UNO_QUERY_THROW );
162         xReg->open( url, true /* read-only */, false /* ! create */ );
163         css::uno::Any arg( css::uno::makeAny(xReg) );
164         css::uno::Reference<css::container::XHierarchicalNameAccess> xTDprov(
165             m_context->getServiceManager()->
166             createInstanceWithArgumentsAndContext(
167                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
168                                    "com.sun.star.comp.stoc."
169                                    "RegistryTypeDescriptionProvider") ),
170                 css::uno::Sequence<css::uno::Any>( &arg, 1 ), m_context ),
171             css::uno::UNO_QUERY_THROW );
172         try {
173             xSet->insert( css::uno::makeAny(xTDprov) );
174             if (! supposedToBeCompatible)
175                 std::cerr << "current rdb file: " <<
176                     rtl::OUStringToOString(
177                         url, osl_getThreadTextEncoding()).getStr() << std::endl;
178             assertTrue(supposedToBeCompatible);
179         } catch (css::lang::IllegalArgumentException &) {
180             if (supposedToBeCompatible)
181                 throw;
182             assertFalse(supposedToBeCompatible);
183         }
184     }
185 
186     ///////
187 
188     css::uno::Reference< css::reflection::XIndirectTypeDescription > sequence(
189         manager->getByHierarchicalName(
190             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean"))),
191         css::uno::UNO_QUERY_THROW);
192     assertEqual(css::uno::TypeClass_SEQUENCE, sequence->getTypeClass());
193     assertEqual(
194         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean")),
195         sequence->getName());
196     assertEqual(
197         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean")),
198         sequence->getReferencedType()->getName());
199 
200     css::uno::Reference< css::reflection::XStructTypeDescription > structure(
201         manager->getByHierarchicalName(
202             rtl::OUString(
203                 RTL_CONSTASCII_USTRINGPARAM(
204                     "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
205                     "any,com.sun.star.uno.XInterface>>"))),
206         css::uno::UNO_QUERY_THROW);
207     assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass());
208     assertEqual(
209         rtl::OUString(
210             RTL_CONSTASCII_USTRINGPARAM(
211                 "test.tdmanager.Struct<boolean,test.tdmanager.Struct<"
212                 "any,com.sun.star.uno.XInterface>>")),
213         structure->getName());
214     assertEqual< bool >(false, structure->getBaseType().is());
215     assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength());
216     assertEqual(
217         rtl::OUString(
218             RTL_CONSTASCII_USTRINGPARAM(
219                 "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
220         structure->getMemberTypes()[0]->getName());
221     assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength());
222     assertEqual(
223         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s")),
224         structure->getMemberNames()[0]);
225     assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength());
226     assertEqual< sal_Int32 >(2, structure->getTypeArguments().getLength());
227     assertEqual(
228         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean")),
229         structure->getTypeArguments()[0]->getName());
230     assertEqual(
231         rtl::OUString(
232             RTL_CONSTASCII_USTRINGPARAM(
233                 "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")),
234         structure->getTypeArguments()[1]->getName());
235 
236     css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >
237         method(
238             manager->getByHierarchicalName(
239                 rtl::OUString(
240                     RTL_CONSTASCII_USTRINGPARAM(
241                         "com.sun.star.uno.XComponentContext::getValueByName"))),
242             css::uno::UNO_QUERY_THROW);
243     assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass());
244     assertEqual(
245         rtl::OUString(
246             RTL_CONSTASCII_USTRINGPARAM(
247                 "com.sun.star.uno.XComponentContext::getValueByName")),
248         method->getName());
249     assertEqual(
250         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("getValueByName")),
251         method->getMemberName());
252     assertEqual< sal_Int32 >(3, method->getPosition());
253     assertEqual(
254         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")),
255         method->getReturnType()->getName());
256     assertEqual< bool >(false, method->isOneway());
257     assertEqual< sal_Int32 >(1, method->getParameters().getLength());
258     assertEqual(
259         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")),
260         method->getParameters()[0]->getName());
261     assertEqual(
262         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string")),
263         method->getParameters()[0]->getType()->getName());
264     assertEqual< bool >(true, method->getParameters()[0]->isIn());
265     assertEqual< bool >(false, method->getParameters()[0]->isOut());
266     assertEqual< sal_Int32 >(0, method->getParameters()[0]->getPosition());
267     assertEqual< sal_Int32 >(0, method->getExceptions().getLength());
268 
269     assertFalse(
270         css::uno::Reference< css::reflection::XPublished >(
271             css::uno::Reference< css::reflection::XTypeDescription >(
272                 manager->getByHierarchicalName(
273                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean"))),
274                 css::uno::UNO_QUERY_THROW),
275             css::uno::UNO_QUERY).is());
276     assertFalse(
277         css::uno::Reference< css::reflection::XPublished >(
278             css::uno::Reference< css::reflection::XTypeDescription >(
279                 manager->getByHierarchicalName(
280                     rtl::OUString(
281                         RTL_CONSTASCII_USTRINGPARAM(
282                             "com.sun.star.beans.XIntroTest::ObjectName"))),
283                 css::uno::UNO_QUERY_THROW),
284             css::uno::UNO_QUERY).is());
285     assertFalse(
286         css::uno::Reference< css::reflection::XPublished >(
287             css::uno::Reference< css::reflection::XTypeDescription >(
288                 manager->getByHierarchicalName(
289                     rtl::OUString(
290                         RTL_CONSTASCII_USTRINGPARAM(
291                             "com.sun.star.beans.XIntroTest::writeln"))),
292                 css::uno::UNO_QUERY_THROW),
293             css::uno::UNO_QUERY).is());
294     //TODO: check that the reflection of a property of an accumulation-based
295     // service does not support XPublished
296 
297     return 0;
298 }
299 
300 rtl::OUString Service::getImplementationName() {
301     return rtl::OUString::createFromAscii("test.tdmanager.impl");
302 }
303 
304 css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames() {
305     return css::uno::Sequence< rtl::OUString >();
306 }
307 
308 css::uno::Reference< css::uno::XInterface > Service::createInstance(
309     css::uno::Reference< css::uno::XComponentContext > const & context)
310     throw (css::uno::Exception)
311 {
312     return static_cast< cppu::OWeakObject * >(new Service(context));
313 }
314 
315 extern "C" void SAL_CALL component_getImplementationEnvironment(
316     char const ** envTypeName, uno_Environment **)
317 {
318     if (envTypeName != 0) {
319         *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
320     }
321 }
322 
323 extern "C" void * SAL_CALL component_getFactory(char const * implName,
324                                                 void * serviceManager, void *) {
325     void * p = 0;
326     if (serviceManager != 0) {
327         css::uno::Reference< css::lang::XSingleComponentFactory > f;
328         if (Service::getImplementationName().equalsAscii(implName)) {
329             f = cppu::createSingleComponentFactory(
330                 &Service::createInstance, Service::getImplementationName(),
331                 Service::getSupportedServiceNames());
332         }
333         if (f.is()) {
334             f->acquire();
335             p = f.get();
336         }
337     }
338     return p;
339 }
340 
341 namespace {
342 
343 bool writeInfo(void * registryKey, rtl::OUString const & implementationName,
344                css::uno::Sequence< rtl::OUString > const & serviceNames) {
345     rtl::OUString keyName(rtl::OUString::createFromAscii("/"));
346     keyName += implementationName;
347     keyName += rtl::OUString::createFromAscii("/UNO/SERVICES");
348     css::uno::Reference< css::registry::XRegistryKey > key;
349     try {
350         key = static_cast< css::registry::XRegistryKey * >(registryKey)->
351             createKey(keyName);
352     } catch (css::registry::InvalidRegistryException &) {}
353     if (!key.is()) {
354         return false;
355     }
356     bool success = true;
357     for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
358         try {
359             key->createKey(serviceNames[i]);
360         } catch (css::registry::InvalidRegistryException &) {
361             success = false;
362             break;
363         }
364     }
365     return success;
366 }
367 
368 }
369 
370 extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) {
371     return registryKey
372         && writeInfo(registryKey, Service::getImplementationName(),
373                      Service::getSupportedServiceNames());
374 }
375