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