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 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : - HierarchyEntry::move
26 : --> Rewrite to use XNamed ( once this is supported by config db api ).
27 :
28 : *************************************************************************/
29 : #include "hierarchydata.hxx"
30 :
31 : #include <vector>
32 : #include <osl/diagnose.h>
33 : #include <rtl/ustrbuf.hxx>
34 : #include <com/sun/star/beans/PropertyValue.hpp>
35 : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
36 : #include <com/sun/star/container/XNameContainer.hpp>
37 : #include <com/sun/star/container/XNameReplace.hpp>
38 : #include <com/sun/star/util/XChangesBatch.hpp>
39 : #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
40 : #include "hierarchyprovider.hxx"
41 : #include "hierarchyuri.hxx"
42 :
43 : using namespace com::sun::star;
44 :
45 : namespace hierarchy_ucp
46 : {
47 :
48 : //=========================================================================
49 0 : struct HierarchyEntry::iterator_Impl
50 : {
51 : HierarchyEntryData entry;
52 : uno::Reference< container::XHierarchicalNameAccess > dir;
53 : uno::Reference< util::XOfficeInstallationDirectories > officeDirs;
54 : uno::Sequence< rtl::OUString> names;
55 : sal_Int32 pos;
56 0 : iterator_Impl()
57 0 : : officeDirs( 0 ), pos( -1 /* before first */ ) {};
58 : };
59 :
60 : //=========================================================================
61 0 : void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer )
62 : {
63 0 : sal_Int32 nCount = rIn.getLength();
64 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
65 : {
66 0 : const sal_Unicode c = rIn.getStr()[ n ];
67 0 : switch ( c )
68 : {
69 : case '&':
70 0 : rBuffer.appendAscii( "&" );
71 0 : break;
72 :
73 : case '"':
74 0 : rBuffer.appendAscii( """ );
75 0 : break;
76 :
77 : case '\'':
78 0 : rBuffer.appendAscii( "'" );
79 0 : break;
80 :
81 : case '<':
82 0 : rBuffer.appendAscii( "<" );
83 0 : break;
84 :
85 : case '>':
86 0 : rBuffer.appendAscii( ">" );
87 0 : break;
88 :
89 : default:
90 0 : rBuffer.append( c );
91 0 : break;
92 : }
93 : }
94 0 : }
95 :
96 : //=========================================================================
97 : //=========================================================================
98 : //
99 : // HierarchyEntry Implementation.
100 : //
101 : //=========================================================================
102 : //=========================================================================
103 :
104 : #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
105 : #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
106 :
107 : // describe path of cfg entry
108 : #define CFGPROPERTY_NODEPATH "nodepath"
109 :
110 : //=========================================================================
111 0 : HierarchyEntry::HierarchyEntry(
112 : const uno::Reference< uno::XComponentContext >& rxContext,
113 : HierarchyContentProvider* pProvider,
114 : const rtl::OUString& rURL )
115 : : m_xContext( rxContext ),
116 : m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
117 0 : m_bTriedToGetRootReadAccess( sal_False )
118 : {
119 0 : HierarchyUri aUri( rURL );
120 0 : m_aServiceSpecifier = aUri.getService();
121 :
122 0 : if ( pProvider )
123 : {
124 : m_xConfigProvider
125 0 : = pProvider->getConfigProvider( m_aServiceSpecifier );
126 : m_xRootReadAccess
127 0 : = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
128 : }
129 :
130 : // Note: do not init m_aPath in init list. createPathFromHierarchyURL
131 : // needs m_xContext and m_aMutex.
132 0 : m_aPath = createPathFromHierarchyURL( aUri );
133 :
134 : // Extract language independent name from URL.
135 0 : sal_Int32 nPos = rURL.lastIndexOf( '/' );
136 0 : if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
137 0 : m_aName = rURL.copy( nPos + 1 );
138 : else
139 0 : OSL_FAIL( "HierarchyEntry - Invalid URL!" );
140 0 : }
141 :
142 : //=========================================================================
143 0 : sal_Bool HierarchyEntry::hasData()
144 : {
145 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
146 : uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
147 0 : = getRootReadAccess();
148 :
149 : OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
150 :
151 0 : if ( xRootReadAccess.is() )
152 0 : return xRootReadAccess->hasByHierarchicalName( m_aPath );
153 :
154 0 : return sal_False;
155 : }
156 :
157 : //=========================================================================
158 0 : sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData )
159 : {
160 : try
161 : {
162 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
163 :
164 : uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
165 0 : = getRootReadAccess();
166 :
167 : OSL_ENSURE( xRootReadAccess.is(),
168 : "HierarchyEntry::getData - No root!" );
169 :
170 0 : if ( xRootReadAccess.is() )
171 : {
172 0 : rtl::OUString aTitlePath = m_aPath;
173 0 : aTitlePath += rtl::OUString("/Title");
174 :
175 : // Note: Avoid NoSuchElementExceptions, because exceptions are
176 : // relatively 'expensive'. Checking for availability of
177 : // title value is sufficient here, because if it is
178 : // there, the other values will be available too.
179 0 : if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
180 0 : return sal_False;
181 :
182 0 : rtl::OUString aValue;
183 :
184 : // Get Title value.
185 0 : if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
186 0 : >>= aValue ) )
187 : {
188 : OSL_FAIL( "HierarchyEntry::getData - "
189 : "Got no Title value!" );
190 0 : return sal_False;
191 : }
192 :
193 0 : rData.setTitle( aValue );
194 :
195 : // Get TargetURL value.
196 0 : rtl::OUString aTargetURLPath = m_aPath;
197 0 : aTargetURLPath += rtl::OUString("/TargetURL");
198 0 : if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
199 0 : >>= aValue ) )
200 : {
201 : OSL_FAIL( "HierarchyEntry::getData - "
202 : "Got no TargetURL value!" );
203 0 : return sal_False;
204 : }
205 :
206 : // TargetURL property may contain a reference to the Office
207 : // installation directory. To ensure a reloctable office
208 : // installation, the path to the office installtion directory must
209 : // never be stored directly. A placeholder is used instead. Replace
210 : // it by actual installation directory.
211 0 : if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
212 0 : aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
213 0 : rData.setTargetURL( aValue );
214 :
215 0 : rtl::OUString aTypePath = m_aPath;
216 0 : aTypePath += rtl::OUString("/Type");
217 0 : if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
218 : {
219 : // Might not be present since it was introduced long after
220 : // Title and TargetURL (#82433#)... So not getting it is
221 : // not an error.
222 :
223 : // Get Type value.
224 0 : sal_Int32 nType = 0;
225 0 : if ( xRootReadAccess->getByHierarchicalName( aTypePath )
226 0 : >>= nType )
227 : {
228 0 : if ( nType == 0 )
229 : {
230 0 : rData.setType( HierarchyEntryData::LINK );
231 : }
232 0 : else if ( nType == 1 )
233 : {
234 0 : rData.setType( HierarchyEntryData::FOLDER );
235 : }
236 : else
237 : {
238 : OSL_FAIL( "HierarchyEntry::getData - "
239 : "Unknown Type value!" );
240 0 : return sal_False;
241 : }
242 : }
243 : }
244 :
245 0 : rData.setName( m_aName );
246 0 : return sal_True;
247 0 : }
248 : }
249 0 : catch ( uno::RuntimeException const & )
250 : {
251 0 : throw;
252 : }
253 0 : catch ( container::NoSuchElementException const & )
254 : {
255 : // getByHierarchicalName
256 :
257 : OSL_FAIL( "HierarchyEntry::getData - caught NoSuchElementException!" );
258 : }
259 0 : return sal_False;
260 : }
261 :
262 : //=========================================================================
263 0 : sal_Bool HierarchyEntry::setData(
264 : const HierarchyEntryData& rData, sal_Bool bCreate )
265 : {
266 : try
267 : {
268 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
269 :
270 0 : if ( !m_xConfigProvider.is() )
271 : m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
272 0 : m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
273 0 : uno::UNO_QUERY );
274 :
275 0 : if ( m_xConfigProvider.is() )
276 : {
277 : // Create parent's key. It must exist!
278 :
279 0 : rtl::OUString aParentPath;
280 0 : sal_Bool bRoot = sal_True;
281 :
282 0 : sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
283 0 : if ( nPos != -1 )
284 : {
285 : // Skip "/Children" segment of the path, too.
286 0 : nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
287 :
288 : OSL_ENSURE( nPos != -1,
289 : "HierarchyEntry::setData - Wrong path!" );
290 :
291 0 : aParentPath += m_aPath.copy( 0, nPos );
292 0 : bRoot = sal_False;
293 : }
294 :
295 0 : uno::Sequence< uno::Any > aArguments( 1 );
296 0 : beans::PropertyValue aProperty;
297 :
298 0 : aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
299 0 : aProperty.Value <<= aParentPath;
300 0 : aArguments[ 0 ] <<= aProperty;
301 :
302 : uno::Reference< util::XChangesBatch > xBatch(
303 0 : m_xConfigProvider->createInstanceWithArguments(
304 : rtl::OUString( READWRITE_SERVICE_NAME ),
305 0 : aArguments ),
306 0 : uno::UNO_QUERY );
307 :
308 : OSL_ENSURE( xBatch.is(),
309 : "HierarchyEntry::setData - No batch!" );
310 :
311 : uno::Reference< container::XNameAccess > xParentNameAccess(
312 0 : xBatch, uno::UNO_QUERY );
313 :
314 : OSL_ENSURE( xParentNameAccess.is(),
315 : "HierarchyEntry::setData - No name access!" );
316 :
317 0 : if ( xBatch.is() && xParentNameAccess.is() )
318 : {
319 : // Try to create own key. It must not exist!
320 :
321 0 : sal_Bool bExists = sal_True;
322 0 : uno::Any aMyKey;
323 :
324 : try
325 : {
326 0 : uno::Reference< container::XNameAccess > xNameAccess;
327 :
328 0 : if ( bRoot )
329 : {
330 0 : xNameAccess = xParentNameAccess;
331 : }
332 : else
333 : {
334 0 : xParentNameAccess->getByName(
335 0 : rtl::OUString("Children") )
336 0 : >>= xNameAccess;
337 : }
338 :
339 0 : if ( xNameAccess->hasByName( m_aName ) )
340 0 : aMyKey = xNameAccess->getByName( m_aName );
341 : else
342 0 : bExists = sal_False;
343 : }
344 0 : catch ( container::NoSuchElementException const & )
345 : {
346 0 : bExists = sal_False;
347 : }
348 :
349 0 : uno::Reference< container::XNameReplace > xNameReplace;
350 0 : uno::Reference< container::XNameContainer > xContainer;
351 :
352 0 : if ( bExists )
353 : {
354 : // Key exists. Replace values.
355 :
356 0 : aMyKey >>= xNameReplace;
357 :
358 : OSL_ENSURE( xNameReplace.is(),
359 : "HierarchyEntry::setData - No name replace!" );
360 : }
361 : else
362 : {
363 0 : if ( !bCreate )
364 0 : return sal_True;
365 :
366 : // Key does not exist. Create / fill / insert it.
367 :
368 0 : uno::Reference< lang::XSingleServiceFactory > xFac;
369 :
370 0 : if ( bRoot )
371 : {
372 : // Special handling for children of root,
373 : // which is not an entry. It's only a set
374 : // of entries.
375 : xFac = uno::Reference< lang::XSingleServiceFactory >(
376 0 : xParentNameAccess, uno::UNO_QUERY );
377 : }
378 : else
379 : {
380 : // Append new entry to parents child list,
381 : // which is a set of entries.
382 0 : xParentNameAccess->getByName(
383 0 : rtl::OUString( "Children" ) ) >>= xFac;
384 : }
385 :
386 : OSL_ENSURE( xFac.is(),
387 : "HierarchyEntry::setData - No factory!" );
388 :
389 0 : if ( xFac.is() )
390 : {
391 : xNameReplace
392 : = uno::Reference< container::XNameReplace >(
393 0 : xFac->createInstance(), uno::UNO_QUERY );
394 :
395 : OSL_ENSURE( xNameReplace.is(),
396 : "HierarchyEntry::setData - No name replace!" );
397 :
398 0 : if ( xNameReplace.is() )
399 : {
400 : xContainer
401 : = uno::Reference< container::XNameContainer >(
402 0 : xFac, uno::UNO_QUERY );
403 :
404 : OSL_ENSURE( xContainer.is(),
405 : "HierarchyEntry::setData - No container!" );
406 : }
407 0 : }
408 : }
409 :
410 0 : if ( xNameReplace.is() )
411 : {
412 : // Set Title value.
413 0 : xNameReplace->replaceByName(
414 : rtl::OUString("Title"),
415 0 : uno::makeAny( rData.getTitle() ) );
416 :
417 : // Set TargetURL value.
418 :
419 : // TargetURL property may contain a reference to the Office
420 : // installation directory. To ensure a reloctable office
421 : // installation, the path to the office installtion
422 : // directory must never be stored directly. Use a
423 : // placeholder instead.
424 0 : rtl::OUString aValue( rData.getTargetURL() );
425 0 : if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
426 : aValue
427 0 : = m_xOfficeInstDirs->makeRelocatableURL( aValue );
428 :
429 0 : xNameReplace->replaceByName(
430 : rtl::OUString("TargetURL"),
431 0 : uno::makeAny( aValue ) );
432 :
433 : // Set Type value.
434 : sal_Int32 nType
435 0 : = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
436 0 : xNameReplace->replaceByName(
437 : rtl::OUString("Type"),
438 0 : uno::makeAny( nType ) );
439 :
440 0 : if ( xContainer.is() )
441 0 : xContainer->insertByName(
442 0 : m_aName, uno::makeAny( xNameReplace ) );
443 :
444 : // Commit changes.
445 0 : xBatch->commitChanges();
446 0 : return sal_True;
447 0 : }
448 0 : }
449 0 : }
450 : }
451 0 : catch ( lang::IllegalArgumentException const & )
452 : {
453 : // replaceByName, insertByName
454 :
455 : OSL_FAIL(
456 : "HierarchyEntry::setData - caught IllegalArgumentException!" );
457 : }
458 0 : catch ( uno::RuntimeException const & )
459 : {
460 0 : throw;
461 : }
462 0 : catch ( container::NoSuchElementException const & )
463 : {
464 : // replaceByName, getByName
465 :
466 : OSL_FAIL(
467 : "HierarchyEntry::setData - caught NoSuchElementException!" );
468 : }
469 0 : catch ( container::ElementExistException const & )
470 : {
471 : // insertByName
472 :
473 : OSL_FAIL(
474 : "HierarchyEntry::setData - caught ElementExistException!" );
475 : }
476 0 : catch ( lang::WrappedTargetException const & )
477 : {
478 : // replaceByName, insertByName, getByName, commitChanges
479 :
480 : OSL_FAIL(
481 : "HierarchyEntry::setData - caught WrappedTargetException!" );
482 : }
483 0 : catch ( uno::Exception const & )
484 : {
485 : // createInstance, createInstanceWithArguments
486 :
487 : OSL_FAIL(
488 : "HierarchyEntry::setData - caught Exception!" );
489 : }
490 :
491 0 : return sal_False;
492 : }
493 :
494 : //=========================================================================
495 0 : sal_Bool HierarchyEntry::move(
496 : const rtl::OUString& rNewURL, const HierarchyEntryData& rData )
497 : {
498 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
499 :
500 0 : rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL );
501 :
502 0 : if ( aNewPath == m_aPath )
503 0 : return sal_True;
504 :
505 0 : sal_Bool bOldRoot = sal_True;
506 0 : uno::Reference< util::XChangesBatch > xOldParentBatch;
507 :
508 0 : rtl::OUString aNewKey;
509 0 : sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
510 0 : if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
511 0 : aNewKey = rNewURL.copy( nURLPos + 1 );
512 : else
513 : {
514 : OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
515 0 : return sal_False;
516 : }
517 :
518 0 : sal_Bool bNewRoot = sal_True;
519 0 : uno::Reference< util::XChangesBatch > xNewParentBatch;
520 :
521 0 : sal_Bool bDifferentParents = sal_True;
522 :
523 : try
524 : {
525 0 : if ( !m_xConfigProvider.is() )
526 : m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
527 0 : m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
528 0 : uno::UNO_QUERY );
529 :
530 0 : if ( !m_xConfigProvider.is() )
531 0 : return sal_False;
532 :
533 0 : rtl::OUString aOldParentPath;
534 0 : sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
535 0 : if ( nPos != -1 )
536 : {
537 : // Skip "/Children" segment of the path, too.
538 0 : nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
539 :
540 : OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
541 :
542 0 : aOldParentPath += m_aPath.copy( 0, nPos );
543 0 : bOldRoot = sal_False;
544 : }
545 :
546 0 : rtl::OUString aNewParentPath;
547 0 : nPos = aNewPath.lastIndexOf( '/' );
548 0 : if ( nPos != -1 )
549 : {
550 : // Skip "/Children" segment of the path, too.
551 0 : nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
552 :
553 : OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
554 :
555 0 : aNewParentPath += aNewPath.copy( 0, nPos );
556 0 : bNewRoot = sal_False;
557 : }
558 :
559 0 : uno::Sequence< uno::Any > aArguments( 1 );
560 0 : beans::PropertyValue aProperty;
561 :
562 0 : aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
563 0 : aProperty.Value <<= aOldParentPath;
564 0 : aArguments[ 0 ] <<= aProperty;
565 :
566 : xOldParentBatch = uno::Reference< util::XChangesBatch >(
567 0 : m_xConfigProvider->createInstanceWithArguments(
568 : rtl::OUString( READWRITE_SERVICE_NAME ),
569 0 : aArguments ),
570 0 : uno::UNO_QUERY );
571 :
572 : OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
573 :
574 0 : if ( !xOldParentBatch.is() )
575 0 : return sal_False;
576 :
577 0 : if ( aOldParentPath == aNewParentPath )
578 : {
579 0 : bDifferentParents = sal_False;
580 0 : xNewParentBatch = xOldParentBatch;
581 : }
582 : else
583 : {
584 0 : bDifferentParents = sal_True;
585 :
586 0 : aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
587 0 : aProperty.Value <<= aNewParentPath;
588 0 : aArguments[ 0 ] <<= aProperty;
589 :
590 : xNewParentBatch = uno::Reference< util::XChangesBatch >(
591 0 : m_xConfigProvider->createInstanceWithArguments(
592 : rtl::OUString( READWRITE_SERVICE_NAME ),
593 0 : aArguments ),
594 0 : uno::UNO_QUERY );
595 :
596 : OSL_ENSURE(
597 : xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
598 :
599 0 : if ( !xNewParentBatch.is() )
600 0 : return sal_False;
601 0 : }
602 : }
603 0 : catch ( uno::RuntimeException const & )
604 : {
605 0 : throw;
606 : }
607 0 : catch ( uno::Exception const & )
608 : {
609 : // createInstance, createInstanceWithArguments
610 :
611 : OSL_FAIL( "HierarchyEntry::move - caught Exception!" );
612 0 : return sal_False;
613 : }
614 :
615 : //////////////////////////////////////////////////////////////////////
616 : // (1) Get entry...
617 : //////////////////////////////////////////////////////////////////////
618 :
619 0 : uno::Any aEntry;
620 0 : uno::Reference< container::XNameAccess > xOldParentNameAccess;
621 0 : uno::Reference< container::XNameContainer > xOldNameContainer;
622 :
623 : try
624 : {
625 : xOldParentNameAccess
626 : = uno::Reference< container::XNameAccess >(
627 0 : xOldParentBatch, uno::UNO_QUERY );
628 :
629 : OSL_ENSURE( xOldParentNameAccess.is(),
630 : "HierarchyEntry::move - No name access!" );
631 :
632 0 : if ( !xOldParentNameAccess.is() )
633 0 : return sal_False;
634 :
635 0 : if ( bOldRoot )
636 : {
637 : xOldNameContainer = uno::Reference< container::XNameContainer >(
638 0 : xOldParentNameAccess, uno::UNO_QUERY );
639 : }
640 : else
641 : {
642 0 : xOldParentNameAccess->getByName(
643 0 : rtl::OUString("Children") )
644 0 : >>= xOldNameContainer;
645 : }
646 :
647 0 : aEntry = xOldNameContainer->getByName( m_aName );
648 : }
649 0 : catch ( container::NoSuchElementException const & )
650 : {
651 : // getByName
652 :
653 : OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
654 0 : return sal_False;
655 : }
656 0 : catch ( lang::WrappedTargetException const & )
657 : {
658 : // getByName
659 :
660 : OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
661 0 : return sal_False;
662 : }
663 :
664 : //////////////////////////////////////////////////////////////////////
665 : // (2) Remove entry... Note: Insert BEFORE remove does not work!
666 : //////////////////////////////////////////////////////////////////////
667 :
668 : try
669 : {
670 0 : xOldNameContainer->removeByName( m_aName );
671 0 : xOldParentBatch->commitChanges();
672 : }
673 0 : catch ( container::NoSuchElementException const & )
674 : {
675 : // getByName, removeByName
676 :
677 : OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
678 0 : return sal_False;
679 : }
680 :
681 : //////////////////////////////////////////////////////////////////////
682 : // (3) Insert entry at new parent...
683 : //////////////////////////////////////////////////////////////////////
684 :
685 : try
686 : {
687 0 : uno::Reference< container::XNameReplace > xNewNameReplace;
688 0 : aEntry >>= xNewNameReplace;
689 :
690 : OSL_ENSURE( xNewNameReplace.is(),
691 : "HierarchyEntry::move - No name replace!" );
692 :
693 0 : if ( !xNewNameReplace.is() )
694 0 : return sal_False;
695 :
696 0 : uno::Reference< container::XNameAccess > xNewParentNameAccess;
697 0 : if ( bDifferentParents )
698 : xNewParentNameAccess
699 : = uno::Reference< container::XNameAccess >(
700 0 : xNewParentBatch, uno::UNO_QUERY );
701 : else
702 0 : xNewParentNameAccess = xOldParentNameAccess;
703 :
704 : OSL_ENSURE( xNewParentNameAccess.is(),
705 : "HierarchyEntry::move - No name access!" );
706 :
707 0 : if ( !xNewParentNameAccess.is() )
708 0 : return sal_False;
709 :
710 0 : uno::Reference< container::XNameContainer > xNewNameContainer;
711 0 : if ( bDifferentParents )
712 : {
713 0 : if ( bNewRoot )
714 : {
715 : xNewNameContainer
716 : = uno::Reference< container::XNameContainer >(
717 0 : xNewParentNameAccess, uno::UNO_QUERY );
718 : }
719 : else
720 : {
721 0 : xNewParentNameAccess->getByName(
722 0 : rtl::OUString("Children") )
723 0 : >>= xNewNameContainer;
724 : }
725 : }
726 : else
727 0 : xNewNameContainer = xOldNameContainer;
728 :
729 0 : if ( !xNewNameContainer.is() )
730 0 : return sal_False;
731 :
732 0 : xNewNameReplace->replaceByName(
733 : rtl::OUString("Title"),
734 0 : uno::makeAny( rData.getTitle() ) );
735 :
736 : // TargetURL property may contain a reference to the Office
737 : // installation directory. To ensure a reloctable office
738 : // installation, the path to the office installtion
739 : // directory must never be stored directly. Use a placeholder
740 : // instead.
741 0 : rtl::OUString aValue( rData.getTargetURL() );
742 0 : if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
743 0 : aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
744 0 : xNewNameReplace->replaceByName(
745 : rtl::OUString("TargetURL"),
746 0 : uno::makeAny( aValue ) );
747 0 : sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
748 0 : xNewNameReplace->replaceByName(
749 : rtl::OUString("Type"),
750 0 : uno::makeAny( nType ) );
751 :
752 0 : xNewNameContainer->insertByName( aNewKey, aEntry );
753 0 : xNewParentBatch->commitChanges();
754 : }
755 0 : catch ( container::NoSuchElementException const & )
756 : {
757 : // replaceByName, insertByName, getByName
758 :
759 : OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
760 0 : return sal_False;
761 : }
762 0 : catch ( lang::IllegalArgumentException const & )
763 : {
764 : // replaceByName, insertByName
765 :
766 : OSL_FAIL(
767 : "HierarchyEntry::move - caught IllegalArgumentException!" );
768 0 : return sal_False;
769 : }
770 0 : catch ( container::ElementExistException const & )
771 : {
772 : // insertByName
773 :
774 : OSL_FAIL( "HierarchyEntry::move - caught ElementExistException!" );
775 0 : return sal_False;
776 : }
777 0 : catch ( lang::WrappedTargetException const & )
778 : {
779 : // replaceByName, insertByName, getByName
780 :
781 : OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
782 0 : return sal_False;
783 : }
784 :
785 0 : return sal_True;
786 : }
787 :
788 : //=========================================================================
789 0 : sal_Bool HierarchyEntry::remove()
790 : {
791 : try
792 : {
793 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
794 :
795 0 : if ( !m_xConfigProvider.is() )
796 : m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
797 0 : m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
798 0 : uno::UNO_QUERY );
799 :
800 0 : if ( m_xConfigProvider.is() )
801 : {
802 : // Create parent's key. It must exist!
803 :
804 0 : rtl::OUString aParentPath;
805 0 : sal_Bool bRoot = sal_True;
806 :
807 0 : sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
808 0 : if ( nPos != -1 )
809 : {
810 : // Skip "/Children" segment of the path, too.
811 0 : nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
812 :
813 : OSL_ENSURE( nPos != -1,
814 : "HierarchyEntry::remove - Wrong path!" );
815 :
816 0 : aParentPath += m_aPath.copy( 0, nPos );
817 0 : bRoot = sal_False;
818 : }
819 :
820 0 : uno::Sequence< uno::Any > aArguments( 1 );
821 0 : beans::PropertyValue aProperty;
822 :
823 0 : aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
824 0 : aProperty.Value <<= aParentPath;
825 0 : aArguments[ 0 ] <<= aProperty;
826 :
827 : uno::Reference< util::XChangesBatch > xBatch(
828 0 : m_xConfigProvider->createInstanceWithArguments(
829 : rtl::OUString( READWRITE_SERVICE_NAME ),
830 0 : aArguments ),
831 0 : uno::UNO_QUERY );
832 :
833 : OSL_ENSURE( xBatch.is(),
834 : "HierarchyEntry::remove - No batch!" );
835 :
836 : uno::Reference< container::XNameAccess > xParentNameAccess(
837 0 : xBatch, uno::UNO_QUERY );
838 :
839 : OSL_ENSURE( xParentNameAccess.is(),
840 : "HierarchyEntry::remove - No name access!" );
841 :
842 0 : if ( xBatch.is() && xParentNameAccess.is() )
843 : {
844 0 : uno::Reference< container::XNameContainer > xContainer;
845 :
846 0 : if ( bRoot )
847 : {
848 : // Special handling for children of root,
849 : // which is not an entry. It's only a set
850 : // of entries.
851 : xContainer = uno::Reference< container::XNameContainer >(
852 0 : xParentNameAccess, uno::UNO_QUERY );
853 : }
854 : else
855 : {
856 : // Append new entry to parents child list,
857 : // which is a set of entries.
858 0 : xParentNameAccess->getByName(
859 0 : rtl::OUString("Children") )
860 0 : >>= xContainer;
861 : }
862 :
863 : OSL_ENSURE( xContainer.is(),
864 : "HierarchyEntry::remove - No container!" );
865 :
866 0 : if ( xContainer.is() )
867 : {
868 0 : xContainer->removeByName( m_aName );
869 0 : xBatch->commitChanges();
870 0 : return sal_True;
871 0 : }
872 0 : }
873 0 : }
874 : }
875 0 : catch ( uno::RuntimeException const & )
876 : {
877 0 : throw;
878 : }
879 0 : catch ( container::NoSuchElementException const & )
880 : {
881 : // getByName, removeByName
882 :
883 : OSL_FAIL(
884 : "HierarchyEntry::remove - caught NoSuchElementException!" );
885 : }
886 0 : catch ( lang::WrappedTargetException const & )
887 : {
888 : // getByName, commitChanges
889 :
890 : OSL_FAIL(
891 : "HierarchyEntry::remove - caught WrappedTargetException!" );
892 : }
893 0 : catch ( uno::Exception const & )
894 : {
895 : // createInstance, createInstanceWithArguments
896 :
897 : OSL_FAIL( "HierarchyEntry::remove - caught Exception!" );
898 : }
899 :
900 0 : return sal_False;
901 : }
902 :
903 : //=========================================================================
904 0 : sal_Bool HierarchyEntry::first( iterator& it )
905 : {
906 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
907 :
908 0 : if ( it.m_pImpl->pos == -1 )
909 : {
910 : // Init...
911 :
912 : try
913 : {
914 : uno::Reference< container::XHierarchicalNameAccess >
915 0 : xRootHierNameAccess = getRootReadAccess();
916 :
917 0 : if ( xRootHierNameAccess.is() )
918 : {
919 0 : uno::Reference< container::XNameAccess > xNameAccess;
920 :
921 0 : if ( !m_aPath.isEmpty() )
922 : {
923 0 : rtl::OUString aPath = m_aPath;
924 0 : aPath += rtl::OUString("/Children");
925 :
926 0 : xRootHierNameAccess->getByHierarchicalName( aPath )
927 0 : >>= xNameAccess;
928 : }
929 : else
930 : xNameAccess
931 : = uno::Reference< container::XNameAccess >(
932 0 : xRootHierNameAccess, uno::UNO_QUERY );
933 :
934 : OSL_ENSURE( xNameAccess.is(),
935 : "HierarchyEntry::first - No name access!" );
936 :
937 0 : if ( xNameAccess.is() )
938 0 : it.m_pImpl->names = xNameAccess->getElementNames();
939 :
940 : uno::Reference< container::XHierarchicalNameAccess >
941 0 : xHierNameAccess( xNameAccess, uno::UNO_QUERY );
942 :
943 : OSL_ENSURE( xHierNameAccess.is(),
944 : "HierarchyEntry::first - No hier. name access!" );
945 :
946 0 : it.m_pImpl->dir = xHierNameAccess;
947 :
948 0 : it.m_pImpl->officeDirs = m_xOfficeInstDirs;
949 0 : }
950 : }
951 0 : catch ( uno::RuntimeException const & )
952 : {
953 0 : throw;
954 : }
955 0 : catch ( container::NoSuchElementException const& )
956 : {
957 : // getByHierarchicalName
958 :
959 : OSL_FAIL(
960 : "HierarchyEntry::first - caught NoSuchElementException!" );
961 : }
962 0 : catch ( uno::Exception const & )
963 : {
964 : OSL_FAIL( "HierarchyEntry::first - caught Exception!" );
965 : }
966 : }
967 :
968 0 : if ( it.m_pImpl->names.getLength() == 0 )
969 0 : return sal_False;
970 :
971 0 : it.m_pImpl->pos = 0;
972 0 : return sal_True;
973 : }
974 :
975 : //=========================================================================
976 0 : sal_Bool HierarchyEntry::next( iterator& it )
977 : {
978 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
979 :
980 0 : if ( it.m_pImpl->pos == -1 )
981 0 : return first( it );
982 :
983 0 : ++(it.m_pImpl->pos);
984 :
985 0 : return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() );
986 : }
987 :
988 : //=========================================================================
989 0 : rtl::OUString HierarchyEntry::createPathFromHierarchyURL(
990 : const HierarchyUri& rURI )
991 : {
992 : // Transform path....
993 : // folder/subfolder/subsubfolder
994 : // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
995 :
996 0 : const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
997 0 : sal_Int32 nLen = aPath.getLength();
998 :
999 0 : if ( nLen )
1000 : {
1001 0 : rtl::OUStringBuffer aNewPath;
1002 0 : aNewPath.appendAscii( "['" );
1003 :
1004 0 : sal_Int32 nStart = 0;
1005 0 : sal_Int32 nEnd = aPath.indexOf( '/' );
1006 :
1007 0 : do
1008 : {
1009 0 : if ( nEnd == -1 )
1010 0 : nEnd = nLen;
1011 :
1012 0 : rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart );
1013 0 : makeXMLName( aToken, aNewPath );
1014 :
1015 0 : if ( nEnd != nLen )
1016 : {
1017 0 : aNewPath.appendAscii( "']/Children/['" );
1018 0 : nStart = nEnd + 1;
1019 0 : nEnd = aPath.indexOf( '/', nStart );
1020 : }
1021 : else
1022 0 : aNewPath.appendAscii( "']" );
1023 : }
1024 : while ( nEnd != nLen );
1025 :
1026 0 : return aNewPath.makeStringAndClear();
1027 : }
1028 :
1029 0 : return aPath;
1030 : }
1031 :
1032 : //=========================================================================
1033 : uno::Reference< container::XHierarchicalNameAccess >
1034 0 : HierarchyEntry::getRootReadAccess()
1035 : {
1036 0 : if ( !m_xRootReadAccess.is() )
1037 : {
1038 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1039 0 : if ( !m_xRootReadAccess.is() )
1040 : {
1041 0 : if ( m_bTriedToGetRootReadAccess ) // #82494#
1042 : {
1043 : OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1044 : "Unable to read any config data! -> #82494#" );
1045 0 : return uno::Reference< container::XHierarchicalNameAccess >();
1046 : }
1047 :
1048 : try
1049 : {
1050 0 : if ( !m_xConfigProvider.is() )
1051 : m_xConfigProvider
1052 : = uno::Reference< lang::XMultiServiceFactory >(
1053 0 : m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
1054 0 : uno::UNO_QUERY );
1055 :
1056 0 : if ( m_xConfigProvider.is() )
1057 : {
1058 : // Create Root object.
1059 :
1060 0 : uno::Sequence< uno::Any > aArguments( 1 );
1061 0 : beans::PropertyValue aProperty;
1062 : aProperty.Name = rtl::OUString(
1063 0 : CFGPROPERTY_NODEPATH );
1064 0 : aProperty.Value <<= rtl::OUString(); // root path
1065 0 : aArguments[ 0 ] <<= aProperty;
1066 :
1067 0 : m_bTriedToGetRootReadAccess = sal_True;
1068 :
1069 : m_xRootReadAccess
1070 : = uno::Reference< container::XHierarchicalNameAccess >(
1071 0 : m_xConfigProvider->createInstanceWithArguments(
1072 : rtl::OUString( READ_SERVICE_NAME ),
1073 0 : aArguments ),
1074 0 : uno::UNO_QUERY );
1075 : }
1076 : }
1077 0 : catch ( uno::RuntimeException const & )
1078 : {
1079 0 : throw;
1080 : }
1081 0 : catch ( uno::Exception const & )
1082 : {
1083 : // createInstance, createInstanceWithArguments
1084 :
1085 : OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1086 : "caught Exception!" );
1087 : }
1088 0 : }
1089 : }
1090 0 : return m_xRootReadAccess;
1091 : }
1092 :
1093 : //=========================================================================
1094 : //=========================================================================
1095 : //
1096 : // HierarchyEntry::iterator Implementation.
1097 : //
1098 : //=========================================================================
1099 : //=========================================================================
1100 :
1101 0 : HierarchyEntry::iterator::iterator()
1102 : {
1103 0 : m_pImpl = new iterator_Impl;
1104 0 : }
1105 :
1106 : //=========================================================================
1107 0 : HierarchyEntry::iterator::~iterator()
1108 : {
1109 0 : delete m_pImpl;
1110 0 : }
1111 :
1112 : //=========================================================================
1113 0 : const HierarchyEntryData& HierarchyEntry::iterator::operator*() const
1114 : {
1115 0 : if ( ( m_pImpl->pos != -1 )
1116 0 : && ( m_pImpl->dir.is() )
1117 0 : && ( m_pImpl->pos < m_pImpl->names.getLength() ) )
1118 : {
1119 : try
1120 : {
1121 0 : rtl::OUStringBuffer aKey;
1122 0 : aKey.appendAscii( "['" );
1123 0 : makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey );
1124 0 : aKey.appendAscii( "']" );
1125 :
1126 0 : rtl::OUString aTitle = aKey.makeStringAndClear();
1127 0 : rtl::OUString aTargetURL = aTitle;
1128 0 : rtl::OUString aType = aTitle;
1129 :
1130 0 : aTitle += rtl::OUString("/Title");
1131 0 : aTargetURL += rtl::OUString("/TargetURL");
1132 0 : aType += rtl::OUString("/Type");
1133 :
1134 0 : rtl::OUString aValue;
1135 0 : m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue;
1136 0 : m_pImpl->entry.setTitle( aValue );
1137 :
1138 0 : m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1139 :
1140 : // TargetURL property may contain a reference to the Office
1141 : // installation directory. To ensure a reloctable office
1142 : // installation, the path to the office installtion directory must
1143 : // never be stored directly. A placeholder is used instead. Replace
1144 : // it by actual installation directory.
1145 0 : if ( m_pImpl->officeDirs.is() && !aValue.isEmpty() )
1146 0 : aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue );
1147 0 : m_pImpl->entry.setTargetURL( aValue );
1148 :
1149 0 : if ( m_pImpl->dir->hasByHierarchicalName( aType ) )
1150 : {
1151 : // Might not be present since it was introduced long
1152 : // after Title and TargetURL (#82433#)... So not getting
1153 : // it is not an error.
1154 :
1155 : // Get Type value.
1156 0 : sal_Int32 nType = 0;
1157 0 : if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1158 : {
1159 0 : if ( nType == 0 )
1160 : {
1161 0 : m_pImpl->entry.setType( HierarchyEntryData::LINK );
1162 : }
1163 0 : else if ( nType == 1 )
1164 : {
1165 0 : m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1166 : }
1167 : else
1168 : {
1169 : OSL_FAIL( "HierarchyEntry::getData - "
1170 : "Unknown Type value!" );
1171 : }
1172 : }
1173 : }
1174 :
1175 : m_pImpl->entry.setName(
1176 0 : m_pImpl->names.getConstArray()[ m_pImpl->pos ] );
1177 : }
1178 0 : catch ( container::NoSuchElementException const & )
1179 : {
1180 0 : m_pImpl->entry = HierarchyEntryData();
1181 : }
1182 : }
1183 :
1184 0 : return m_pImpl->entry;
1185 : }
1186 :
1187 : } // namespace hierarchy_ucp
1188 :
1189 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|