class Catalog::Downloader : public HTTP::Request
{
public:
- Downloader(Catalog* aOwner, const std::string& aUrl) :
+ Downloader(CatalogRef aOwner, const std::string& aUrl) :
HTTP::Request(aUrl),
m_owner(aOwner)
{
return false;
}
- Catalog* m_owner;
+ CatalogRef m_owner;
std::string m_buffer;
};
static_catalogs.erase(it);
}
-Catalog* Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
+CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
{
- Catalog* c = new Catalog(aRoot);
+ CatalogRef c = new Catalog(aRoot);
+ c->m_url = aUrl;
Downloader* dl = new Downloader(c, aUrl);
aRoot->makeHTTPRequest(dl);
return c;
}
-Catalog* Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
+CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
{
SGPath xml = aPath;
xml.append("catalog.xml");
return NULL;
}
- Catalog* c = new Catalog(aRoot);
+ CatalogRef c = new Catalog(aRoot);
c->m_installRoot = aPath;
c->parseProps(props);
c->parseTimestamp();
Catalog::packagesMatching(const SGPropertyNode* aFilter) const
{
PackageList r;
- BOOST_FOREACH(Package* p, m_packages) {
+ BOOST_FOREACH(PackageRef p, m_packages) {
if (p->matches(aFilter)) {
r.push_back(p);
}
Catalog::packagesNeedingUpdate() const
{
PackageList r;
- BOOST_FOREACH(Package* p, m_packages) {
+ BOOST_FOREACH(PackageRef p, m_packages) {
if (!p->isInstalled()) {
continue;
}
for (int i = 0; i < nChildren; i++) {
const SGPropertyNode* pkgProps = aProps->getChild(i);
if (strcmp(pkgProps->getName(), "package") == 0) {
- Package* p = new Package(pkgProps, this);
+ PackageRef p = new Package(pkgProps, this);
m_packages.push_back(p);
} else {
SGPropertyNode* c = m_props->getChild(pkgProps->getName(), pkgProps->getIndex(), true);
copyProperties(pkgProps, c);
}
} // of children iteration
-
+
+ if (!m_url.empty()) {
+ if (m_url != m_props->getStringValue("url")) {
+ // this effectively allows packages to migrate to new locations,
+ // although if we're going to rely on that feature we should
+ // maybe formalise it!
+ SG_LOG(SG_GENERAL, SG_WARN, "package downloaded from:" << m_url
+ << " is now at: " << m_props->getStringValue("url"));
+ }
+ }
+
+ m_url = m_props->getStringValue("url");
+
if (m_installRoot.isNull()) {
m_installRoot = m_root->path();
m_installRoot.append(id());
}
}
-Package* Catalog::getPackageById(const std::string& aId) const
+PackageRef Catalog::getPackageById(const std::string& aId) const
{
- BOOST_FOREACH(Package* p, m_packages) {
+ BOOST_FOREACH(PackageRef p, m_packages) {
if (p->id() == aId) {
return p;
}
std::string Catalog::url() const
{
- return m_props->getStringValue("url");
+ return m_url;
}
std::string Catalog::description() const
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
#include <simgear/package/Delegate.hxx>
namespace simgear
class Catalog;
class Root;
-typedef std::vector<Package*> PackageList;
-typedef std::vector<Catalog*> CatalogList;
+typedef SGSharedPtr<Package> PackageRef;
+typedef SGSharedPtr<Catalog> CatalogRef;
+typedef SGSharedPtr<Install> InstallRef;
+
+typedef std::vector<PackageRef> PackageList;
+typedef std::vector<CatalogRef> CatalogList;
-class Catalog
+ class Catalog : public SGReferenced
{
public:
virtual ~Catalog();
- static Catalog* createFromUrl(Root* aRoot, const std::string& aUrl);
+ static CatalogRef createFromUrl(Root* aRoot, const std::string& aUrl);
- static Catalog* createFromPath(Root* aRoot, const SGPath& aPath);
+ static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
static CatalogList allCatalogs();
std::string description() const;
- Package* getPackageById(const std::string& aId) const;
+ PackageRef getPackageById(const std::string& aId) const;
/**
* test if the catalog data was retrieved longer ago than the
Root* m_root;
SGPropertyNode_ptr m_props;
SGPath m_installRoot;
-
+ std::string m_url;
+
PackageList m_packages;
time_t m_retrievedTime;
};
class Install::PackageArchiveDownloader : public HTTP::Request
{
public:
- PackageArchiveDownloader(Install* aOwner) :
+ PackageArchiveDownloader(InstallRef aOwner) :
HTTP::Request("" /* dummy URL */),
m_owner(aOwner)
{
m_urls.erase(m_urls.begin()); // pop first URL
}
- Install* m_owner;
+ InstallRef m_owner;
string_list m_urls;
SG_MD5_CTX m_md5;
std::string m_buffer;
////////////////////////////////////////////////////////////////////
-Install::Install(Package* aPkg, const SGPath& aPath) :
+Install::Install(PackageRef aPkg, const SGPath& aPath) :
m_package(aPkg),
m_path(aPath),
m_download(NULL)
parseRevision();
}
-Install* Install::createFromPath(const SGPath& aPath, Catalog* aCat)
+InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
{
std::string id = aPath.file();
- Package* pkg = aCat->getPackageById(id);
+ PackageRef pkg = aCat->getPackageById(id);
if (!pkg)
throw sg_exception("no package with id:" + id);
#include <simgear/misc/sg_path.hxx>
#include <simgear/package/Delegate.hxx>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
namespace simgear
{
// forward decls
class Package;
class Catalog;
-
+class Install;
+
+typedef SGSharedPtr<Package> PackageRef;
+typedef SGSharedPtr<Catalog> CatalogRef;
+typedef SGSharedPtr<Install> InstallRef;
+
/**
*
*/
-class Install
+class Install : public SGReferenced
{
public:
/**
* create from a directory on disk, or fail.
*/
- static Install* createFromPath(const SGPath& aPath, Catalog* aCat);
+ static InstallRef createFromPath(const SGPath& aPath, CatalogRef aCat);
unsigned int revsion() const
{ return m_revision; }
- Package* package() const
+ PackageRef package() const
{ return m_package; }
SGPath path() const
class PackageArchiveDownloader;
friend class PackageArchiveDownloader;
- Install(Package* aPkg, const SGPath& aPath);
+ Install(PackageRef aPkg, const SGPath& aPath);
void parseRevision();
void writeRevisionFile();
void installResult(Delegate::FailureCode aReason);
void installProgress(unsigned int aBytes, unsigned int aTotal);
- Package* m_package;
+ PackageRef m_package;
unsigned int m_revision; ///< revision on disk
SGPath m_path; ///< installation point on disk
namespace pkg {
-Package::Package(const SGPropertyNode* aProps, Catalog* aCatalog) :
+Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) :
m_catalog(aCatalog)
{
initWithProps(aProps);
return p.exists();
}
-Install* Package::install()
+InstallRef Package::install()
{
SGPath p(m_catalog->installRoot());
p.append("Aircraft");
return Install::createFromPath(p, m_catalog);
}
- Install* ins = new Install(this, p);
+ InstallRef ins(new Install(this, p));
m_catalog->root()->scheduleToUpdate(ins);
return ins;
}
// prefer local hangar package if possible, in case someone does something
// silly with naming. Of course flightgear's aircraft search doesn't know
// about hanagrs, so names still need to be unique.
- Package* depPkg = m_catalog->getPackageById(depName);
+ PackageRef depPkg = m_catalog->getPackageById(depName);
if (!depPkg) {
Root* rt = m_catalog->root();
depPkg = rt->getPackageById(depName);
#include <simgear/props/props.hxx>
#include <simgear/misc/strutils.hxx>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
typedef std::set<std::string> string_set;
namespace simgear
class Install;
class Catalog;
class Package;
+
+typedef SGSharedPtr<Package> PackageRef;
+typedef SGSharedPtr<Catalog> CatalogRef;
+typedef SGSharedPtr<Install> InstallRef;
-typedef std::vector<Package*> PackageList;
+typedef std::vector<PackageRef> PackageList;
-class Package
+ class Package : public SGReferenced
{
public:
/**
* get or create an install for the package
*/
- Install* install();
+ InstallRef install();
bool isInstalled() const;
unsigned int revision() const;
- Catalog* catalog() const
+ CatalogRef catalog() const
{ return m_catalog; }
bool matches(const SGPropertyNode* aFilter) const;
private:
friend class Catalog;
- Package(const SGPropertyNode* aProps, Catalog* aCatalog);
+ Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
void initWithProps(const SGPropertyNode* aProps);
SGPropertyNode_ptr m_props;
string_set m_tags;
- Catalog* m_catalog;
+ CatalogRef m_catalog;
};
namespace pkg {
-typedef std::map<std::string, Catalog*> CatalogDict;
+typedef std::map<std::string, CatalogRef> CatalogDict;
class Root::RootPrivate
{
Delegate* delegate;
std::string version;
- std::set<Catalog*> refreshing;
- std::deque<Install*> updateDeque;
+ std::set<CatalogRef> refreshing;
+ std::deque<InstallRef> updateDeque;
std::deque<HTTP::Request_ptr> httpPendingRequests;
};
}
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
- Catalog* cat = Catalog::createFromPath(this, c);
+ CatalogRef cat = Catalog::createFromPath(this, c);
if (cat) {
d->catalogs[cat->id()] = cat;
}
return d->version;
}
-Catalog* Root::getCatalogById(const std::string& aId) const
+CatalogRef Root::getCatalogById(const std::string& aId) const
{
CatalogDict::const_iterator it = d->catalogs.find(aId);
if (it == d->catalogs.end()) {
return it->second;
}
-Package* Root::getPackageById(const std::string& aName) const
+PackageRef Root::getPackageById(const std::string& aName) const
{
size_t lastDot = aName.rfind('.');
- Package* pkg = NULL;
+ PackageRef pkg = NULL;
if (lastDot == std::string::npos) {
// naked package ID
CatalogDict::const_iterator it = d->catalogs.begin();
std::string catalogId = aName.substr(0, lastDot);
std::string id = aName.substr(lastDot + 1);
- Catalog* catalog = getCatalogById(catalogId);
+ CatalogRef catalog = getCatalogById(catalogId);
if (!catalog) {
return NULL;
}
return d->locale;
}
-void Root::scheduleToUpdate(Install* aInstall)
+void Root::scheduleToUpdate(InstallRef aInstall)
{
if (!aInstall) {
throw sg_exception("missing argument to scheduleToUpdate");
}
}
-void Root::startInstall(Install* aInstall)
+void Root::startInstall(InstallRef aInstall)
{
if (d->delegate) {
- d->delegate->startInstall(aInstall);
+ d->delegate->startInstall(aInstall.ptr());
}
}
-void Root::installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal)
+void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
{
if (d->delegate) {
- d->delegate->installProgress(aInstall, aBytes, aTotal);
+ d->delegate->installProgress(aInstall.ptr(), aBytes, aTotal);
}
}
-void Root::startNext(Install* aCurrent)
+void Root::startNext(InstallRef aCurrent)
{
if (d->updateDeque.front() != aCurrent) {
SG_LOG(SG_GENERAL, SG_ALERT, "current install of package not head of the deque");
}
}
-void Root::finishInstall(Install* aInstall)
+void Root::finishInstall(InstallRef aInstall)
{
if (d->delegate) {
- d->delegate->finishInstall(aInstall);
+ d->delegate->finishInstall(aInstall.ptr());
}
startNext(aInstall);
}
-void Root::failedInstall(Install* aInstall, Delegate::FailureCode aReason)
+void Root::failedInstall(InstallRef aInstall, Delegate::FailureCode aReason)
{
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
<< aInstall->package()->id() << ":" << aReason);
if (d->delegate) {
- d->delegate->failedInstall(aInstall, aReason);
+ d->delegate->failedInstall(aInstall.ptr(), aReason);
}
startNext(aInstall);
}
-void Root::catalogRefreshBegin(Catalog* aCat)
+void Root::catalogRefreshBegin(CatalogRef aCat)
{
d->refreshing.insert(aCat);
}
-void Root::catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason)
+void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason)
{
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
if (aReason != Delegate::FAIL_SUCCESS) {
bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
if (isPermanentFailure) {
SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
- d->catalogs.erase(catIt);
+ if (catIt != d->catalogs.end()) {
+ d->catalogs.erase(catIt);
+ }
}
} else if (catIt == d->catalogs.end()) {
// first fresh, add to our storage now
#include <simgear/misc/sg_path.hxx>
#include <simgear/package/Delegate.hxx>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
class SGPropertyNode;
namespace simgear
class Package;
class Catalog;
class Install;
+
+typedef SGSharedPtr<Package> PackageRef;
+typedef SGSharedPtr<Catalog> CatalogRef;
+typedef SGSharedPtr<Install> InstallRef;
+
+typedef std::vector<PackageRef> PackageList;
+typedef std::vector<CatalogRef> CatalogList;
-typedef std::vector<Package*> PackageList;
-typedef std::vector<Catalog*> CatalogList;
-
-class Root
+class Root : public SGReferenced
{
public:
Root(const SGPath& aPath, const std::string& aVersion);
*/
PackageList packagesNeedingUpdate() const;
- Package* getPackageById(const std::string& aId) const;
+ PackageRef getPackageById(const std::string& aId) const;
- Catalog* getCatalogById(const std::string& aId) const;
+ CatalogRef getCatalogById(const std::string& aId) const;
- void scheduleToUpdate(Install* aInstall);
+ void scheduleToUpdate(InstallRef aInstall);
private:
friend class Install;
friend class Catalog;
- void catalogRefreshBegin(Catalog* aCat);
- void catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason);
+ void catalogRefreshBegin(CatalogRef aCat);
+ void catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason);
- void startNext(Install* aCurrent);
+ void startNext(InstallRef aCurrent);
- void startInstall(Install* aInstall);
- void installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal);
- void finishInstall(Install* aInstall);
- void failedInstall(Install* aInstall, Delegate::FailureCode aReason);
+ void startInstall(InstallRef aInstall);
+ void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
+ void finishInstall(InstallRef aInstall);
+ void failedInstall(InstallRef aInstall, Delegate::FailureCode aReason);
class RootPrivate;
std::auto_ptr<RootPrivate> d;
};
-
+
+typedef SGSharedPtr<Root> RootRef;
+
} // of namespace pkg
} // of namespace simgear
} else if (!strcmp(argv[1], "refresh")) {
root->refresh(true);
} else if (!strcmp(argv[1], "install")) {
- pkg::Package* pkg = root->getPackageById(argv[2]);
+ pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
- pkg::Catalog* catalog = pkg->catalog();
+ pkg::CatalogRef catalog = pkg->catalog();
cout << "Will install:" << pkg->id() << " from " << catalog->id() <<
"(" << catalog->description() << ")" << endl;
pkg->install();
} else if (!strcmp(argv[1], "uninstall") || !strcmp(argv[1], "remove")) {
- pkg::Package* pkg = root->getPackageById(argv[2]);
+ pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;
cout << "\t" << p->id() << " " << p->getLocalisedProp("name") << endl;
}
} else if (!strcmp(argv[1], "info")) {
- pkg::Package* pkg = root->getPackageById(argv[2]);
+ pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;