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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include "cacheupdatelistener.hxx"
28 #include "constant.hxx"
29 
30 //_______________________________________________
31 // includes
32 #include <com/sun/star/util/XChangesNotifier.hpp>
33 #include <com/sun/star/util/XRefreshable.hpp>
34 #include <salhelper/singletonref.hxx>
35 #include <unotools/configpathes.hxx>
36 #include <rtl/ustring.hxx>
37 
38 //_______________________________________________
39 // namespace
40 
41 namespace filter{
42     namespace config{
43 
44 namespace css = ::com::sun::star;
45 
46 //_______________________________________________
47 // definitions
48 
49 /*-----------------------------------------------
50     05.03.2004 08:36
51 -----------------------------------------------*/
CacheUpdateListener(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const css::uno::Reference<css::uno::XInterface> & xConfigAccess,FilterCache::EItemType eConfigType)52 CacheUpdateListener::CacheUpdateListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR        ,
53                                          const css::uno::Reference< css::uno::XInterface >&            xConfigAccess,
54                                                FilterCache::EItemType                                  eConfigType  )
55     : BaseLock     (             )
56     , m_xSMGR      (xSMGR        )
57     , m_rCache     (             )
58     , m_xConfig    (xConfigAccess)
59     , m_eConfigType(eConfigType  )
60 {
61 }
62 
63 /*-----------------------------------------------
64     05.03.2004 08:37
65 -----------------------------------------------*/
~CacheUpdateListener()66 CacheUpdateListener::~CacheUpdateListener()
67 {
68 }
69 
70 /*-----------------------------------------------
71     07.03.2004 07:59
72 -----------------------------------------------*/
startListening()73 void CacheUpdateListener::startListening()
74 {
75     // SAFE ->
76     ::osl::ResettableMutexGuard aLock(m_aLock);
77     css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY);
78     aLock.clear();
79     // <- SAFE
80 
81     if (!xNotifier.is())
82         return;
83 
84     css::uno::Reference< css::util::XChangesListener > xThis(static_cast< css::util::XChangesListener* >(this), css::uno::UNO_QUERY_THROW);
85     xNotifier->addChangesListener(xThis);
86 
87 /*
88     css::uno::Reference< css::container::XContainer > xNotifier(xConfigAccess, css::uno::UNO_QUERY);
89     if (!xNotifier.is())
90         return;
91 
92     css::uno::Reference< css::container::XContainerListener > xThis(static_cast< css::container::XContainerListener* >(this), css::uno::UNO_QUERY);
93     xNotifier->addContainerListener(xThis);
94 */
95 }
96 
97 /*-----------------------------------------------
98     07.03.2004 07:59
99 -----------------------------------------------*/
stopListening()100 void CacheUpdateListener::stopListening()
101 {
102     // SAFE ->
103     ::osl::ResettableMutexGuard aLock(m_aLock);
104     css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY);
105     aLock.clear();
106     // <- SAFE
107 
108     if (!xNotifier.is())
109         return;
110 
111     css::uno::Reference< css::util::XChangesListener > xThis(static_cast< css::util::XChangesListener* >(this), css::uno::UNO_QUERY);
112     xNotifier->removeChangesListener(xThis);
113 
114 /*
115     css::uno::Reference< css::container::XContainer > xNotifier(xConfigAccess, css::uno::UNO_QUERY);
116     if (!xNotifier.is())
117         return;
118 
119     css::uno::Reference< css::container::XContainerListener > xThis(static_cast< css::container::XContainerListener* >(this), css::uno::UNO_QUERY);
120     xNotifier->removeContainerListener(xThis);
121 */
122 }
123 
124 /*-----------------------------------------------
125     07.03.2004 08:17
126 -----------------------------------------------*/
changesOccurred(const css::util::ChangesEvent & aEvent)127 void SAL_CALL  CacheUpdateListener::changesOccurred(const css::util::ChangesEvent& aEvent)
128     throw(css::uno::RuntimeException)
129 {
130     // SAFE ->
131     ::osl::ResettableMutexGuard aLock(m_aLock);
132 
133     // disposed ?
134     if ( ! m_xConfig.is())
135         return;
136 
137     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
138     FilterCache::EItemType                                 eType = m_eConfigType;
139 
140     aLock.clear();
141     // <- SAFE
142 
143     OUStringList lChangedItems;
144     sal_Int32    c = aEvent.Changes.getLength();
145     sal_Int32    i = 0;
146 
147     for (i=0; i<c; ++i)
148     {
149         const css::util::ElementChange& aChange = aEvent.Changes[i];
150 
151         ::rtl::OUString sOrgPath ;
152         ::rtl::OUString sTempPath;
153 
154         ::rtl::OUString sProperty;
155         ::rtl::OUString sNode    ;
156         ::rtl::OUString sLocale  ;
157 
158         /*  at least we must be able to retrieve 2 path elements
159             But sometimes the original path can contain 3 of them ... in case
160             a localized value was changed.
161             =>
162             1) Filters/Filter["filtername"]/Property
163             2) Filters/Filter["filtername"]/LocalizedProperty/Locale
164         */
165 
166         aChange.Accessor >>= sOrgPath;
167         if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sLocale))
168             continue;
169         sOrgPath = sTempPath;
170         if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sProperty))
171         {
172             sNode     = sLocale;
173             sProperty = ::rtl::OUString();
174             sLocale   = ::rtl::OUString();
175         }
176         else
177         {
178             sOrgPath = sTempPath;
179             if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sNode))
180             {
181                 sNode     = sProperty;
182                 sProperty = sLocale;
183                 sLocale   = ::rtl::OUString();
184             }
185         }
186 
187         if ( ! sNode.getLength() )
188             continue;
189 
190         OUStringList::const_iterator pIt = ::std::find(lChangedItems.begin(), lChangedItems.end(), sNode);
191         if (pIt == lChangedItems.end())
192             lChangedItems.push_back(sNode);
193     }
194 
195     sal_Bool                     bNotifyRefresh = sal_False;
196     OUStringList::const_iterator pIt;
197     for (  pIt  = lChangedItems.begin();
198            pIt != lChangedItems.end()  ;
199          ++pIt                         )
200     {
201         const ::rtl::OUString& sItem = *pIt;
202         try
203         {
204             m_rCache->refreshItem(eType, sItem);
205         }
206         catch(const css::container::NoSuchElementException&)
207             {
208                 // can be ignored! Because we must be aware that
209                 // sItem was removed from the condfiguration and we forced an update of the cache.
210                 // But we know, that the cache is up-to-date know and has thrown this exception afterwards .-)
211             }
212         // NO FLUSH! Otherwhise we start a never ending story here .-)
213         bNotifyRefresh = sal_True;
214     }
215 
216     // notify sfx cache about the changed filter cache .-)
217     if (bNotifyRefresh)
218     {
219         css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster(
220             xSMGR->createInstance(SERVICE_FILTERCONFIGREFRESH),
221             css::uno::UNO_QUERY);
222         if (xRefreshBroadcaster.is())
223             xRefreshBroadcaster->refresh();
224     }
225 }
226 
227 /*-----------------------------------------------
228     05.03.2004 08:44
229 -----------------------------------------------*/
disposing(const css::lang::EventObject & aEvent)230 void SAL_CALL CacheUpdateListener::disposing(const css::lang::EventObject& aEvent)
231     throw(css::uno::RuntimeException)
232 {
233     // SAFE ->
234     ::osl::ResettableMutexGuard aLock(m_aLock);
235     if (aEvent.Source == m_xConfig)
236         m_xConfig.clear();
237     aLock.clear();
238     // <- SAFE
239 }
240 
241     } // namespace config
242 } // namespace filter
243