1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 #include "tools/SdGlobalResourceContainer.hxx"
32 
33 #include <algorithm>
34 #include <vector>
35 
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 
39 
40 namespace sd {
41 
42 
43 //===== SdGlobalResourceContainer::Implementation =============================
44 
45 class SdGlobalResourceContainer::Implementation
46 {
47 private:
48     friend class SdGlobalResourceContainer;
49     static SdGlobalResourceContainer* mpInstance;
50 
51 	::osl::Mutex maMutex;
52 
53     /** All instances of SdGlobalResource in this vector are owned by the
54         container and will be destroyed when the container is destroyed.
55     */
56     typedef ::std::vector<SdGlobalResource*> ResourceList;
57     ResourceList maResources;
58 
59     typedef ::std::vector<boost::shared_ptr<SdGlobalResource> > SharedResourceList;
60     SharedResourceList maSharedResources;
61 
62     typedef ::std::vector<Reference<XInterface> > XInterfaceResourceList;
63     XInterfaceResourceList maXInterfaceResources;
64 };
65 
66 
67 
68 
69 // static
70 SdGlobalResourceContainer& SdGlobalResourceContainer::Instance (void)
71 {
72     DBG_ASSERT(Implementation::mpInstance!=NULL,
73         "SdGlobalResourceContainer::Instance(): instance has been deleted");
74     // Maybe we should throw an exception when the instance has been deleted.
75     return *Implementation::mpInstance;
76 }
77 
78 SdGlobalResourceContainer*
79     SdGlobalResourceContainer::Implementation::mpInstance = NULL;
80 
81 
82 
83 
84 //===== SdGlobalResourceContainer =============================================
85 
86 void SdGlobalResourceContainer::AddResource (
87     ::std::auto_ptr<SdGlobalResource> pResource)
88 {
89     ::osl::MutexGuard aGuard (mpImpl->maMutex);
90 
91     Implementation::ResourceList::iterator iResource;
92     iResource = ::std::find (
93         mpImpl->maResources.begin(),
94         mpImpl->maResources.end(),
95         pResource.get());
96     if (iResource == mpImpl->maResources.end())
97         mpImpl->maResources.push_back(pResource.get());
98     else
99     {
100         // Because the given resource is an auto_ptr it is highly unlikely
101         // that we come here.  But who knows?
102         DBG_ASSERT (false,
103             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
104     }
105     // We can not put the auto_ptr into the vector so we release the
106     // auto_ptr and document that we take ownership explicitly.
107     pResource.release();
108 }
109 
110 
111 
112 
113 void SdGlobalResourceContainer::AddResource (
114     ::boost::shared_ptr<SdGlobalResource> pResource)
115 {
116     ::osl::MutexGuard aGuard (mpImpl->maMutex);
117 
118     Implementation::SharedResourceList::iterator iResource;
119     iResource = ::std::find (
120         mpImpl->maSharedResources.begin(),
121         mpImpl->maSharedResources.end(),
122         pResource);
123     if (iResource == mpImpl->maSharedResources.end())
124         mpImpl->maSharedResources.push_back(pResource);
125     else
126     {
127         DBG_ASSERT (false,
128             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
129     }
130 }
131 
132 
133 
134 
135 void SdGlobalResourceContainer::AddResource (const Reference<XInterface>& rxResource)
136 {
137     ::osl::MutexGuard aGuard (mpImpl->maMutex);
138 
139     Implementation::XInterfaceResourceList::iterator iResource;
140     iResource = ::std::find (
141         mpImpl->maXInterfaceResources.begin(),
142         mpImpl->maXInterfaceResources.end(),
143         rxResource);
144     if (iResource == mpImpl->maXInterfaceResources.end())
145         mpImpl->maXInterfaceResources.push_back(rxResource);
146     else
147     {
148         DBG_ASSERT (false,
149             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
150     }
151 }
152 
153 
154 
155 SdGlobalResourceContainer::SdGlobalResourceContainer (void)
156     : mpImpl (new SdGlobalResourceContainer::Implementation())
157 {
158     Implementation::mpInstance = this;
159 }
160 
161 
162 
163 
164 SdGlobalResourceContainer::~SdGlobalResourceContainer (void)
165 {
166     ::osl::MutexGuard aGuard (mpImpl->maMutex);
167 
168     // Release the resources in reversed order of their addition to the
169     // container.  This is because a resource A added before resource B
170     // may have been created due to a request of B.  Thus B depends on A and
171     // should be destroyed first.
172     Implementation::ResourceList::reverse_iterator iResource;
173     for (iResource = mpImpl->maResources.rbegin();
174          iResource != mpImpl->maResources.rend();
175          ++iResource)
176     {
177         delete *iResource;
178     }
179 
180     // The SharedResourceList has not to be released manually.  We just
181     // assert resources that are still held by someone other than us.
182     Implementation::SharedResourceList::reverse_iterator iSharedResource;
183     for (iSharedResource = mpImpl->maSharedResources.rbegin();
184          iSharedResource != mpImpl->maSharedResources.rend();
185          ++iSharedResource)
186     {
187         if ( ! iSharedResource->unique())
188         {
189             SdGlobalResource* pResource = iSharedResource->get();
190             OSL_TRACE(" %p %d", pResource, iSharedResource->use_count());
191             DBG_ASSERT(iSharedResource->unique(),
192                 "SdGlobalResource still held in ~SdGlobalResourceContainer");
193         }
194     }
195 
196     Implementation::XInterfaceResourceList::reverse_iterator iXInterfaceResource;
197     for (iXInterfaceResource = mpImpl->maXInterfaceResources.rbegin();
198          iXInterfaceResource != mpImpl->maXInterfaceResources.rend();
199          ++iXInterfaceResource)
200     {
201         Reference<lang::XComponent> xComponent (*iXInterfaceResource, UNO_QUERY);
202         *iXInterfaceResource = NULL;
203         if (xComponent.is())
204             xComponent->dispose();
205     }
206 
207     DBG_ASSERT(Implementation::mpInstance == this,
208         "~SdGlobalResourceContainer(): more than one instance of singleton");
209     Implementation::mpInstance = NULL;
210 }
211 
212 
213 
214 
215 } // end of namespace sd
216