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 #include "componentmodule.hxx"
29 #include <tools/resmgr.hxx>
30 #ifndef _SOLAR_HRC
31 #include <svl/solar.hrc>
32 #endif
33 #include <comphelper/sequence.hxx>
34 #include <tools/debug.hxx>
35 
36 #define ENTER_MOD_METHOD()	\
37 	::osl::MutexGuard aGuard(s_aMutex);	\
38 	ensureImpl()
39 
40 //.........................................................................
41 namespace COMPMOD_NAMESPACE
42 {
43 //.........................................................................
44 
45 	using namespace ::com::sun::star::uno;
46 	using namespace ::com::sun::star::lang;
47 	using namespace ::com::sun::star::registry;
48 	using namespace ::comphelper;
49 	using namespace ::cppu;
50 
51 	//=========================================================================
52 	//= OModuleImpl
53 	//=========================================================================
54 	/** implementation for <type>OModule</type>. not threadsafe, has to be guarded by it's owner
55 	*/
56 	class OModuleImpl
57 	{
58 		ResMgr*		m_pRessources;
59 		sal_Bool	m_bInitialized;
60 		ByteString	m_sFilePrefix;
61 
62 	public:
63 		/// ctor
64 		OModuleImpl();
65 		~OModuleImpl();
66 
67 		/// get the manager for the ressources of the module
68 		ResMgr*	getResManager();
69 		void	setResourceFilePrefix(const ::rtl::OString& _rPrefix) { m_sFilePrefix = _rPrefix; }
70 	};
71 
72 	//-------------------------------------------------------------------------
73 	OModuleImpl::OModuleImpl()
74 		:m_pRessources(NULL)
75 		,m_bInitialized(sal_False)
76 	{
77 	}
78 
79 	//-------------------------------------------------------------------------
80 	OModuleImpl::~OModuleImpl()
81 	{
82 		if (m_pRessources)
83 			delete m_pRessources;
84 	}
85 
86 	//-------------------------------------------------------------------------
87 	ResMgr*	OModuleImpl::getResManager()
88 	{
89 		// note that this method is not threadsafe, which counts for the whole class !
90 		if (!m_pRessources && !m_bInitialized)
91 		{
92 			DBG_ASSERT(m_sFilePrefix.Len(), "OModuleImpl::getResManager: no resource file prefix!");
93 			// create a manager with a fixed prefix
94 			ByteString aMgrName = m_sFilePrefix;
95 
96 			m_pRessources = ResMgr::CreateResMgr(aMgrName.GetBuffer());
97 			DBG_ASSERT(m_pRessources,
98 					(ByteString("OModuleImpl::getResManager: could not create the resource manager (file name: ")
99 				+=	aMgrName
100 				+=	ByteString(")!")).GetBuffer());
101 
102 			m_bInitialized = sal_True;
103 		}
104 		return m_pRessources;
105 	}
106 
107 	//=========================================================================
108 	//= OModule
109 	//=========================================================================
110 	::osl::Mutex	OModule::s_aMutex;
111 	sal_Int32		OModule::s_nClients = 0;
112 	OModuleImpl*	OModule::s_pImpl = NULL;
113 	::rtl::OString	OModule::s_sResPrefix;
114 	//-------------------------------------------------------------------------
115 	ResMgr*	OModule::getResManager()
116 	{
117 		ENTER_MOD_METHOD();
118 		return s_pImpl->getResManager();
119 	}
120 
121 	//-------------------------------------------------------------------------
122 	void OModule::setResourceFilePrefix(const ::rtl::OString& _rPrefix)
123 	{
124 		::osl::MutexGuard aGuard(s_aMutex);
125 		s_sResPrefix = _rPrefix;
126 		if (s_pImpl)
127 			s_pImpl->setResourceFilePrefix(_rPrefix);
128 	}
129 
130 	//-------------------------------------------------------------------------
131 	void OModule::registerClient()
132 	{
133 		::osl::MutexGuard aGuard(s_aMutex);
134 		++s_nClients;
135 	}
136 
137 	//-------------------------------------------------------------------------
138 	void OModule::revokeClient()
139 	{
140 		::osl::MutexGuard aGuard(s_aMutex);
141 		if (!--s_nClients && s_pImpl)
142 		{
143 			delete s_pImpl;
144 			s_pImpl = NULL;
145 		}
146 	}
147 
148 	//-------------------------------------------------------------------------
149 	void OModule::ensureImpl()
150 	{
151 		if (s_pImpl)
152 			return;
153 		s_pImpl = new OModuleImpl();
154 		s_pImpl->setResourceFilePrefix(s_sResPrefix);
155 	}
156 
157 	//--------------------------------------------------------------------------
158 	//- registration helper
159 	//--------------------------------------------------------------------------
160 
161 	Sequence< ::rtl::OUString >*				OModule::s_pImplementationNames = NULL;
162 	Sequence< Sequence< ::rtl::OUString > >*	OModule::s_pSupportedServices = NULL;
163 	Sequence< sal_Int64 >*						OModule::s_pCreationFunctionPointers = NULL;
164 	Sequence< sal_Int64 >*						OModule::s_pFactoryFunctionPointers = NULL;
165 
166 	//--------------------------------------------------------------------------
167 	void OModule::registerComponent(
168 		const ::rtl::OUString& _rImplementationName,
169 		const Sequence< ::rtl::OUString >& _rServiceNames,
170 		ComponentInstantiation _pCreateFunction,
171 		FactoryInstantiation _pFactoryFunction)
172 	{
173 		if (!s_pImplementationNames)
174 		{
175 			OSL_ENSURE(!s_pSupportedServices && !s_pCreationFunctionPointers && !s_pFactoryFunctionPointers,
176 				"OModule::registerComponent : inconsistent state (the pointers (1)) !");
177 			s_pImplementationNames = new Sequence< ::rtl::OUString >;
178 			s_pSupportedServices = new Sequence< Sequence< ::rtl::OUString > >;
179 			s_pCreationFunctionPointers = new Sequence< sal_Int64 >;
180 			s_pFactoryFunctionPointers = new Sequence< sal_Int64 >;
181 		}
182 		OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers,
183 			"OModule::registerComponent : inconsistent state (the pointers (2)) !");
184 
185 		OSL_ENSURE(	(s_pImplementationNames->getLength() == s_pSupportedServices->getLength())
186 					&&	(s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength())
187 					&&	(s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()),
188 			"OModule::registerComponent : inconsistent state !");
189 
190 		sal_Int32 nOldLen = s_pImplementationNames->getLength();
191 		s_pImplementationNames->realloc(nOldLen + 1);
192 		s_pSupportedServices->realloc(nOldLen + 1);
193 		s_pCreationFunctionPointers->realloc(nOldLen + 1);
194 		s_pFactoryFunctionPointers->realloc(nOldLen + 1);
195 
196 		s_pImplementationNames->getArray()[nOldLen] = _rImplementationName;
197 		s_pSupportedServices->getArray()[nOldLen] = _rServiceNames;
198 		s_pCreationFunctionPointers->getArray()[nOldLen] = reinterpret_cast<sal_Int64>(_pCreateFunction);
199 		s_pFactoryFunctionPointers->getArray()[nOldLen] = reinterpret_cast<sal_Int64>(_pFactoryFunction);
200 	}
201 
202 	//--------------------------------------------------------------------------
203 	void OModule::revokeComponent(const ::rtl::OUString& _rImplementationName)
204 	{
205 		if (!s_pImplementationNames)
206 		{
207 			OSL_ASSERT("OModule::revokeComponent : have no class infos ! Are you sure called this method at the right time ?");
208 			return;
209 		}
210 		OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers,
211 			"OModule::revokeComponent : inconsistent state (the pointers) !");
212 		OSL_ENSURE(	(s_pImplementationNames->getLength() == s_pSupportedServices->getLength())
213 					&&	(s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength())
214 					&&	(s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()),
215 			"OModule::revokeComponent : inconsistent state !");
216 
217 		sal_Int32 nLen = s_pImplementationNames->getLength();
218 		const ::rtl::OUString* pImplNames = s_pImplementationNames->getConstArray();
219 		for (sal_Int32 i=0; i<nLen; ++i, ++pImplNames)
220 		{
221 			if (pImplNames->equals(_rImplementationName))
222 			{
223 				removeElementAt(*s_pImplementationNames, i);
224 				removeElementAt(*s_pSupportedServices, i);
225 				removeElementAt(*s_pCreationFunctionPointers, i);
226 				removeElementAt(*s_pFactoryFunctionPointers, i);
227 				break;
228 			}
229 		}
230 
231 		if (s_pImplementationNames->getLength() == 0)
232 		{
233 			delete s_pImplementationNames; s_pImplementationNames = NULL;
234 			delete s_pSupportedServices; s_pSupportedServices = NULL;
235 			delete s_pCreationFunctionPointers; s_pCreationFunctionPointers = NULL;
236 			delete s_pFactoryFunctionPointers; s_pFactoryFunctionPointers = NULL;
237 		}
238 	}
239 
240 	//--------------------------------------------------------------------------
241 	Reference< XInterface > OModule::getComponentFactory(
242 		const ::rtl::OUString& _rImplementationName,
243 		const Reference< XMultiServiceFactory >& _rxServiceManager)
244 	{
245 		OSL_ENSURE(_rxServiceManager.is(), "OModule::getComponentFactory : invalid argument (service manager) !");
246 		OSL_ENSURE(_rImplementationName.getLength(), "OModule::getComponentFactory : invalid argument (implementation name) !");
247 
248 		if (!s_pImplementationNames)
249 		{
250 			OSL_ASSERT("OModule::getComponentFactory : have no class infos ! Are you sure called this method at the right time ?");
251 			return NULL;
252 		}
253 		OSL_ENSURE(s_pImplementationNames && s_pSupportedServices && s_pCreationFunctionPointers && s_pFactoryFunctionPointers,
254 			"OModule::getComponentFactory : inconsistent state (the pointers) !");
255 		OSL_ENSURE(	(s_pImplementationNames->getLength() == s_pSupportedServices->getLength())
256 					&&	(s_pImplementationNames->getLength() == s_pCreationFunctionPointers->getLength())
257 					&&	(s_pImplementationNames->getLength() == s_pFactoryFunctionPointers->getLength()),
258 			"OModule::getComponentFactory : inconsistent state !");
259 
260 
261 		Reference< XInterface > xReturn;
262 
263 
264 		sal_Int32 nLen = s_pImplementationNames->getLength();
265 		const ::rtl::OUString* pImplName = s_pImplementationNames->getConstArray();
266 		const Sequence< ::rtl::OUString >* pServices = s_pSupportedServices->getConstArray();
267 		const sal_Int64* pComponentFunction = s_pCreationFunctionPointers->getConstArray();
268 		const sal_Int64* pFactoryFunction = s_pFactoryFunctionPointers->getConstArray();
269 
270 		for (sal_Int32 i=0; i<nLen; ++i, ++pImplName, ++pServices, ++pComponentFunction, ++pFactoryFunction)
271 		{
272 			if (pImplName->equals(_rImplementationName))
273 			{
274 				const FactoryInstantiation FactoryInstantiationFunction = reinterpret_cast<const FactoryInstantiation>(*pFactoryFunction);
275 				const ComponentInstantiation ComponentInstantiationFunction = reinterpret_cast<const ComponentInstantiation>(*pComponentFunction);
276 
277 				xReturn = FactoryInstantiationFunction( _rxServiceManager, *pImplName, ComponentInstantiationFunction, *pServices, NULL);
278 				if (xReturn.is())
279 				{
280 					xReturn->acquire();
281 					return xReturn.get();
282 				}
283 			}
284 		}
285 
286 		return NULL;
287 	}
288 
289 
290 //.........................................................................
291 }	// namespace COMPMOD_NAMESPACE
292 //.........................................................................
293 
294