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