]> git.mxchange.org Git - simgear.git/blob - simgear/package/Root.cxx
LGPL license on package files.
[simgear.git] / simgear / package / Root.cxx
1 // Copyright (C) 2013  James Turner - zakalawe@mac.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #include <simgear/package/Root.hxx>
19
20 #include <boost/foreach.hpp>
21 #include <cstring>
22
23 #include <simgear/debug/logstream.hxx>
24 #include <simgear/props/props_io.hxx>
25 #include <simgear/io/HTTPRequest.hxx>
26 #include <simgear/io/HTTPClient.hxx>
27 #include <simgear/misc/sg_dir.hxx>
28 #include <simgear/structure/exception.hxx>
29 #include <simgear/package/Package.hxx>
30 #include <simgear/package/Install.hxx>
31 #include <simgear/package/Catalog.hxx>
32
33 namespace simgear {
34     
35 namespace pkg {
36
37 void Root::setMaxAgeSeconds(int seconds)
38 {
39     m_maxAgeSeconds = seconds;
40 }
41
42 void Root::setHTTPClient(HTTP::Client* aHTTP)
43 {
44     m_http = aHTTP;
45 }
46
47 HTTP::Client* Root::getHTTPClient() const
48 {
49     return m_http;
50 }
51
52 Root::Root(const SGPath& aPath) :
53     m_path(aPath),
54     m_http(NULL),
55     m_maxAgeSeconds(60 * 60 * 24),
56     m_delegate(NULL)
57 {
58     if (getenv("LOCALE")) {
59         m_locale = getenv("LOCALE");
60     }
61     
62     Dir d(aPath);
63     if (!d.exists()) {
64         d.create(0755);
65         return;
66     }
67     
68     BOOST_FOREACH(SGPath c, d.children(Dir::TYPE_DIR)) {
69         Catalog* cat = Catalog::createFromPath(this, c);
70         if (cat) {
71            m_catalogs[cat->id()] = cat;     
72         }
73     } // of child directories iteration
74 }
75
76 Root::~Root()
77 {
78     
79 }
80
81 Catalog* Root::getCatalogById(const std::string& aId) const
82 {
83     CatalogDict::const_iterator it = m_catalogs.find(aId);
84     if (it == m_catalogs.end()) {
85         return NULL;
86     }
87     
88     return it->second;
89 }
90
91 Package* Root::getPackageById(const std::string& aName) const
92 {
93     size_t lastDot = aName.rfind('.');
94     
95     Package* pkg = NULL;
96     if (lastDot == std::string::npos) {
97         // naked package ID
98         CatalogDict::const_iterator it = m_catalogs.begin();
99         for (; it != m_catalogs.end(); ++it) {
100             pkg = it->second->getPackageById(aName);
101             if (pkg) {
102                 return pkg;
103             }
104         }
105         
106         return NULL;
107     }
108     
109     std::string catalogId = aName.substr(0, lastDot);
110     std::string id = aName.substr(lastDot + 1);    
111     Catalog* catalog = getCatalogById(catalogId);
112     if (!catalog) {
113         return NULL;
114     }
115             
116     return catalog->getPackageById(id);
117 }
118
119 CatalogList Root::catalogs() const
120 {
121     CatalogList r;
122     CatalogDict::const_iterator it = m_catalogs.begin();
123     for (; it != m_catalogs.end(); ++it) {
124         r.push_back(it->second);
125     }
126     
127     return r;
128 }
129
130 PackageList
131 Root::packagesMatching(const SGPropertyNode* aFilter) const
132 {
133     PackageList r;
134     
135     CatalogDict::const_iterator it = m_catalogs.begin();
136     for (; it != m_catalogs.end(); ++it) {
137         PackageList r2(it->second->packagesMatching(aFilter));
138         r.insert(r.end(), r2.begin(), r2.end());
139     }
140     
141     return r;
142 }
143
144 PackageList
145 Root::packagesNeedingUpdate() const
146 {
147     PackageList r;
148     
149     CatalogDict::const_iterator it = m_catalogs.begin();
150     for (; it != m_catalogs.end(); ++it) {
151         PackageList r2(it->second->packagesNeedingUpdate());
152         r.insert(r.end(), r2.begin(), r2.end());
153     }
154     
155     return r;
156 }
157
158 void Root::refresh(bool aForce)
159 {
160     CatalogDict::iterator it = m_catalogs.begin();
161     for (; it != m_catalogs.end(); ++it) {
162         if (aForce || (it->second->ageInSeconds() > m_maxAgeSeconds)) {
163             it->second->refresh();
164         }
165     }
166 }
167
168 void Root::setLocale(const std::string& aLocale)
169 {
170     m_locale = aLocale;
171 }
172
173 std::string Root::getLocale() const
174 {
175     return m_locale;
176 }
177
178 void Root::scheduleToUpdate(Install* aInstall)
179 {
180     if (!aInstall) {
181         sg_exception("missing argument to scheduleToUpdate");
182     }
183     
184     PackageList deps = aInstall->package()->dependencies();
185     BOOST_FOREACH(Package* dep, deps) {
186         // will internally schedule for update if required
187         // hence be careful, this method is re-entered in here!
188         dep->install();
189     }
190
191     bool wasEmpty = m_updateDeque.empty();    
192     m_updateDeque.push_back(aInstall);
193     if (wasEmpty) {
194         aInstall->startUpdate();
195     }
196 }
197
198 void Root::startInstall(Install* aInstall)
199 {
200     if (m_delegate) {
201         m_delegate->startInstall(aInstall);
202     }
203 }
204
205 void Root::installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal)
206 {
207     if (m_delegate) {
208         m_delegate->installProgress(aInstall, aBytes, aTotal);
209     }
210 }
211
212 void Root::startNext(Install* aCurrent)
213 {
214     if (m_updateDeque.front() != aCurrent) {
215         SG_LOG(SG_GENERAL, SG_ALERT, "current install of package not head of the deque");
216     } else {
217         m_updateDeque.pop_front();
218     }
219     
220     if (!m_updateDeque.empty()) {
221         m_updateDeque.front()->startUpdate();
222     }
223 }
224
225 void Root::finishInstall(Install* aInstall)
226 {
227     if (m_delegate) {
228         m_delegate->finishInstall(aInstall);
229     }
230     
231     startNext(aInstall);
232 }
233
234 void Root::failedInstall(Install* aInstall, Delegate::FailureCode aReason)
235 {
236     SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:" 
237         << aInstall->package()->id() << ":" << aReason);
238     if (m_delegate) {
239         m_delegate->failedInstall(aInstall, aReason);
240     }
241     
242     startNext(aInstall);
243 }
244
245 void Root::catalogRefreshBegin(Catalog* aCat)
246 {
247     m_refreshing.insert(aCat);
248 }
249
250 void Root::catalogRefreshComplete(Catalog* aCat, bool aSuccess)
251 {
252     m_refreshing.erase(aCat);
253     if (m_refreshing.empty()) {
254         if (m_delegate) {
255             m_delegate->refreshComplete();
256         }
257     }
258 }
259
260 } // of namespace pkg
261
262 } // of namespace simgear