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 "precompiled_sd.hxx"
29 
30 #include "ResourceFactoryManager.hxx"
31 #include <tools/wldcrd.hxx>
32 #include <com/sun/star/lang/IllegalArgumentException.hpp>
33 #include <com/sun/star/lang/XComponent.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <boost/bind.hpp>
37 #include <algorithm>
38 
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::drawing::framework;
42 using ::rtl::OUString;
43 
44 namespace sd { namespace framework {
45 
46 ResourceFactoryManager::ResourceFactoryManager (const Reference<XControllerManager>& rxManager)
47     : maMutex(),
48       maFactoryMap(),
49       maFactoryPatternList(),
50       mxControllerManager(rxManager),
51       mxURLTransformer()
52 {
53     // Create the URL transformer.
54     Reference<lang::XMultiServiceFactory> xServiceManager (
55         ::comphelper::getProcessServiceFactory());
56     mxURLTransformer = Reference<util::XURLTransformer>(
57         xServiceManager->createInstance(
58             OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
59         UNO_QUERY);
60 }
61 
62 
63 
64 
65 ResourceFactoryManager::~ResourceFactoryManager (void)
66 {
67     Reference<lang::XComponent> xComponent (mxURLTransformer, UNO_QUERY);
68     if (xComponent.is())
69         xComponent->dispose();
70 }
71 
72 
73 
74 
75 void ResourceFactoryManager::AddFactory (
76     const OUString& rsURL,
77     const Reference<XResourceFactory>& rxFactory)
78         throw (RuntimeException)
79 {
80     if ( ! rxFactory.is())
81         throw lang::IllegalArgumentException();
82     if (rsURL.getLength() == 0)
83         throw lang::IllegalArgumentException();
84 
85     ::osl::MutexGuard aGuard (maMutex);
86 
87     if (rsURL.indexOf('*') >= 0 || rsURL.indexOf('?') >= 0)
88     {
89         // The URL is a URL pattern not an single URL.
90         maFactoryPatternList.push_back(FactoryPatternList::value_type(rsURL, rxFactory));
91     }
92     else
93     {
94         maFactoryMap[rsURL] = rxFactory;
95     }
96 }
97 
98 
99 
100 
101 void ResourceFactoryManager::RemoveFactoryForURL (
102     const OUString& rsURL)
103     throw (RuntimeException)
104 {
105     if (rsURL.getLength() == 0)
106         throw lang::IllegalArgumentException();
107 
108     ::osl::MutexGuard aGuard (maMutex);
109 
110     FactoryMap::iterator iFactory (maFactoryMap.find(rsURL));
111     if (iFactory != maFactoryMap.end())
112     {
113         maFactoryMap.erase(iFactory);
114     }
115     else
116     {
117         // The URL may be a pattern.  Look that up.
118         FactoryPatternList::iterator iPattern;
119         for (iPattern=maFactoryPatternList.begin();
120              iPattern!=maFactoryPatternList.end();
121              ++iPattern)
122         {
123             if (iPattern->first == rsURL)
124             {
125                 // Found the pattern.  Remove it.
126                 maFactoryPatternList.erase(iPattern);
127                 break;
128             }
129         }
130     }
131 }
132 
133 
134 
135 
136 
137 void ResourceFactoryManager::RemoveFactoryForReference(
138     const Reference<XResourceFactory>& rxFactory)
139     throw (RuntimeException)
140 {
141     ::osl::MutexGuard aGuard (maMutex);
142 
143     // Collect a list with all keys that map to the given factory.
144     ::std::vector<OUString> aKeys;
145     FactoryMap::const_iterator iFactory;
146     for (iFactory=maFactoryMap.begin(); iFactory!=maFactoryMap.end(); ++iFactory)
147         if (iFactory->second == rxFactory)
148             aKeys.push_back(iFactory->first);
149 
150     // Remove the entries whose keys we just have collected.
151     ::std::vector<OUString>::const_iterator iKey;
152     for (iKey=aKeys.begin(); iKey!=aKeys.end();  ++iKey)
153         maFactoryMap.erase(maFactoryMap.find(*iKey));
154 
155     // Remove the pattern entries whose factories are identical to the given
156     // factory.
157     FactoryPatternList::iterator iNewEnd (
158         std::remove_if(
159             maFactoryPatternList.begin(),
160             maFactoryPatternList.end(),
161             ::boost::bind(
162                 std::equal_to<Reference<XResourceFactory> >(),
163                 ::boost::bind(&FactoryPatternList::value_type::second, _1),
164                 rxFactory)));
165     if (iNewEnd != maFactoryPatternList.end())
166         maFactoryPatternList.erase(iNewEnd, maFactoryPatternList.end());
167 }
168 
169 
170 
171 
172 Reference<XResourceFactory> ResourceFactoryManager::GetFactory (
173     const OUString& rsCompleteURL)
174     throw (RuntimeException)
175 {
176     OUString sURLBase (rsCompleteURL);
177     if (mxURLTransformer.is())
178     {
179         util::URL aURL;
180         aURL.Complete = rsCompleteURL;
181         if (mxURLTransformer->parseStrict(aURL))
182             sURLBase = aURL.Main;
183     }
184 
185     Reference<XResourceFactory> xFactory = FindFactory(sURLBase);
186 
187     if ( ! xFactory.is() && mxControllerManager.is())
188     {
189         Reference<XModuleController> xModuleController(mxControllerManager->getModuleController());
190         if (xModuleController.is())
191         {
192             // Ask the module controller to provide a factory of the
193             // requested view type.  Note that this can (and should) cause
194             // intermediate calls to AddFactory().
195             xModuleController->requestResource(sURLBase);
196 
197             xFactory = FindFactory(sURLBase);
198         }
199     }
200 
201     return xFactory;
202 }
203 
204 
205 
206 
207 Reference<XResourceFactory> ResourceFactoryManager::FindFactory (const OUString& rsURLBase)
208     throw (RuntimeException)
209 {
210     ::osl::MutexGuard aGuard (maMutex);
211     FactoryMap::const_iterator iFactory (maFactoryMap.find(rsURLBase));
212     if (iFactory != maFactoryMap.end())
213         return iFactory->second;
214     else
215     {
216         // Check the URL patterns.
217         FactoryPatternList::const_iterator iPattern;
218         for (iPattern=maFactoryPatternList.begin();
219              iPattern!=maFactoryPatternList.end();
220              ++iPattern)
221         {
222             WildCard aWildCard (iPattern->first);
223             if (aWildCard.Matches(rsURLBase))
224                 return iPattern->second;
225         }
226     }
227     return NULL;
228 }
229 
230 } } // end of namespace sd::framework
231