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 #include "unodevtools/typemanager.hxx"
25 
26 #include "rtl/alloc.h"
27 #include "registry/reader.hxx"
28 #include "cppuhelper/bootstrap.hxx"
29 
30 #include "com/sun/star/container/XSet.hpp"
31 #include "com/sun/star/reflection/XTypeDescription.hpp"
32 #include "com/sun/star/registry/XSimpleRegistry.hpp"
33 #include "com/sun/star/uno/XComponentContext.hpp"
34 
35 using namespace ::rtl;
36 using namespace ::cppu;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::lang;
39 using namespace ::com::sun::star::container;
40 using namespace ::com::sun::star::registry;
41 using namespace ::com::sun::star::reflection;
42 
43 namespace unodevtools {
44 
mapTypeClass(TypeClass typeclass)45 static RTTypeClass mapTypeClass(TypeClass typeclass) {
46     switch(typeclass) {
47     case TypeClass_ENUM:
48         return RT_TYPE_ENUM;
49     case TypeClass_TYPEDEF:
50         return RT_TYPE_TYPEDEF;
51     case TypeClass_STRUCT:
52         return RT_TYPE_STRUCT;
53     case TypeClass_UNION:
54         return RT_TYPE_UNION;
55     case TypeClass_EXCEPTION:
56         return RT_TYPE_EXCEPTION;
57     case TypeClass_INTERFACE:
58         return RT_TYPE_INTERFACE;
59     case TypeClass_SERVICE:
60         return RT_TYPE_SERVICE;
61     case TypeClass_MODULE:
62         return RT_TYPE_MODULE;
63     case TypeClass_CONSTANTS:
64         return RT_TYPE_CONSTANTS;
65     case TypeClass_SINGLETON:
66         return RT_TYPE_SINGLETON;
67     default:
68         break;
69     }
70     return RT_TYPE_INVALID;
71 }
72 
73 
UnoTypeManager()74 UnoTypeManager::UnoTypeManager()
75 {
76 	m_pImpl = new UnoTypeManagerImpl();
77 	acquire();
78 }
79 
~UnoTypeManager()80 UnoTypeManager::~UnoTypeManager()
81 {
82 	release();
83 }
84 
release()85 void UnoTypeManager::release()
86 {
87 	if (0 == TypeManager::release())
88 		delete m_pImpl;
89 }
90 
init(const::std::vector<::rtl::OUString> registries)91 sal_Bool UnoTypeManager::init(
92     const ::std::vector< ::rtl::OUString > registries)
93 {
94     Reference< XComponentContext > xContext=
95         defaultBootstrap_InitialComponentContext();
96 
97     if ( !xContext.is() ) {
98         OUString msg(RTL_CONSTASCII_USTRINGPARAM(
99             "internal UNO problem, can't create initial UNO component context"));
100         throw RuntimeException( msg, Reference< XInterface >());
101     }
102     Any a = xContext->getValueByName(
103         OUString(RTL_CONSTASCII_USTRINGPARAM(
104             "/singletons/com.sun.star.reflection.theTypeDescriptionManager")));
105 
106     a >>= m_pImpl->m_tdmgr;
107 
108     if ( !m_pImpl->m_tdmgr.is() ) {
109         OUString msg(RTL_CONSTASCII_USTRINGPARAM(
110             "internal UNO problem, can't get TypeDescriptionManager"));
111         throw RuntimeException( msg, Reference< XInterface >());
112     }
113 
114     if ( !registries.empty() ) {
115 
116         Reference< XMultiComponentFactory > xServiceManager(
117             xContext->getServiceManager() );
118         if ( !xServiceManager.is() ) {
119             OUString msg(RTL_CONSTASCII_USTRINGPARAM(
120                              "internal UNO problem, can't get ServiceManager"));
121             throw RuntimeException( msg, Reference< XInterface >());
122         }
123 
124         Sequence<Any> seqArgs(registries.size());
125 
126         std::vector< OUString >::const_iterator iter = registries.begin();
127         int i = 0;
128         while ( iter != registries.end() )
129         {
130             Reference< XSimpleRegistry > xReg(
131                 xServiceManager->createInstanceWithContext(
132                     OUString(RTL_CONSTASCII_USTRINGPARAM(
133                              "com.sun.star.registry.SimpleRegistry")),
134                     xContext), UNO_QUERY);
135             xReg->open(convertToFileUrl(
136                            OUStringToOString(*iter, RTL_TEXTENCODING_UTF8)),
137                            sal_True, sal_False);
138 
139             seqArgs[i++] = makeAny(xReg);
140             iter++;
141         }
142 
143         Reference< XHierarchicalNameAccess > xTDProvider(
144             xServiceManager->createInstanceWithArgumentsAndContext(
145                 OUString(RTL_CONSTASCII_USTRINGPARAM(
146                              "com.sun.star.reflection.TypeDescriptionProvider")),
147                 seqArgs, xContext),
148             UNO_QUERY);
149         if ( !xTDProvider.is() ) {
150             OUString msg(RTL_CONSTASCII_USTRINGPARAM(
151                              "internal UNO problem, can't create local"
152                              " type description provider"));
153             throw RuntimeException( msg, Reference< XInterface >());
154 		}
155 
156         a = makeAny(xTDProvider);
157         Reference< XSet > xSet(m_pImpl->m_tdmgr, UNO_QUERY);
158         xSet->insert(a);
159     }
160 
161 	return sal_True;
162 }
163 
isValidType(const::rtl::OString & name) const164 sal_Bool UnoTypeManager::isValidType(const ::rtl::OString& name) const
165 {
166     return m_pImpl->m_tdmgr->hasByHierarchicalName(
167         OStringToOUString(name, RTL_TEXTENCODING_UTF8));
168 }
169 
getTypeName(RegistryKey & rTypeKey) const170 OString UnoTypeManager::getTypeName(RegistryKey& rTypeKey) const
171 {
172     OString typeName = OUStringToOString(rTypeKey.getName(), RTL_TEXTENCODING_UTF8);
173     static OString sBase("/UCR");
174     if (typeName.indexOf(sBase) == 0) {
175         typeName = typeName.copy(typeName.indexOf('/', 1) + 1);
176     } else {
177         typeName = typeName.copy(1);
178     }
179     return typeName;
180 }
181 
182 // extern
183 void* getTypeBlob(Reference< XHierarchicalNameAccess > xTDmgr,
184                   const OString& typeName, sal_uInt32* pBlob);
185 
getTypeReader(const OString & name,sal_Bool *) const186 typereg::Reader UnoTypeManager::getTypeReader(
187     const OString& name, sal_Bool * /*pIsExtraType*/ ) const
188 {
189     typereg::Reader reader;
190 
191 	void* pBlob = NULL;
192 	sal_uInt32 blobsize = 0;
193 
194 	if ( (pBlob = getTypeBlob(m_pImpl->m_tdmgr, name, &blobsize)) != NULL )
195 		reader = typereg::Reader(pBlob, blobsize, sal_True, TYPEREG_VERSION_1);
196 
197 	if ( pBlob )
198 		rtl_freeMemory(pBlob);
199 
200 	return reader;
201 }
202 
getTypeReader(RegistryKey & rTypeKey) const203 typereg::Reader UnoTypeManager::getTypeReader(RegistryKey& rTypeKey) const
204 {
205     typereg::Reader reader;
206 
207 	if (rTypeKey.isValid()) {
208 		RegValueType 	valueType;
209 		sal_uInt32		valueSize;
210 
211 		if (!rTypeKey.getValueInfo(OUString(), &valueType, &valueSize)) {
212 			sal_uInt8*	pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
213 			if ( !rTypeKey.getValue(OUString(), pBuffer) ) {
214                 reader = typereg::Reader(
215                     pBuffer, valueSize, true, TYPEREG_VERSION_1);
216 			}
217 			rtl_freeMemory(pBuffer);
218 		}
219 	}
220 	return reader;
221 }
222 
223 
getTypeClass(const OString & name) const224 RTTypeClass UnoTypeManager::getTypeClass(const OString& name) const
225 {
226 	if ( m_pImpl->m_t2TypeClass.count(name) > 0 ) {
227 		return m_pImpl->m_t2TypeClass[name];
228 	} else {
229         Reference< XTypeDescription > xTD;
230         Any a = m_pImpl->m_tdmgr->getByHierarchicalName(
231             OStringToOUString(name, RTL_TEXTENCODING_UTF8));
232         a >>= xTD;
233 
234 		if ( xTD.is() ) {
235             RTTypeClass tc = mapTypeClass(xTD->getTypeClass());
236             if (tc != RT_TYPE_INVALID)
237                 m_pImpl->m_t2TypeClass[name] = tc;
238             return tc;
239 		}
240 	}
241 
242 	return RT_TYPE_INVALID;
243 }
244 
getTypeClass(RegistryKey & rTypeKey) const245 RTTypeClass UnoTypeManager::getTypeClass(RegistryKey& rTypeKey) const
246 {
247     OString name = getTypeName(rTypeKey);
248 
249 	if ( m_pImpl->m_t2TypeClass.count(name) > 0 ) {
250 		return m_pImpl->m_t2TypeClass[name];
251 	} else {
252 		if ( rTypeKey.isValid() ) {
253 			RegValueType 	valueType;
254 			sal_uInt32		valueSize;
255 
256 			if ( !rTypeKey.getValueInfo(OUString(), &valueType, &valueSize) ) {
257 				sal_uInt8*	pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
258 				if ( !rTypeKey.getValue(OUString(), pBuffer) ) {
259 					typereg::Reader reader(
260                         pBuffer, valueSize, false, TYPEREG_VERSION_1);
261 
262 					RTTypeClass ret = reader.getTypeClass();
263 
264 					rtl_freeMemory(pBuffer);
265 
266 					m_pImpl->m_t2TypeClass[name] = ret;
267 					return ret;
268 				}
269 				rtl_freeMemory(pBuffer);
270 			}
271 		}
272 	}
273 
274 	return RT_TYPE_INVALID;
275 }
276 
277 } // end of namespace unodevtools
278