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 #ifndef SG_PACKAGE_INSTALL_HXX
19 #define SG_PACKAGE_INSTALL_HXX
20 
21 #include <vector>
22 
23 #include <simgear/misc/sg_path.hxx>
24 #include <simgear/misc/sg_dir.hxx>
25 #include <simgear/package/Delegate.hxx>
26 
27 #include <simgear/structure/function_list.hxx>
28 #include <simgear/structure/SGReferenced.hxx>
29 #include <simgear/structure/SGSharedPtr.hxx>
30 #include <simgear/io/HTTPRequest.hxx>
31 
32 namespace simgear
33 {
34 
35 namespace pkg
36 {
37 
38 // forward decls
39 class Package;
40 class Catalog;
41 class Install;
42 
43 typedef SGSharedPtr<Package> PackageRef;
44 typedef SGSharedPtr<Catalog> CatalogRef;
45 typedef SGSharedPtr<Install> InstallRef;
46 
47 /**
48  *
49  */
50 class Install : public SGReferenced
51 {
52 public:
53     virtual ~Install();
54 
55     typedef std::function<void(Install*)> Callback;
56     typedef std::function<void(Install*, unsigned int, unsigned int)> ProgressCallback;
57 
58     /**
59      * create from a directory on disk, or fail.
60      */
61     static InstallRef createFromPath(const SGPath& aPath, CatalogRef aCat);
62 
revsion() const63     unsigned int revsion() const
64         { return m_revision; }
65 
package() const66     PackageRef package() const
67         { return m_package; }
68 
path() const69     SGPath path() const
70         { return m_path; }
71 
72     bool hasUpdate() const;
73 
74     void startUpdate();
75 
76     bool uninstall();
77 
78     bool isDownloading() const;
79 
80     bool isQueued() const;
81 
82     int downloadedPercent() const;
83 
84     size_t downloadedBytes() const;
85 
86     Delegate::StatusCode status() const;
87 
88     /**
89      * full path to the primary -set.xml file for this install
90      */
91     SGPath primarySetPath() const;
92 
93     /**
94      * if a download is in progress, cancel it. If this is the first install
95      * of the package (as opposed to an update), the install will be cleaned
96      * up once the last reference is gone.
97      */
98     void cancelDownload();
99 
100     /**
101      * Set the handler to be called when the installation successfully
102      * completes.
103      *
104      * @note If the installation is already complete, the handler is called
105      *       immediately.
106      */
107     Install* done(const Callback& cb);
108 
109     template<class C>
done(C * instance,void (C::* mem_func)(Install *))110     Install* done(C* instance, void (C::*mem_func)(Install*))
111     {
112       return done(std::bind(mem_func, instance, std::placeholders::_1));
113     }
114 
115     /**
116      * Set the handler to be called when the installation fails or is aborted.
117      *
118      * @note If the installation has already failed, the handler is called
119      *       immediately.
120      */
121     Install* fail(const Callback& cb);
122 
123     template<class C>
fail(C * instance,void (C::* mem_func)(Install *))124     Install* fail(C* instance, void (C::*mem_func)(Install*))
125     {
126       return fail(std::bind(mem_func, instance, std::placeholders::_1));
127     }
128 
129     /**
130      * Set the handler to be called when the installation either successfully
131      * completes or fails.
132      *
133      * @note If the installation is already complete or has already failed, the
134      *       handler is called immediately.
135      */
136     Install* always(const Callback& cb);
137 
138     template<class C>
always(C * instance,void (C::* mem_func)(Install *))139     Install* always(C* instance, void (C::*mem_func)(Install*))
140     {
141       return always(std::bind(mem_func, instance, std::placeholders::_1));
142     }
143 
144     /**
145      * Set the handler to be called during downloading the installation file
146      * indicating the progress of the download.
147      *
148      */
149     Install* progress(const ProgressCallback& cb);
150 
151     template<class C>
progress(C * instance,void (C::* mem_func)(Install *,unsigned int,unsigned int))152     Install* progress(C* instance,
153                       void (C::*mem_func)(Install*, unsigned int, unsigned int))
154     {
155       return progress(std::bind(mem_func,
156                                 instance,
157                                 std::placeholders::_1,
158                                 std::placeholders::_2,
159                                 std::placeholders::_3));
160     }
161 
162 private:
163     friend class Package;
164 
165     class PackageArchiveDownloader;
166     friend class PackageArchiveDownloader;
167 
168     Install(PackageRef aPkg, const SGPath& aPath);
169 
170     void parseRevision();
171     void writeRevisionFile();
172 
173     void installResult(Delegate::StatusCode aReason);
174     void installProgress(unsigned int aBytes, unsigned int aTotal);
175     void startDownload();
176 
177     PackageRef m_package;
178     unsigned int m_revision; ///< revision on disk
179     SGPath m_path; ///< installation point on disk
180 
181     HTTP::Request_ptr m_download;
182 
183     Delegate::StatusCode m_status;
184 
185     function_list<Callback>         _cb_done,
186                                     _cb_fail,
187                                     _cb_always;
188     function_list<ProgressCallback> _cb_progress;
189 };
190 
191 
192 } // of namespace pkg
193 
194 } // of namespace simgear
195 
196 #endif // of SG_PACKAGE_CATALOG_HXX
197