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 //  #define TRACE(x) OSL_TRACE(x)
29 #define TRACE(x)
30 
31 #include <osl/diagnose.h>
32 #include <osl/mutex.hxx>
33 #include <cppuhelper/factory.hxx>
34 #include <cppuhelper/implbase2.hxx>
35 #include <cppuhelper/implementationentry.hxx>
36 #include "cppuhelper/unourl.hxx"
37 #include "rtl/malformeduriexception.hxx"
38 
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/lang/XComponent.hpp>
41 #include <com/sun/star/registry/XRegistryKey.hpp>
42 #include <com/sun/star/connection/XConnector.hpp>
43 #include <com/sun/star/bridge/XBridgeFactory.hpp>
44 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
45 
46 using namespace cppu;
47 using namespace rtl;
48 using namespace osl;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::connection;
52 using namespace com::sun::star::bridge;
53 using namespace com::sun::star::registry;
54 
55 #define SERVICENAME		"com.sun.star.bridge.UnoUrlResolver"
56 #define IMPLNAME		"com.sun.star.comp.bridge.UnoUrlResolver"
57 
58 namespace unourl_resolver
59 {
60 	rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
61 //--------------------------------------------------------------------------------------------------
62 Sequence< OUString > resolver_getSupportedServiceNames()
63 {
64 	static Sequence < OUString > *pNames = 0;
65 	if( ! pNames )
66 	{
67 		MutexGuard guard( Mutex::getGlobalMutex() );
68 		if( !pNames )
69 		{
70 			static Sequence< OUString > seqNames(1);
71 			seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
72 			pNames = &seqNames;
73 		}
74 	}
75 	return *pNames;
76 }
77 
78 OUString resolver_getImplementationName()
79 {
80 	static OUString *pImplName = 0;
81 	if( ! pImplName )
82 	{
83 		MutexGuard guard( Mutex::getGlobalMutex() );
84 		if( ! pImplName )
85 		{
86 			static OUString implName(
87 				RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
88 			pImplName = &implName;
89 		}
90 	}
91 	return *pImplName;
92 }
93 
94 //==================================================================================================
95 class ResolverImpl : public WeakImplHelper2< XServiceInfo, XUnoUrlResolver >
96 {
97 	Reference< XMultiComponentFactory > _xSMgr;
98 	Reference< XComponentContext > _xCtx;
99 
100 public:
101 	ResolverImpl( const Reference< XComponentContext > & xSMgr );
102 	virtual ~ResolverImpl();
103 
104 	// XServiceInfo
105 	virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
106 	virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException);
107 	virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
108 
109 	// XUnoUrlResolver
110     virtual Reference< XInterface > SAL_CALL resolve( const OUString & rUnoUrl )
111 		throw (NoConnectException, ConnectionSetupException, RuntimeException);
112 };
113 
114 //##################################################################################################
115 
116 //__________________________________________________________________________________________________
117 ResolverImpl::ResolverImpl( const Reference< XComponentContext > & xCtx )
118 	: _xSMgr( xCtx->getServiceManager() )
119 	, _xCtx( xCtx )
120 {
121 	g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
122 }
123 //__________________________________________________________________________________________________
124 ResolverImpl::~ResolverImpl()
125 {
126 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
127 }
128 
129 // XServiceInfo
130 //__________________________________________________________________________________________________
131 OUString ResolverImpl::getImplementationName()
132 	throw(::com::sun::star::uno::RuntimeException)
133 {
134 	return resolver_getImplementationName();
135 }
136 //__________________________________________________________________________________________________
137 sal_Bool ResolverImpl::supportsService( const OUString & rServiceName )
138 	throw(::com::sun::star::uno::RuntimeException)
139 {
140 	const Sequence< OUString > & rSNL = getSupportedServiceNames();
141 	const OUString * pArray = rSNL.getConstArray();
142 	for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
143 	{
144 		if (pArray[nPos] == rServiceName)
145 			return sal_True;
146 	}
147 	return sal_False;
148 }
149 //__________________________________________________________________________________________________
150 Sequence< OUString > ResolverImpl::getSupportedServiceNames()
151 	throw(::com::sun::star::uno::RuntimeException)
152 {
153 	return resolver_getSupportedServiceNames();
154 }
155 
156 // XUnoUrlResolver
157 //__________________________________________________________________________________________________
158 Reference< XInterface > ResolverImpl::resolve( const OUString & rUnoUrl )
159 	throw (NoConnectException, ConnectionSetupException, RuntimeException)
160 {
161     OUString aProtocolDescr;
162     OUString aConnectDescr;
163     OUString aInstanceName;
164     try
165     {
166         cppu::UnoUrl aUrl(rUnoUrl);
167         aProtocolDescr = aUrl.getProtocol().getDescriptor();
168         aConnectDescr = aUrl.getConnection().getDescriptor();
169         aInstanceName = aUrl.getObjectName();
170     }
171     catch (rtl::MalformedUriException & rEx)
172     {
173         throw ConnectionSetupException(rEx.getMessage(), 0);
174     }
175 
176 	Reference< XConnector > xConnector(
177 		_xSMgr->createInstanceWithContext(
178 			OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Connector") ),
179 			_xCtx ),
180 		UNO_QUERY );
181 
182 	if (! xConnector.is())
183 		throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no connector!" ) ), Reference< XInterface >() );
184 
185 	Reference< XConnection > xConnection( xConnector->connect( aConnectDescr ) );
186 
187 	// As soon as singletons are ready, switch to singleton !
188 	Reference< XBridgeFactory > xBridgeFactory(
189 		_xSMgr->createInstanceWithContext(
190 			OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory") ),
191 			_xCtx ),
192 		UNO_QUERY );
193 
194 	if (! xBridgeFactory.is())
195 		throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no bridge factory!" ) ), Reference< XInterface >() );
196 
197 	// bridge
198 	Reference< XBridge > xBridge( xBridgeFactory->createBridge(
199 		OUString(), aProtocolDescr,
200 		xConnection, Reference< XInstanceProvider >() ) );
201 
202 	Reference< XInterface > xRet( xBridge->getInstance( aInstanceName ) );
203 
204 	return xRet;
205 }
206 
207 //==================================================================================================
208 static Reference< XInterface > SAL_CALL ResolverImpl_create( const Reference< XComponentContext > & xCtx )
209 {
210 	return Reference< XInterface >( *new ResolverImpl( xCtx ) );
211 }
212 
213 
214 }
215 
216 using namespace unourl_resolver;
217 
218 static struct ImplementationEntry g_entries[] =
219 {
220 	{
221 		ResolverImpl_create, resolver_getImplementationName,
222 		resolver_getSupportedServiceNames, createSingleComponentFactory,
223 		&g_moduleCount.modCnt , 0
224 	},
225 	{ 0, 0, 0, 0, 0, 0 }
226 };
227 
228 extern "C"
229 {
230 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
231 {
232 	return g_moduleCount.canUnload( &g_moduleCount , pTime );
233 }
234 
235 //==================================================================================================
236 void SAL_CALL component_getImplementationEnvironment(
237 	const sal_Char ** ppEnvTypeName, uno_Environment ** )
238 {
239 	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
240 }
241 //==================================================================================================
242 void * SAL_CALL component_getFactory(
243 	const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
244 {
245 	return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
246 }
247 }
248