Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "framework/ResourceId.hxx"
22 : #include "framework/FrameworkHelper.hxx"
23 : #include "tools/SdGlobalResourceContainer.hxx"
24 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
25 : #include <com/sun/star/uno/XComponentContext.hpp>
26 : #include <com/sun/star/util/URLTransformer.hpp>
27 : #include <comphelper/processfactory.hxx>
28 : #include <rtl/ref.hxx>
29 :
30 : using namespace ::com::sun::star;
31 : using namespace ::com::sun::star::uno;
32 : using namespace ::com::sun::star::lang;
33 : using namespace ::com::sun::star::drawing::framework;
34 :
35 : /** When the USE_OPTIMIZATIONS symbol is defined then at some optimizations
36 : are activated that work only together with XResourceId objects that are
37 : implemented by the ResourceId class. For other implementations of when
38 : the USE_OPTIMIZATIONS symbol is not defined then alternative code is
39 : used instead.
40 : */
41 : #define USE_OPTIMIZATIONS
42 :
43 : namespace sd { namespace framework {
44 :
45 0 : Reference<XInterface> SAL_CALL ResourceId_createInstance (
46 : const Reference<XComponentContext>& rxContext)
47 : {
48 : (void)rxContext;
49 0 : return Reference<XInterface>(static_cast<XWeak*>(new ::sd::framework::ResourceId()));
50 : }
51 :
52 :
53 :
54 :
55 0 : OUString ResourceId_getImplementationName (void) throw(RuntimeException)
56 : {
57 0 : return OUString("com.sun.star.comp.Draw.framework.ResourceId");
58 : }
59 :
60 :
61 :
62 :
63 0 : Sequence<OUString> SAL_CALL ResourceId_getSupportedServiceNames (void)
64 : throw (RuntimeException)
65 : {
66 0 : static const OUString sServiceName("com.sun.star.drawing.framework.ResourceId");
67 0 : return Sequence<OUString>(&sServiceName, 1);
68 : }
69 :
70 :
71 :
72 :
73 : //===== ResourceId ============================================================
74 :
75 0 : WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
76 :
77 0 : ResourceId::ResourceId (void)
78 : : ResourceIdInterfaceBase(),
79 : maResourceURLs(0),
80 0 : mpURL()
81 : {
82 0 : }
83 :
84 :
85 :
86 :
87 0 : ResourceId::ResourceId (
88 : const std::vector<OUString>& rResourceURLs)
89 : : ResourceIdInterfaceBase(),
90 : maResourceURLs(rResourceURLs),
91 0 : mpURL()
92 : {
93 0 : ParseResourceURL();
94 0 : }
95 :
96 :
97 :
98 :
99 0 : ResourceId::ResourceId (
100 : const OUString& rsResourceURL)
101 : : ResourceIdInterfaceBase(),
102 : maResourceURLs(1, rsResourceURL),
103 0 : mpURL()
104 : {
105 : // Handle the special case of an empty resource URL.
106 0 : if (rsResourceURL.isEmpty())
107 0 : maResourceURLs.clear();
108 0 : ParseResourceURL();
109 0 : }
110 :
111 :
112 :
113 :
114 0 : ResourceId::ResourceId (
115 : const OUString& rsResourceURL,
116 : const OUString& rsAnchorURL)
117 : : ResourceIdInterfaceBase(),
118 : maResourceURLs(2),
119 0 : mpURL()
120 : {
121 0 : maResourceURLs[0] = rsResourceURL;
122 0 : maResourceURLs[1] = rsAnchorURL;
123 0 : ParseResourceURL();
124 0 : }
125 :
126 :
127 :
128 :
129 0 : ResourceId::ResourceId (
130 : const OUString& rsResourceURL,
131 : const OUString& rsFirstAnchorURL,
132 : const Sequence<OUString>& rAnchorURLs)
133 : : ResourceIdInterfaceBase(),
134 0 : maResourceURLs(2+rAnchorURLs.getLength()),
135 0 : mpURL()
136 : {
137 0 : maResourceURLs[0] = rsResourceURL;
138 0 : maResourceURLs[1] = rsFirstAnchorURL;
139 0 : for (sal_Int32 nIndex=0; nIndex<rAnchorURLs.getLength(); ++nIndex)
140 0 : maResourceURLs[nIndex+2] = rAnchorURLs[nIndex];
141 0 : ParseResourceURL();
142 0 : }
143 :
144 :
145 :
146 :
147 0 : ResourceId::~ResourceId (void)
148 : {
149 0 : mpURL.reset();
150 0 : }
151 :
152 :
153 :
154 :
155 : OUString SAL_CALL
156 0 : ResourceId::getResourceURL (void)
157 : throw(com::sun::star::uno::RuntimeException, std::exception)
158 : {
159 0 : if (!maResourceURLs.empty())
160 0 : return maResourceURLs[0];
161 : else
162 0 : return OUString();
163 : }
164 :
165 :
166 :
167 :
168 : util::URL SAL_CALL
169 0 : ResourceId::getFullResourceURL (void)
170 : throw(com::sun::star::uno::RuntimeException, std::exception)
171 : {
172 0 : if (mpURL.get() != NULL)
173 0 : return *mpURL;
174 :
175 0 : Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
176 0 : if (xURLTransformer.is() && !maResourceURLs.empty() )
177 : {
178 0 : mpURL.reset(new util::URL);
179 0 : mpURL->Complete = maResourceURLs[0];
180 0 : xURLTransformer->parseStrict(*mpURL);
181 0 : return *mpURL;
182 : }
183 :
184 0 : util::URL aURL;
185 0 : if (!maResourceURLs.empty())
186 0 : aURL.Complete = maResourceURLs[0];
187 0 : return aURL;
188 : }
189 :
190 :
191 :
192 :
193 : sal_Bool SAL_CALL
194 0 : ResourceId::hasAnchor (void)
195 : throw (RuntimeException, std::exception)
196 : {
197 0 : return maResourceURLs.size()>1;
198 : }
199 :
200 :
201 :
202 :
203 : Reference<XResourceId> SAL_CALL
204 0 : ResourceId::getAnchor (void)
205 : throw (RuntimeException, std::exception)
206 : {
207 0 : ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
208 0 : const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
209 0 : if (nAnchorCount > 0)
210 : {
211 0 : rResourceId->maResourceURLs.resize(nAnchorCount);
212 0 : for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
213 0 : rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
214 : }
215 0 : return Reference<XResourceId>(rResourceId.get());
216 : }
217 :
218 :
219 :
220 :
221 : Sequence<OUString> SAL_CALL
222 0 : ResourceId::getAnchorURLs (void)
223 : throw (RuntimeException, std::exception)
224 : {
225 0 : const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
226 0 : if (nAnchorCount > 0)
227 : {
228 0 : Sequence<OUString> aAnchorURLs (nAnchorCount);
229 0 : for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
230 0 : aAnchorURLs[nIndex] = maResourceURLs[nIndex+1];
231 0 : return aAnchorURLs;
232 : }
233 : else
234 0 : return Sequence<OUString>();
235 : }
236 :
237 :
238 :
239 :
240 : OUString SAL_CALL
241 0 : ResourceId::getResourceTypePrefix (void)
242 : throw (RuntimeException, std::exception)
243 : {
244 0 : if (!maResourceURLs.empty() )
245 : {
246 : // Return the "private:resource/<type>/" prefix.
247 :
248 : // Get the prefix that ends with the second "/".
249 0 : const OUString& rsResourceURL (maResourceURLs[0]);
250 0 : sal_Int32 nPrefixEnd (rsResourceURL.indexOf('/', 0));
251 0 : if (nPrefixEnd >= 0)
252 0 : nPrefixEnd = rsResourceURL.indexOf('/', nPrefixEnd+1) + 1;
253 : else
254 0 : nPrefixEnd = 0;
255 :
256 0 : return rsResourceURL.copy(0,nPrefixEnd);
257 : }
258 : else
259 0 : return OUString();
260 : }
261 :
262 :
263 :
264 :
265 : sal_Int16 SAL_CALL
266 0 : ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
267 : throw (RuntimeException, std::exception)
268 : {
269 0 : sal_Int16 nResult (0);
270 :
271 0 : if ( ! rxResourceId.is())
272 : {
273 : // The empty reference is interpreted as empty resource id object.
274 0 : if (!maResourceURLs.empty())
275 0 : nResult = +1;
276 : else
277 0 : nResult = 0;
278 : }
279 : else
280 : {
281 0 : ResourceId* pId = NULL;
282 : #ifdef USE_OPTIMIZATIONS
283 0 : pId = dynamic_cast<ResourceId*>(rxResourceId.get());
284 : #endif
285 0 : if (pId != NULL)
286 : {
287 : // We have direct access to the implementation of the given
288 : // resource id object.
289 0 : nResult = CompareToLocalImplementation(*pId);
290 : }
291 : else
292 : {
293 : // We have to do the comparison via the UNO interface of the
294 : // given resource id object.
295 0 : nResult = CompareToExternalImplementation(rxResourceId);
296 : }
297 : }
298 :
299 0 : return nResult;
300 : }
301 :
302 :
303 :
304 :
305 0 : sal_Int16 ResourceId::CompareToLocalImplementation (const ResourceId& rId) const
306 : {
307 0 : sal_Int16 nResult (0);
308 :
309 0 : const sal_uInt32 nLocalURLCount (maResourceURLs.size());
310 0 : const sal_uInt32 nURLCount(rId.maResourceURLs.size());
311 :
312 : // Start comparison with the top most anchors.
313 0 : for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
314 0 : nIndex>=0 && nLocalIndex>=0;
315 : --nIndex,--nLocalIndex)
316 : {
317 0 : const OUString sLocalURL (maResourceURLs[nLocalIndex]);
318 0 : const OUString sURL (rId.maResourceURLs[nIndex]);
319 0 : const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
320 0 : if (nLocalResult != 0)
321 : {
322 0 : if (nLocalResult < 0)
323 0 : nResult = -1;
324 : else
325 0 : nResult = +1;
326 0 : break;
327 : }
328 0 : }
329 :
330 0 : if (nResult == 0)
331 : {
332 : // No difference found yet. When the lengths are the same then the
333 : // two resource ids are equivalent. Otherwise the shorter comes
334 : // first.
335 0 : if (nLocalURLCount != nURLCount)
336 : {
337 0 : if (nLocalURLCount < nURLCount)
338 0 : nResult = -1;
339 : else
340 0 : nResult = +1;
341 : }
342 : }
343 :
344 0 : return nResult;
345 : }
346 :
347 :
348 :
349 :
350 0 : sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
351 : {
352 0 : sal_Int16 nResult (0);
353 :
354 0 : const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
355 0 : const sal_uInt32 nLocalURLCount (maResourceURLs.size());
356 0 : const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
357 :
358 : // Start comparison with the top most anchors.
359 0 : sal_Int32 nLocalResult (0);
360 0 : for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
361 0 : nIndex>=0&&nLocalIndex>=0;
362 : --nIndex,--nLocalIndex)
363 : {
364 0 : if (nIndex == 0 )
365 0 : nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
366 : else
367 0 : nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
368 0 : if (nLocalResult != 0)
369 : {
370 0 : if (nLocalResult < 0)
371 0 : nResult = -1;
372 : else
373 0 : nResult = +1;
374 0 : break;
375 : }
376 : }
377 :
378 0 : if (nResult == 0)
379 : {
380 : // No difference found yet. When the lengths are the same then the
381 : // two resource ids are equivalent. Otherwise the shorter comes
382 : // first.
383 0 : if (nLocalURLCount != nURLCount)
384 : {
385 0 : if (nLocalURLCount < nURLCount)
386 0 : nResult = -1;
387 : else
388 0 : nResult = +1;
389 : }
390 : }
391 :
392 0 : return nResult;
393 : }
394 :
395 :
396 :
397 :
398 : sal_Bool SAL_CALL
399 0 : ResourceId::isBoundTo (
400 : const Reference<XResourceId>& rxResourceId,
401 : AnchorBindingMode eMode)
402 : throw (RuntimeException, std::exception)
403 : {
404 0 : if ( ! rxResourceId.is())
405 : {
406 : // An empty reference is interpreted as empty resource id.
407 0 : return IsBoundToAnchor(NULL, NULL, eMode);
408 : }
409 :
410 0 : ResourceId* pId = NULL;
411 : #ifdef USE_OPTIMIZATIONS
412 0 : pId = dynamic_cast<ResourceId*>(rxResourceId.get());
413 : #endif
414 0 : if (pId != NULL)
415 : {
416 0 : return IsBoundToAnchor(pId->maResourceURLs, eMode);
417 : }
418 : else
419 : {
420 0 : const OUString sResourceURL (rxResourceId->getResourceURL());
421 0 : const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
422 0 : return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
423 : }
424 : }
425 :
426 :
427 :
428 :
429 : sal_Bool SAL_CALL
430 0 : ResourceId::isBoundToURL (
431 : const OUString& rsAnchorURL,
432 : AnchorBindingMode eMode)
433 : throw (RuntimeException, std::exception)
434 : {
435 0 : return IsBoundToAnchor(&rsAnchorURL, NULL, eMode);
436 : }
437 :
438 :
439 :
440 :
441 : Reference<XResourceId> SAL_CALL
442 0 : ResourceId::clone (void)
443 : throw(RuntimeException, std::exception)
444 : {
445 0 : return new ResourceId(maResourceURLs);
446 : }
447 :
448 :
449 :
450 :
451 : //----- XInitialization -------------------------------------------------------
452 :
453 0 : void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
454 : throw (RuntimeException, std::exception)
455 : {
456 0 : sal_uInt32 nCount (aArguments.getLength());
457 0 : for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
458 : {
459 0 : OUString sResourceURL;
460 0 : if (aArguments[nIndex] >>= sResourceURL)
461 0 : maResourceURLs.push_back(sResourceURL);
462 : else
463 : {
464 0 : Reference<XResourceId> xAnchor;
465 0 : if (aArguments[nIndex] >>= xAnchor)
466 : {
467 0 : if (xAnchor.is())
468 : {
469 0 : maResourceURLs.push_back(xAnchor->getResourceURL());
470 0 : Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
471 0 : for (sal_Int32 nURLIndex=0; nURLIndex<aAnchorURLs.getLength(); ++nURLIndex)
472 : {
473 0 : maResourceURLs.push_back(aAnchorURLs[nURLIndex]);
474 0 : }
475 : }
476 0 : }
477 : }
478 0 : }
479 0 : ParseResourceURL();
480 0 : }
481 :
482 :
483 :
484 :
485 :
486 :
487 : /** When eMode is DIRECTLY then the anchor of the called object and the
488 : anchor represented by the given sequence of anchor URLs have to be
489 : identical. When eMode is RECURSIVE then the anchor of the called
490 : object has to start with the given anchor URLs.
491 : */
492 0 : bool ResourceId::IsBoundToAnchor (
493 : const OUString* psFirstAnchorURL,
494 : const Sequence<OUString>* paAnchorURLs,
495 : AnchorBindingMode eMode) const
496 : {
497 0 : const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
498 0 : const bool bHasFirstAnchorURL (psFirstAnchorURL!=NULL);
499 : const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
500 0 : + (paAnchorURLs!=NULL ? paAnchorURLs->getLength() : 0));
501 :
502 : // Check the lengths.
503 0 : if (nLocalAnchorURLCount<nAnchorURLCount ||
504 0 : (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
505 : {
506 0 : return false;
507 : }
508 :
509 : // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
510 : // id and the given anchor.
511 0 : sal_uInt32 nOffset = 0;
512 0 : if (paAnchorURLs != NULL)
513 : {
514 0 : sal_uInt32 nCount = paAnchorURLs->getLength();
515 0 : while (nOffset < nCount)
516 : {
517 0 : if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
518 0 : (*paAnchorURLs)[nCount - 1 - nOffset]))
519 : {
520 0 : return false;
521 : }
522 0 : ++nOffset;
523 : }
524 : }
525 0 : if (bHasFirstAnchorURL)
526 : {
527 0 : if ( ! psFirstAnchorURL->equals(maResourceURLs[nLocalAnchorURLCount - nOffset]))
528 0 : return false;
529 : }
530 :
531 0 : return true;
532 : }
533 :
534 :
535 :
536 :
537 0 : bool ResourceId::IsBoundToAnchor (
538 : const ::std::vector<OUString>& rAnchorURLs,
539 : AnchorBindingMode eMode) const
540 : {
541 0 : const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
542 0 : const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
543 :
544 : // Check the lengths.
545 0 : if (nLocalAnchorURLCount<nAnchorURLCount ||
546 0 : (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
547 : {
548 0 : return false;
549 : }
550 :
551 : // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
552 : // id and the given anchor.
553 0 : for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
554 : {
555 0 : if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
556 0 : rAnchorURLs[nAnchorURLCount - 1 - nOffset]))
557 : {
558 0 : return false;
559 : }
560 : }
561 :
562 0 : return true;
563 : }
564 :
565 :
566 :
567 :
568 0 : void ResourceId::ParseResourceURL (void)
569 : {
570 0 : ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
571 0 : Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
572 0 : if ( ! xURLTransformer.is())
573 : {
574 : // Create the URL transformer.
575 0 : Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
576 0 : xURLTransformer = Reference<util::XURLTransformer>(util::URLTransformer::create(xContext));
577 0 : mxURLTransformerWeak = xURLTransformer;
578 0 : SdGlobalResourceContainer::Instance().AddResource(
579 0 : Reference<XInterface>(xURLTransformer,UNO_QUERY));
580 : }
581 :
582 0 : if (xURLTransformer.is() && !maResourceURLs.empty() )
583 : {
584 0 : mpURL.reset(new util::URL);
585 0 : mpURL->Complete = maResourceURLs[0];
586 0 : xURLTransformer->parseStrict(*mpURL);
587 0 : if (mpURL->Main == maResourceURLs[0])
588 0 : mpURL.reset();
589 : else
590 0 : maResourceURLs[0] = mpURL->Main;
591 0 : }
592 0 : }
593 :
594 :
595 0 : } } // end of namespace sd::framework
596 :
597 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|