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_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 #include <uifactory/windowcontentfactorymanager.hxx>
35 #include <uifactory/uielementfactorymanager.hxx>
36 #include <threadhelp/resetableguard.hxx>
37 #include "services.h"
38 
39 //_________________________________________________________________________________________________________________
40 //	interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/container/XContainer.hpp>
47 #include <com/sun/star/frame/XFrame.hpp>
48 #include <com/sun/star/awt/XToolkit.hpp>
49 #include <com/sun/star/awt/XControlModel.hpp>
50 #include <com/sun/star/awt/XControl.hpp>
51 
52 //_________________________________________________________________________________________________________________
53 //	includes of other projects
54 //_________________________________________________________________________________________________________________
55 #include <rtl/ustrbuf.hxx>
56 #include <cppuhelper/weak.hxx>
57 #include <tools/urlobj.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <vcl/svapp.hxx>
60 
61 //_________________________________________________________________________________________________________________
62 //	Defines
63 //_________________________________________________________________________________________________________________
64 //
65 
66 using namespace ::com::sun::star;
67 
68 //_________________________________________________________________________________________________________________
69 //	Namespace
70 //_________________________________________________________________________________________________________________
71 //
72 
73 namespace framework
74 {
75 
76 //*****************************************************************************************************************
77 //	XInterface, XTypeProvider, XServiceInfo
78 //*****************************************************************************************************************
79 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE  (   WindowContentFactoryManager				        ,
80                                             ::cppu::OWeakObject							    ,
81                                             SERVICENAME_WINDOWCONTENTFACTORYMANAGER         ,
82 											IMPLEMENTATIONNAME_WINDOWCONTENTFACTORYMANAGER
83 										)
84 
85 DEFINE_INIT_SERVICE                     (   WindowContentFactoryManager, {} )
86 
87 WindowContentFactoryManager::WindowContentFactoryManager( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) :
88     ThreadHelpBase( &Application::GetSolarMutex() ),
89     m_bConfigRead( sal_False ),
90     m_xServiceManager( xServiceManager )
91 {
92     m_pConfigAccess = new ConfigurationAccess_FactoryManager( m_xServiceManager,rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.WindowContentFactories/Registered/ContentFactories" )) );
93     m_pConfigAccess->acquire();
94     m_xModuleManager = uno::Reference< frame::XModuleManager >( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), uno::UNO_QUERY );
95 }
96 
97 WindowContentFactoryManager::~WindowContentFactoryManager()
98 {
99     ResetableGuard aLock( m_aLock );
100 
101     // reduce reference count
102     m_pConfigAccess->release();
103 }
104 
105 void WindowContentFactoryManager::RetrieveTypeNameFromResourceURL( const rtl::OUString& aResourceURL, rtl::OUString& aType, rtl::OUString& aName )
106 {
107     const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17;
108     const char      RESOURCEURL_PREFIX[] = "private:resource/";
109 
110     if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
111         ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
112     {
113         rtl::OUString aTmpStr( aResourceURL.copy( RESOURCEURL_PREFIX_SIZE ));
114         sal_Int32 nToken = 0;
115         sal_Int32 nPart  = 0;
116 		do
117 		{
118 			::rtl::OUString sToken = aTmpStr.getToken( 0, '/', nToken);
119 			if ( sToken.getLength() )
120 			{
121                 if ( nPart == 0 )
122                     aType = sToken;
123                 else if ( nPart == 1 )
124                     aName = sToken;
125                 else
126                     break;
127                 nPart++;
128 			}
129 		}
130 		while( nToken >=0 );
131     }
132 }
133 
134 // XSingleComponentFactory
135 uno::Reference< uno::XInterface > SAL_CALL WindowContentFactoryManager::createInstanceWithContext(
136     const uno::Reference< uno::XComponentContext >& /*xContext*/ )
137 throw (uno::Exception, uno::RuntimeException)
138 {
139 /*
140     // Currently this method cannot be implemented for generic use. There is no way for external
141        code to get a handle to the dialog model.
142 
143     uno::Reference< lang::XMultiServiceFactory > xServiceManager( xContext->getServiceManager(), uno::UNO_QUERY );
144 
145     const ::rtl::OUString sToolkitService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit"));
146     uno::Reference< awt::XToolkit > xToolkit( xServiceManager->createInstance( sToolkitService ), uno::UNO_QUERY_THROW );
147 
148     const ::rtl::OUString sDialogModelService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlDialogModel"));
149     uno::Reference< awt::XControlModel > xDialogModel( xServiceManager->createInstance( sDialogModelService ), uno::UNO_QUERY_THROW );
150 
151     const ::rtl::OUString sDecoration(RTL_CONSTASCII_USTRINGPARAM("Decoration"));
152     uno::Reference< beans::XPropertySet > xPropSet( xDialogModel, uno::UNO_QUERY_THROW );
153     xPropSet->setPropertyValue( sDecoration, uno::makeAny(false));
154 
155     const ::rtl::OUString sDialogService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlDialog"));
156     uno::Reference< awt::XControl > xDialogControl( xServiceManager->createInstance( sDialogService ), uno::UNO_QUERY_THROW );
157 
158     xDialogControl->setModel( xDialogModel );
159 
160     uno::Reference< awt::XWindowPeer > xWindowParentPeer( xToolkit->getDesktopWindow(), uno::UNO_QUERY );
161     xDialogControl->createPeer( xToolkit, xWindowParentPeer );
162     uno::Reference< uno::XInterface > xWindow( xDialogControl->getPeer(), uno::UNO_QUERY );
163 */
164     uno::Reference< uno::XInterface > xWindow;
165     return xWindow;
166 }
167 
168 uno::Reference< uno::XInterface > SAL_CALL WindowContentFactoryManager::createInstanceWithArgumentsAndContext(
169     const uno::Sequence< uno::Any >& Arguments, const uno::Reference< uno::XComponentContext >& Context )
170 throw (uno::Exception, uno::RuntimeException)
171 {
172     uno::Reference< uno::XInterface > xWindow;
173     uno::Reference< frame::XFrame >   xFrame;
174     ::rtl::OUString                   aResourceURL;
175 
176     for (sal_Int32 i=0; i < Arguments.getLength(); i++ )
177     {
178         beans::PropertyValue aPropValue;
179         if ( Arguments[i] >>= aPropValue )
180         {
181             if ( aPropValue.Name.equalsAscii( "Frame" ))
182                 aPropValue.Value >>= xFrame;
183             else if ( aPropValue.Name.equalsAscii( "ResourceURL" ))
184                 aPropValue.Value >>= aResourceURL;
185         }
186     }
187 
188     uno::Reference< frame::XModuleManager > xModuleManager;
189     // SAFE
190 	{
191 		ResetableGuard aLock( m_aLock );
192 		xModuleManager = m_xModuleManager;
193 	}
194     // UNSAFE
195 
196     // Determine the module identifier
197     ::rtl::OUString aType;
198     ::rtl::OUString aName;
199     ::rtl::OUString aModuleId;
200     try
201     {
202         if ( xFrame.is() && xModuleManager.is() )
203             aModuleId = xModuleManager->identify( uno::Reference< uno::XInterface >( xFrame, uno::UNO_QUERY ) );
204     }
205     catch ( frame::UnknownModuleException& )
206     {
207     }
208 
209     RetrieveTypeNameFromResourceURL( aResourceURL, aType, aName );
210     if ( aType.getLength() > 0 &&
211          aName.getLength() > 0 &&
212          aModuleId.getLength() > 0 )
213     {
214         ::rtl::OUString                   aImplementationName;
215         uno::Reference< uno::XInterface > xHolder( static_cast<cppu::OWeakObject*>(this), uno::UNO_QUERY );
216 
217         // Detetmine the implementation name of the window content factory dependent on the
218         // module identifier, user interface element type and name
219         // SAFE
220         ResetableGuard aLock( m_aLock );
221 
222         if ( !m_bConfigRead )
223         {
224             m_bConfigRead = sal_True;
225             m_pConfigAccess->readConfigurationData();
226         }
227 
228         aImplementationName = m_pConfigAccess->getFactorySpecifierFromTypeNameModule( aType, aName, aModuleId );
229         if ( aImplementationName.getLength() > 0 )
230         {
231             aLock.unlock();
232             // UNSAFE
233 
234             uno::Reference< lang::XMultiServiceFactory > xServiceManager( Context->getServiceManager(), uno::UNO_QUERY );
235             if ( xServiceManager.is() )
236             {
237                 uno::Reference< lang::XSingleComponentFactory > xFactory(
238                     xServiceManager->createInstance( aImplementationName ), uno::UNO_QUERY );
239                 if ( xFactory.is() )
240                 {
241                     // Be careful: We call external code. Therefore here we have to catch all exceptions
242                     try
243                     {
244                         xWindow = xFactory->createInstanceWithArgumentsAndContext( Arguments, Context );
245                     }
246                     catch ( uno::Exception& )
247                     {
248                         DBG_UNHANDLED_EXCEPTION();
249                     }
250                 }
251             }
252         }
253     }
254 
255     // UNSAFE
256     if ( !xWindow.is())
257     {
258         // Fallback: Use internal factory code to create a toolkit dialog as a content window
259         xWindow = createInstanceWithContext(Context);
260     }
261 
262     return xWindow;
263 }
264 
265 } // namespace framework
266