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	<rtl/alloc.h>
25 #include	<osl/file.hxx>
26 #include	<codemaker/typemanager.hxx>
27 
28 using namespace rtl;
29 
TypeManager()30 TypeManager::TypeManager()
31 {
32 	m_pImpl = new TypeManagerImpl();
33 	acquire();
34 }
35 
~TypeManager()36 TypeManager::~TypeManager()
37 {
38 	release();
39 }
40 
acquire()41 sal_Int32 TypeManager::acquire()
42 {
43 	return osl_incrementInterlockedCount(&m_pImpl->m_refCount);
44 }
45 
release()46 sal_Int32 TypeManager::release()
47 {
48 	sal_Int32 refCount = 0;
49 	if (0 == (refCount = osl_decrementInterlockedCount(&m_pImpl->m_refCount)) )
50 	{
51 		delete m_pImpl;
52 	}
53 	return refCount;;
54 }
55 
RegistryTypeManager()56 RegistryTypeManager::RegistryTypeManager()
57 {
58 	m_pImpl = new RegistryTypeManagerImpl();
59 	acquire();
60 }
61 
~RegistryTypeManager()62 RegistryTypeManager::~RegistryTypeManager()
63 {
64 	release();
65 }
66 
acquire()67 void RegistryTypeManager::acquire()
68 {
69 	TypeManager::acquire();
70 }
71 
release()72 void RegistryTypeManager::release()
73 {
74 	if (0 == TypeManager::release())
75 	{
76 		if (m_pImpl->m_pMergedRegistry)
77 		{
78 			if (m_pImpl->m_pMergedRegistry->isValid())
79 			{
80 				m_pImpl->m_pMergedRegistry->destroy(OUString());
81 			}
82 
83 			delete m_pImpl->m_pMergedRegistry;
84 		}
85 
86 		if (m_pImpl->m_registries.size() > 0)
87 		{
88 			freeRegistries();
89 		}
90 
91 		delete m_pImpl;
92 	}
93 }
94 
init(sal_Bool bMerged,const StringVector & regFiles)95 sal_Bool RegistryTypeManager::init(sal_Bool bMerged, const StringVector& regFiles)
96 {
97 	m_pImpl->m_isMerged = bMerged && (regFiles.size() > 1);
98 
99 	if (regFiles.empty())
100 		return sal_False;
101 
102 	StringVector::const_iterator iter = regFiles.begin();
103 
104 	Registry tmpReg;
105 	while (iter != regFiles.end())
106 	{
107 		if (!tmpReg.open( convertToFileUrl(*iter), REG_READONLY))
108 			m_pImpl->m_registries.push_back(new Registry(tmpReg));
109 		else
110 		{
111 			freeRegistries();
112 			return sal_False;
113 		}
114 		iter++;
115 	}
116 
117 	if (m_pImpl->m_isMerged)
118 	{
119 		Registry *pTmpReg = new Registry;
120         OUString tmpName;
121 		osl::FileBase::createTempFile(0, 0, &tmpName);
122 		if (!pTmpReg->create(tmpName))
123 		{
124 			RegistryKey rootKey;
125 			RegError ret = REG_NO_ERROR;
126 			OUString aRoot( RTL_CONSTASCII_USTRINGPARAM("/") );
127 			iter = regFiles.begin();
128 			pTmpReg->openRootKey(rootKey);
129 
130 			while (iter != regFiles.end())
131 			{
132 				if ( (ret = pTmpReg->mergeKey(rootKey, aRoot, convertToFileUrl( *iter ))) )
133 				{
134 					if (ret != REG_MERGE_CONFLICT)
135 					{
136 						freeRegistries();
137 						rootKey.closeKey();
138 						pTmpReg->destroy( OUString() );
139 						delete pTmpReg;
140 						return sal_False;
141 					}
142 				}
143 				iter++;
144 			}
145 
146 			m_pImpl->m_pMergedRegistry = pTmpReg;
147 			freeRegistries();
148 		} else
149 		{
150 			delete pTmpReg;
151 			freeRegistries();
152 			return sal_False;
153 		}
154 	}
155 
156 	return sal_True;
157 }
158 
getTypeReader(const OString & name)159 TypeReader RegistryTypeManager::getTypeReader(const OString& name)
160 {
161 	TypeReader reader;
162 	RegistryKey key(searchTypeKey(name));
163 
164 	if (key.isValid())
165 	{
166 		RegValueType 	valueType;
167 		sal_uInt32		valueSize;
168 
169 		if (!key.getValueInfo(OUString(), &valueType, &valueSize))
170 		{
171 			sal_uInt8*	pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
172 			if (!key.getValue(OUString(), pBuffer))
173 			{
174 				reader = TypeReader(pBuffer, valueSize, sal_True);
175 			}
176 			rtl_freeMemory(pBuffer);
177 		}
178 	}
179 	return reader;
180 }
181 
getTypeClass(const OString & name)182 RTTypeClass RegistryTypeManager::getTypeClass(const OString& name)
183 {
184 	if (m_pImpl->m_t2TypeClass.count(name) > 0)
185 	{
186 		return m_pImpl->m_t2TypeClass[name];
187 	} else
188 	{
189 		RegistryKey key(searchTypeKey(name));
190 
191 		if (key.isValid())
192 		{
193 			RegValueType 	valueType;
194 			sal_uInt32		valueSize;
195 
196 			if (!key.getValueInfo(OUString(), &valueType, &valueSize))
197 			{
198 				sal_uInt8*	pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
199 				if (!key.getValue(OUString(), pBuffer))
200 				{
201 					TypeReader reader(pBuffer, valueSize, sal_False);
202 
203 					RTTypeClass ret = reader.getTypeClass();
204 
205 					rtl_freeMemory(pBuffer);
206 
207 					m_pImpl->m_t2TypeClass[name] = ret;
208 					return ret;
209 				}
210 				rtl_freeMemory(pBuffer);
211 			}
212 		}
213 	}
214 
215 	return RT_TYPE_INVALID;
216 }
217 
setBase(const OString & base)218 void RegistryTypeManager::setBase(const OString& base)
219 {
220 	m_pImpl->m_base = base;
221 
222 	if (base.lastIndexOf('/') != (base.getLength() - 1))
223 	{
224 		m_pImpl->m_base += "/";
225 	}
226 }
227 
freeRegistries()228 void RegistryTypeManager::freeRegistries()
229 {
230 	RegistryList::const_iterator iter = m_pImpl->m_registries.begin();
231 
232 	while (iter != m_pImpl->m_registries.end())
233 	{
234 		delete *iter;
235 
236 		iter++;
237 	}
238 
239 }
240 
searchTypeKey(const OString & name)241 RegistryKey	RegistryTypeManager::searchTypeKey(const OString& name)
242 {
243 	RegistryKey key, rootKey;
244 
245 	if (m_pImpl->m_isMerged)
246 	{
247 		if (!m_pImpl->m_pMergedRegistry->openRootKey(rootKey))
248 		{
249 			rootKey.openKey(OStringToOUString(m_pImpl->m_base + name, RTL_TEXTENCODING_UTF8), key);
250 		}
251 	} else
252 	{
253 		RegistryList::const_iterator iter = m_pImpl->m_registries.begin();
254 
255 		while (iter != m_pImpl->m_registries.end())
256 		{
257 			if (!(*iter)->openRootKey(rootKey))
258 			{
259 				if (!rootKey.openKey(OStringToOUString(m_pImpl->m_base + name, RTL_TEXTENCODING_UTF8), key))
260 					break;
261 			}
262 
263 			iter++;
264 		}
265 	}
266 
267 	return key;
268 }
269 
270