[haiku-commits] haiku: hrev51514 - in src: apps/haikudepot/server apps/haikudepot/model tests/apps/haikudepot apps/haikudepot

  • From: apl@xxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 3 Nov 2017 20:14:15 +0100 (CET)

hrev51514 adds 1 changeset to branch 'master'
old head: af463b82f8fda261cfc339becdf5b42e85b37de1
new head: 3d528c4a60da48db99b687e5a90f83084ec034f9
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=3d528c4a60da+%5Eaf463b82f8fd

----------------------------------------------------------------------------

3d528c4a60da: HaikuDepot: Change communication mechanism with server for repos
  
  (last commit with same title only included new files - added those now)
  
  Previously the desktop application would make a number of JSON-RPC calls
  over HTTP to get the repositories.  Now it will make a single call to get
  the repositories and cache the result.  This uses standard HTTP cache
  signalling techniques and allows the server-side the ability to cache
  the generated data as well.  Note that the model classes and parse-
  related classes are generated and may not be code-style compliant.  They
  are generated from JSON schema files in the server-side project.
  Information about this as well as the python files used to generate the
  C++ classes and headers are included in the server-side project.

                                    [ Andrew Lindesay <apl@xxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev51514
Commit:      3d528c4a60da48db99b687e5a90f83084ec034f9
URL:         http://cgit.haiku-os.org/haiku/commit/?id=3d528c4a60da
Author:      Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:        Fri Nov  3 19:09:46 2017 UTC

----------------------------------------------------------------------------

11 files changed, 366 insertions(+), 251 deletions(-)
src/apps/haikudepot/Jamfile                      |   8 +-
src/apps/haikudepot/model/Model.cpp              |  75 +++---
src/apps/haikudepot/model/Model.h                |   5 +-
.../haikudepot/server/AbstractServerProcess.cpp  | 233 ++++++++++++++++++-
.../haikudepot/server/AbstractServerProcess.h    |  42 +++-
.../server/RepositoryDataUpdateProcess.cpp       |   2 +-
.../server/ServerIconExportUpdateProcess.cpp     | 196 ++--------------
.../server/ServerIconExportUpdateProcess.h       |  33 ++-
src/apps/haikudepot/ui/MainWindow.cpp            |   8 +-
.../apps/haikudepot/HaikuDepotTestAddon.cpp      |   3 +-
src/tests/apps/haikudepot/Jamfile                |  12 +-

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index 182dc0e..885d3f9 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -4,7 +4,7 @@ UsePrivateHeaders interface shared storage package support net ;
 
 # source directories
 local sourceDirs =
-       edits_generic model textview ui ui_generic server tar util
+       edits_generic model textview ui ui_generic server 
server/dumpexportrepository tar util
 ;
 
 local sourceDir ;
@@ -74,10 +74,16 @@ Application HaikuDepot :
        SharedBitmap.cpp
        UserLoginWindow.cpp
        
+       # network + server - model
+       DumpExportRepository.cpp
+       DumpExportRepositorySource.cpp
+       DumpExportRepositoryJsonListener.cpp
+
        # network + server
        AbstractServerProcess.cpp
        ServerSettings.cpp
        WebAppInterface.cpp
+       RepositoryDataUpdateProcess.cpp
        ServerIconExportUpdateProcess.cpp
        StandardMetaDataJsonEventListener.cpp
        StandardMetaData.cpp
diff --git a/src/apps/haikudepot/model/Model.cpp 
b/src/apps/haikudepot/model/Model.cpp
index 5845a7f..7d67e6f 100644
--- a/src/apps/haikudepot/model/Model.cpp
+++ b/src/apps/haikudepot/model/Model.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "Model.h"
+#include "RepositoryDataUpdateProcess.h"
 #include "StorageUtils.h"
 
 #include <ctime>
@@ -834,59 +835,47 @@ Model::SetAuthorization(const BString& username, const 
BString& password,
 
 // #pragma mark - private
 
+/*! When bulk repository data comes down from the server, it will
+    arrive as a json.gz payload.  This is stored locally as a cache
+    and this method will provide the on-disk storage location for
+    this file.
+*/
 
-void
-Model::PopulateWebAppRepositoryCode(DepotInfo& depotInfo)
+status_t
+Model::_DumpExportRepositoryDataPath(BPath& path) const
 {
-       if (depotInfo.BaseURL().Length() > 0) {
+       BPath repoDataPath;
 
-               BMessage repositoriesEnvelope;
-               BMessage result;
-               double total;
-               StringList repositorySourceBaseURLs;
+       if (find_directory(B_USER_CACHE_DIRECTORY, &repoDataPath) == B_OK
+               && repoDataPath.Append("HaikuDepot") == B_OK
+               && create_directory(repoDataPath.Path(), 0777) == B_OK
+               && repoDataPath.Append("repository-all_en.json.gz") == B_OK) {
+               path.SetTo(repoDataPath.Path());
+               return B_OK;
+       }
 
-               repositorySourceBaseURLs.Add(depotInfo.BaseURL());
+       path.Unset();
+       fprintf(stdout, "unable to find the user cache file for repositories'"
+               " data");
+       return B_ERROR;
+}
 
-               // TODO; better API call handling around errors.
 
-               if (fWebAppInterface.RetrieveRepositoriesForSourceBaseURLs(
-                       repositorySourceBaseURLs, repositoriesEnvelope) == B_OK
-                       && repositoriesEnvelope.FindMessage("result", &result) 
== B_OK
-                       && result.FindDouble("total", &total) == B_OK) {
+status_t
+Model::PopulateWebAppRepositoryCodes()
+{
+       status_t result = B_OK;
+       BPath dataPath;
 
-                       if ((int64)total > 0) {
-                               BMessage repositories;
-                               BMessage repository;
-                               BString repositoryCode;
+       result = _DumpExportRepositoryDataPath(dataPath);
 
-                               if (result.FindMessage("items", &repositories) 
== B_OK
-                                       && repositories.FindMessage("0", 
&repository) == B_OK
-                                       && repository.FindString("code", 
&repositoryCode) == B_OK) {
+       if (result != B_OK)
+               return result;
 
-                                       
depotInfo.SetWebAppRepositoryCode(repositoryCode);
+       RepositoryDataUpdateProcess process(dataPath, &fDepots);
+       result = process.Run();
 
-                                       printf("did assign web app repository 
code '%s' to local "
-                                               "depot '%s'\n",
-                                               
depotInfo.WebAppRepositoryCode().String(),
-                                               depotInfo.Name().String());
-                               } else {
-                                       printf("unable to find the 'code' in 
the api response for "
-                                               "local depot '%s'\n",
-                                               depotInfo.Name().String());
-                               }
-                       } else {
-                               printf("unable to find a repository code for 
'%s'\n",
-                                       depotInfo.BaseURL().String());
-                       }
-               } else {
-                       printf("unexpected result obtaining repository code for 
'%s'\n",
-                               depotInfo.BaseURL().String());
-               }
-       } else {
-               printf("missing base url for depot info %s --> will not obtain 
web app "
-                       "repository code\n",
-                       depotInfo.Name().String());
-       }
+       return result;
 }
 
 
diff --git a/src/apps/haikudepot/model/Model.h 
b/src/apps/haikudepot/model/Model.h
index a7d6459..ba73bfc 100644
--- a/src/apps/haikudepot/model/Model.h
+++ b/src/apps/haikudepot/model/Model.h
@@ -118,8 +118,7 @@ public:
                        bool                            ShowDevelopPackages() 
const
                                                                        { 
return fShowDevelopPackages; }
 
-                       void                            
PopulateWebAppRepositoryCode(
-                                                                       
DepotInfo& depotInfo);
+                       status_t                        
PopulateWebAppRepositoryCodes();
 
                        // Retrieve package information
        static  const uint32            POPULATE_CACHED_RATING  = 1 << 0;
@@ -152,6 +151,8 @@ public:
 
 
 private:
+                       status_t                        
_DumpExportRepositoryDataPath(
+                                                                       BPath& 
path) const;
                        void                            
_UpdateIsFeaturedFilter();
 
        static  int32                           _PopulateAllPackagesEntry(void* 
cookie);
diff --git a/src/apps/haikudepot/server/AbstractServerProcess.cpp 
b/src/apps/haikudepot/server/AbstractServerProcess.cpp
index 2fb761f..9618509 100644
--- a/src/apps/haikudepot/server/AbstractServerProcess.cpp
+++ b/src/apps/haikudepot/server/AbstractServerProcess.cpp
@@ -4,9 +4,240 @@
  */
 #include "AbstractServerProcess.h"
 
+#include <errno.h>
+#include <string.h>
+
+#include <AutoDeleter.h>
+#include <FileIO.h>
+#include <HttpRequest.h>
+#include <HttpTime.h>
+#include <UrlProtocolRoster.h>
+
+#include <support/ZlibCompressionAlgorithm.h>
+
+#include "ServerSettings.h"
+#include "StandardMetaDataJsonEventListener.h"
+#include "ToFileUrlProtocolListener.h"
+
+
+#define MAX_REDIRECTS 3
+#define MAX_FAILURES 2
+
+#define HTTP_STATUS_FOUND 302
+#define HTTP_STATUS_NOT_MODIFIED 304
+
+// 30 seconds
+#define TIMEOUT_MICROSECONDS 3e+7
+
+
+status_t
+AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue) const
+{
+       BPath metaDataPath;
+       BString jsonPath;
+
+       GetStandardMetaDataPath(metaDataPath);
+       GetStandardMetaDataJsonPath(jsonPath);
+
+       return IfModifiedSinceHeaderValue(headerValue, metaDataPath, jsonPath);
+}
+
+
+status_t
+AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue,
+       const BPath& metaDataPath, const BString& jsonPath) const
+{
+       headerValue.SetTo("");
+       struct stat s;
+
+       if (-1 == stat(metaDataPath.Path(), &s)) {
+               if (ENOENT != errno)
+                        return B_ERROR;
+
+               return B_FILE_NOT_FOUND;
+       }
+
+       if (s.st_size == 0)
+               return B_BAD_VALUE;
+
+       StandardMetaData metaData;
+       status_t result = PopulateMetaData(metaData, metaDataPath, jsonPath);
+
+       if (result == B_OK) {
+
+               // An example of this output would be; 'Fri, 24 Oct 2014 
19:32:27 +0000'
+
+               BDateTime modifiedDateTime = metaData
+                       .GetDataModifiedTimestampAsDateTime();
+               BPrivate::BHttpTime modifiedHttpTime(modifiedDateTime);
+               headerValue.SetTo(modifiedHttpTime
+                       .ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE));
+       } else {
+               fprintf(stderr, "unable to parse the meta-data date and time -"
+                       " cannot set the 'If-Modified-Since' header\n");
+       }
+
+       return result;
+}
+
+
+status_t
+AbstractServerProcess::PopulateMetaData(
+       StandardMetaData& metaData, const BPath& path,
+       const BString& jsonPath) const
+{
+       StandardMetaDataJsonEventListener listener(jsonPath, metaData);
+       status_t result = ParseJsonFromFileWithListener(&listener, path);
+
+       if (result != B_OK)
+               return result;
+
+       result = listener.ErrorStatus();
+
+       if (result != B_OK)
+               return result;
+
+       if (!metaData.IsPopulated()) {
+               fprintf(stderr, "the meta data was read from [%s], but no 
values "
+                       "were extracted\n", path.Path());
+               return B_BAD_DATA;
+       }
+
+       return B_OK;
+}
+
+
+bool
+AbstractServerProcess::LooksLikeGzip(const char *pathStr) const
+{
+       int l = strlen(pathStr);
+       return l > 4 && 0 == strncmp(&pathStr[l - 3], ".gz", 3);
+}
+
+
+/*!    Note that a B_OK return code from this method may not indicate that the
+       listening process went well.  One has to see if there was an error in
+       the listener.
+*/
 
 status_t
-AbstractServerProcess::Run()
+AbstractServerProcess::ParseJsonFromFileWithListener(
+       BJsonEventListener *listener,
+       const BPath& path) const
 {
+       const char* pathStr = path.Path();
+       FILE* file = fopen(pathStr, "rb");
+
+       if (file == NULL) {
+               fprintf(stderr, "unable to find the meta data file at [%s]\n",
+                       path.Path());
+               return B_FILE_NOT_FOUND;
+       }
+
+       BFileIO rawInput(file, true); // takes ownership
+
+               // if the file extension ends with '.gz' then the data will be
+               // compressed and the algorithm needs to decompress the data as
+               // it is parsed.
+
+       if (LooksLikeGzip(pathStr)) {
+               BDataIO* gzDecompressedInput = NULL;
+               BZlibDecompressionParameters* zlibDecompressionParameters
+                       = new BZlibDecompressionParameters();
+
+               status_t result = BZlibCompressionAlgorithm()
+                       .CreateDecompressingInputStream(&rawInput,
+                               zlibDecompressionParameters, 
gzDecompressedInput);
+
+               if (B_OK != result)
+                       return result;
+
+               ObjectDeleter<BDataIO> 
gzDecompressedInputDeleter(gzDecompressedInput);
+               BPrivate::BJson::Parse(gzDecompressedInput, listener);
+       } else {
+               BPrivate::BJson::Parse(&rawInput, listener);
+       }
+
        return B_OK;
 }
+
+
+status_t
+AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
+       const BUrl& url, uint32 redirects, uint32 failures)
+{
+       if (redirects > MAX_REDIRECTS) {
+               fprintf(stdout, "exceeded %d redirects --> failure\n", 
MAX_REDIRECTS);
+               return B_IO_ERROR;
+       }
+
+       if (failures > MAX_FAILURES) {
+               fprintf(stdout, "exceeded %d failures\n", MAX_FAILURES);
+               return B_IO_ERROR;
+       }
+
+       fprintf(stdout, "will stream '%s' to [%s]\n", url.UrlString().String(),
+               targetFilePath.Path());
+
+       ToFileUrlProtocolListener listener(targetFilePath, LoggingName(),
+               ServerSettings::UrlConnectionTraceLoggingEnabled());
+
+       BHttpHeaders headers;
+       ServerSettings::AugmentHeaders(headers);
+
+       BString ifModifiedSinceHeader;
+       status_t ifModifiedSinceHeaderStatus = IfModifiedSinceHeaderValue(
+               ifModifiedSinceHeader);
+
+       if (ifModifiedSinceHeaderStatus == B_OK &&
+               ifModifiedSinceHeader.Length() > 0) {
+               headers.AddHeader("If-Modified-Since", ifModifiedSinceHeader);
+       }
+
+       BHttpRequest *request = dynamic_cast<BHttpRequest *>(
+               BUrlProtocolRoster::MakeRequest(url, &listener));
+       ObjectDeleter<BHttpRequest> requestDeleter(request);
+       request->SetHeaders(headers);
+       request->SetMaxRedirections(0);
+       request->SetTimeout(TIMEOUT_MICROSECONDS);
+
+       thread_id thread = request->Run();
+       wait_for_thread(thread, NULL);
+
+       const BHttpResult& result = dynamic_cast<const BHttpResult&>(
+               request->Result());
+
+       int32 statusCode = result.StatusCode();
+
+       if (BHttpRequest::IsSuccessStatusCode(statusCode)) {
+               fprintf(stdout, "did complete streaming data\n");
+               return B_OK;
+       } else if (statusCode == HTTP_STATUS_NOT_MODIFIED) {
+               fprintf(stdout, "remote data has not changed since [%s]\n",
+                       ifModifiedSinceHeader.String());
+               return APP_ERR_NOT_MODIFIED;
+       } else if (BHttpRequest::IsRedirectionStatusCode(statusCode)) {
+               const BHttpHeaders responseHeaders = result.Headers();
+               const char *locationValue = responseHeaders["Location"];
+
+               if (locationValue != NULL && strlen(locationValue) != 0) {
+                       BUrl location(result.Url(), locationValue);
+                       fprintf(stdout, "will redirect to; %s\n",
+                               location.UrlString().String());
+                               return DownloadToLocalFile(targetFilePath, 
location, redirects + 1, 0);
+               }
+
+               fprintf(stdout, "unable to find 'Location' header for 
redirect\n");
+               return B_IO_ERROR;
+       } else {
+               if (statusCode == 0 || (statusCode / 100) == 5) {
+                       fprintf(stdout, "error response from server; %" 
B_PRId32 " --> "
+                               "retry...\n", statusCode);
+                       return DownloadToLocalFile(targetFilePath, url, 
redirects, failures + 1);
+               }
+
+               fprintf(stdout, "unexpected response from server; %" B_PRId32 
"\n",
+                       statusCode);
+               return B_IO_ERROR;
+       }
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/AbstractServerProcess.h 
b/src/apps/haikudepot/server/AbstractServerProcess.h
index 8264742..f6679a3 100644
--- a/src/apps/haikudepot/server/AbstractServerProcess.h
+++ b/src/apps/haikudepot/server/AbstractServerProcess.h
@@ -6,11 +6,51 @@
 #ifndef ABSTRACT_SERVER_PROCESS_H
 #define ABSTRACT_SERVER_PROCESS_H
 
+#include <Json.h>
 #include <String.h>
+#include <Url.h>
+
+#include "StandardMetaData.h"
+
+
+#define APP_ERR_NOT_MODIFIED (B_APP_ERROR_BASE + 452)
+
 
 class AbstractServerProcess {
 public:
-                       status_t                        Run();
+       virtual status_t                        Run() = 0;
+
+protected:
+       virtual void                            GetStandardMetaDataPath(
+                                                                       BPath& 
path) const = 0;
+       virtual void                            GetStandardMetaDataJsonPath(
+                                                                       
BString& jsonPath) const = 0;
+       virtual const char*                     LoggingName() const = 0;
+
+                       status_t                        
IfModifiedSinceHeaderValue(
+                                                                       
BString& headerValue) const;
+                       status_t                        
IfModifiedSinceHeaderValue(
+                                                                       
BString& headerValue,
+                                                                       const 
BPath& metaDataPath,
+                                                                       const 
BString& jsonPath) const;
+
+                       status_t                        PopulateMetaData(
+                                                                       
StandardMetaData& metaData,
+                                                                       const 
BPath& path,
+                                                                       const 
BString& jsonPath) const;
+
+                       status_t                        
ParseJsonFromFileWithListener(
+                                                                       
BJsonEventListener *listener,
+                                                                       const 
BPath& path) const;
+
+                       status_t                        DownloadToLocalFile(
+                                                                       const 
BPath& targetFilePath,
+                                                                       const 
BUrl& url,
+                                                                       uint32 
redirects, uint32 failures);
+
+private:
+                       bool                            LooksLikeGzip(const 
char *pathStr) const;
+
 };
 
 #endif // ABSTRACT_SERVER_PROCESS_H
diff --git a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp 
b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp
index 8264333..be41a54 100644
--- a/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp
+++ b/src/apps/haikudepot/server/RepositoryDataUpdateProcess.cpp
@@ -177,7 +177,7 @@ RepositoryDataUpdateProcess::Run()
 
                // TODO: add language ISO code to the path; just 'en' for now.
        status_t result = DownloadToLocalFile(fLocalFilePath,
-               ServerSettings::CreateFullUrl("/__repository/all_en.json.gz"),
+               ServerSettings::CreateFullUrl("/__repository/all-en.json.gz"),
                0, 0);
 
        if (result == B_OK) {
diff --git a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp 
b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp
index 6466b3e..d2444a3 100644
--- a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp
+++ b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.cpp
@@ -5,38 +5,16 @@
 
 #include "ServerIconExportUpdateProcess.h"
 
-#include <errno.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <time.h>
 
-#include <AutoDeleter.h>
 #include <FileIO.h>
-#include <HttpRequest.h>
-#include <HttpTime.h>
-#include <Json.h>
-#include <Url.h>
-#include <UrlProtocolRoster.h>
 #include <support/ZlibCompressionAlgorithm.h>
 
 #include "ServerSettings.h"
-#include "StandardMetaDataJsonEventListener.h"
 #include "StorageUtils.h"
 #include "TarArchiveService.h"
-#include "ToFileUrlProtocolListener.h"
-
-
-#define MAX_REDIRECTS 3
-#define MAX_FAILURES 2
-
-#define HTTP_STATUS_OK 200
-#define HTTP_STATUS_FOUND 302
-#define HTTP_STATUS_NOT_MODIFIED 304
-
-#define APP_ERR_NOT_MODIFIED (B_APP_ERROR_BASE + 452)
-
-// 30 seconds
-#define TIMEOUT_MICROSECONDS 3e+7
 
 
 /*! This constructor will locate the cached data in a standardized location */
@@ -48,6 +26,11 @@ ServerIconExportUpdateProcess::ServerIconExportUpdateProcess(
 }
 
 
+ServerIconExportUpdateProcess::~ServerIconExportUpdateProcess()
+{
+}
+
+
 status_t
 ServerIconExportUpdateProcess::Run()
 {
@@ -56,7 +39,7 @@ ServerIconExportUpdateProcess::Run()
 
        fprintf(stdout, "will start fetching icons\n");
 
-       result = _Download(tarGzFilePath);
+       result = Download(tarGzFilePath);
 
        if (result != APP_ERR_NOT_MODIFIED) {
                if (result != B_OK)
@@ -96,168 +79,33 @@ ServerIconExportUpdateProcess::Run()
 }
 
 
-status_t
-ServerIconExportUpdateProcess::_IfModifiedSinceHeaderValue(BString& 
headerValue,
-       BPath& iconMetaDataPath) const
+void
+ServerIconExportUpdateProcess::GetStandardMetaDataPath(BPath& path) const
 {
-       headerValue.SetTo("");
-       struct stat s;
-
-       if (-1 == stat(iconMetaDataPath.Path(), &s)) {
-               if (ENOENT != errno)
-                        return B_ERROR;
-
-               return B_FILE_NOT_FOUND;
-       }
-
-       StandardMetaData iconMetaData;
-       status_t result = _PopulateIconMetaData(iconMetaData, iconMetaDataPath);
-
-       if (result == B_OK) {
-
-               // An example of this output would be; 'Fri, 24 Oct 2014 
19:32:27 +0000'
-
-               BDateTime modifiedDateTime = iconMetaData
-                       .GetDataModifiedTimestampAsDateTime();
-               BPrivate::BHttpTime modifiedHttpTime(modifiedDateTime);
-               headerValue.SetTo(modifiedHttpTime
-                       .ToString(BPrivate::B_HTTP_TIME_FORMAT_COOKIE));
-       } else {
-               fprintf(stderr, "unable to parse the icon meta-data date and 
time -"
-                       " cannot set the 'If-Modified-Since' header\n");
-       }
-
-       return result;
+       path.SetTo(fLocalStorageDirectoryPath.Path());
+       path.Append("hicn/info.json");
 }
 
 
-status_t
-ServerIconExportUpdateProcess::_IfModifiedSinceHeaderValue(BString& 
headerValue)
-    const
+void
+ServerIconExportUpdateProcess::GetStandardMetaDataJsonPath(
+       BString& jsonPath) const
 {
-       BPath iconMetaDataPath(fLocalStorageDirectoryPath);
-       iconMetaDataPath.Append("hicn/info.json");
-       return _IfModifiedSinceHeaderValue(headerValue, iconMetaDataPath);
+               // the "$" here indicates that the data is at the top level.
+       jsonPath.SetTo("$");
 }
 
 
-status_t
-ServerIconExportUpdateProcess::_Download(BPath& tarGzFilePath)
+const char*
+ServerIconExportUpdateProcess::LoggingName() const
 {
-       return _Download(tarGzFilePath,
-               ServerSettings::CreateFullUrl("/__pkgicon/all.tar.gz"), 0, 0);
+       return "icon-export-update";
 }
 
 
 status_t
-ServerIconExportUpdateProcess::_Download(BPath& tarGzFilePath, const BUrl& url,
-       uint32 redirects, uint32 failures)
+ServerIconExportUpdateProcess::Download(BPath& tarGzFilePath)
 {
-       if (redirects > MAX_REDIRECTS) {
-               fprintf(stdout, "exceeded %d redirects --> failure\n", 
MAX_REDIRECTS);
-               return B_IO_ERROR;
-       }
-
-       if (failures > MAX_FAILURES) {
-               fprintf(stdout, "exceeded %d failures\n", MAX_FAILURES);
-               return B_IO_ERROR;
-       }
-
-       fprintf(stdout, "will stream '%s' to [%s]\n", url.UrlString().String(),
-               tarGzFilePath.Path());
-
-       ToFileUrlProtocolListener listener(tarGzFilePath, "icon-export",
-               ServerSettings::UrlConnectionTraceLoggingEnabled());
-
-       BHttpHeaders headers;
-       ServerSettings::AugmentHeaders(headers);
-
-       BString ifModifiedSinceHeader;
-       status_t ifModifiedSinceHeaderStatus = _IfModifiedSinceHeaderValue(
-               ifModifiedSinceHeader);
-
-       if (ifModifiedSinceHeaderStatus == B_OK &&
-               ifModifiedSinceHeader.Length() > 0) {
-               headers.AddHeader("If-Modified-Since", ifModifiedSinceHeader);
-       }
-
-       BHttpRequest *request = dynamic_cast<BHttpRequest *>(
-               BUrlProtocolRoster::MakeRequest(url, &listener));
-       ObjectDeleter<BHttpRequest> requestDeleter(request);
-       request->SetHeaders(headers);
-       request->SetMaxRedirections(0);
-       request->SetTimeout(TIMEOUT_MICROSECONDS);
-
-       thread_id thread = request->Run();
-       wait_for_thread(thread, NULL);
-
-       const BHttpResult& result = dynamic_cast<const BHttpResult&>(
-               request->Result());
-
-       int32 statusCode = result.StatusCode();
-
-       if (BHttpRequest::IsSuccessStatusCode(statusCode)) {
-               fprintf(stdout, "did complete streaming data\n");
-               return B_OK;
-       } else if (statusCode == HTTP_STATUS_NOT_MODIFIED) {
-               fprintf(stdout, "remote data has not changed since [%s]\n",
-                       ifModifiedSinceHeader.String());
-               return APP_ERR_NOT_MODIFIED;
-       } else if (BHttpRequest::IsRedirectionStatusCode(statusCode)) {
-               const BHttpHeaders responseHeaders = result.Headers();
-               const char *locationValue = responseHeaders["Location"];
-
-               if (locationValue != NULL && strlen(locationValue) != 0) {
-                       BUrl location(result.Url(), locationValue);
-                       fprintf(stdout, "will redirect to; %s\n",
-                               location.UrlString().String());
-                               return _Download(tarGzFilePath, location, 
redirects + 1, 0);
-               }
-
-               fprintf(stdout, "unable to find 'Location' header for 
redirect\n");
-               return B_IO_ERROR;
-       } else {
-               if (statusCode == 0 || (statusCode / 100) == 5) {
-                       fprintf(stdout, "error response from server; %" 
B_PRId32 " --> "
-                               "retry...\n", statusCode);
-                       return _Download(tarGzFilePath, url, redirects, 
failures + 1);
-               }
-
-               fprintf(stdout, "unexpected response from server; %" B_PRId32 
"\n",
-                       statusCode);
-               return B_IO_ERROR;
-       }
-}
-
-
-status_t
-ServerIconExportUpdateProcess::_PopulateIconMetaData(
-       StandardMetaData& iconMetaData, BPath& path) const
-{
-       FILE *file = fopen(path.Path(), "rb");
-
-       if (file == NULL) {
-               fprintf(stderr, "unable to find the icon meta data file at 
[%s]\n",
-                       path.Path());
-               return B_FILE_NOT_FOUND;
-       }
-
-       BFileIO iconMetaDataFile(file, true); // takes ownership
-               // the "$" here indicates that the data is at the top level.
-       StandardMetaDataJsonEventListener listener("$", iconMetaData);
-       BPrivate::BJson::Parse(&iconMetaDataFile, &listener);
-
-       status_t result = listener.ErrorStatus();
-
-       if (result != B_OK)
-               return result;
-
-       if (!iconMetaData.IsPopulated()) {
-               fprintf(stderr, "the icon meta data was read from [%s], but no 
values "
-                       "were extracted\n", path.Path());
-               return B_BAD_DATA;
-       }
-
-       return B_OK;
-}
-
+       return DownloadToLocalFile(tarGzFilePath,
+               ServerSettings::CreateFullUrl("/__pkgicon/all.tar.gz"), 0, 0);
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h 
b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h
index 9bcc67c..f91c806 100644
--- a/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h
+++ b/src/apps/haikudepot/server/ServerIconExportUpdateProcess.h
@@ -3,8 +3,8 @@
  * All rights reserved. Distributed under the terms of the MIT License.
  */
 
-#ifndef SERVER_ICON_PROCESS_H
-#define SERVER_ICON_PROCESS_H
+#ifndef SERVER_ICON_EXPORT_UPDATE_PROCESS_H
+#define SERVER_ICON_EXPORT_UPDATE_PROCESS_H
 
 
 #include "AbstractServerProcess.h"
@@ -14,35 +14,28 @@
 #include <String.h>
 #include <Url.h>
 
-#include "StandardMetaData.h"
-
 
 class ServerIconExportUpdateProcess : public AbstractServerProcess {
 public:
 
                                                                
ServerIconExportUpdateProcess(
                                                                        const 
BPath& localStorageDirectoryPath);
+       virtual                                         
~ServerIconExportUpdateProcess();
 
                        status_t                        Run();
 
+protected:
+                       void                            
GetStandardMetaDataPath(BPath& path) const;
+                       void                            
GetStandardMetaDataJsonPath(
+                                                                       
BString& jsonPath) const;
+                       const char*                     LoggingName() const;
+
+
 private:
-                       status_t                        _Download(BPath& 
tarGzFilePath);
-                       status_t                        _Download(BPath& 
tarGzFilePath, const BUrl& url,
-                                                                       uint32 
redirects, uint32 failures);
-                       BString                         _FormFullUrl(const 
BString& suffix) const;
-                       status_t                        
_IfModifiedSinceHeaderValue(
-                                                                       
BString& headerValue) const;
-                       status_t                        
_IfModifiedSinceHeaderValue(
-                                                                       
BString& headerValue,
-                                                                       BPath& 
iconMetaDataPath) const;
-
-                       status_t                        _PopulateIconMetaData(
-                                                                       
StandardMetaData& iconMetaData, BPath& path)
-                                                                       const;
-
-                       BString                         fBaseUrl;
+                       status_t                        Download(BPath& 
tarGzFilePath);
+
                        BPath                           
fLocalStorageDirectoryPath;
 
 };
 
-#endif // SERVER_ICON_PROCESS_H
+#endif // SERVER_ICON_EXPORT_UPDATE_PROCESS_H
diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index f24fe38..f92a136 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -851,12 +851,6 @@ MainWindow::_RefreshPackageList(bool force)
 
                if (getRepositoryConfigStatus == B_OK) {
                        depotInfo.SetBaseURL(repoConfig.BaseURL());
-
-                       // it would be nice if this could be more logically 
located such as
-                       // when the repository is added to the model, but that 
is probably
-                       // a bigger change.
-
-                       fModel.PopulateWebAppRepositoryCode(depotInfo);
                } else {
                        printf("unable to obtain the repository config for 
local "
                                "repository '%s'; %s\n",
@@ -1000,6 +994,8 @@ MainWindow::_RefreshPackageList(bool force)
                        fModel.AddDepot(it->second);
        }
 
+       fModel.PopulateWebAppRepositoryCodes();
+
        // start retrieving package icons and average ratings
        if (force || wasEmpty)
                fModel.PopulateAllPackages();
diff --git a/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp 
b/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp
index f996a93..c2af027 100644
--- a/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp
+++ b/src/tests/apps/haikudepot/HaikuDepotTestAddon.cpp
@@ -7,7 +7,7 @@
 #include <TestSuiteAddon.h>
 
 #include "StandardMetaDataJsonEventListenerTest.h"
-
+#include "DumpExportRepositoryJsonListenerTest.h"
 
 BTestSuite*
 getTestSuite()
@@ -15,6 +15,7 @@ getTestSuite()
        BTestSuite* suite = new BTestSuite("HaikuDepot");
 
        StandardMetaDataJsonEventListenerTest::AddTests(*suite);
+       DumpExportRepositoryJsonListenerTest::AddTests(*suite);
 
        return suite;
 }
diff --git a/src/tests/apps/haikudepot/Jamfile 
b/src/tests/apps/haikudepot/Jamfile
index b621a12..a8cbe67 100644
--- a/src/tests/apps/haikudepot/Jamfile
+++ b/src/tests/apps/haikudepot/Jamfile
@@ -3,13 +3,20 @@ SubDir HAIKU_TOP src tests apps haikudepot ;
 SetSubDirSupportedPlatformsBeOSCompatible ;
 AddSubDirSupportedPlatforms libbe_test ;
 
+SubDirHdrs [ FDirName $(HAIKU_TOP) src apps haikudepot ] ;
 SubDirHdrs [ FDirName $(HAIKU_TOP) src apps haikudepot server ] ;
+SubDirHdrs [ FDirName $(HAIKU_TOP) src apps haikudepot server 
dumpexportrepository ] ;
 
 UsePrivateHeaders shared ;
 
 UnitTestLib haikudepottest.so :
        HaikuDepotTestAddon.cpp
 
+       DumpExportRepositorySource.cpp
+       DumpExportRepository.cpp
+       DumpExportRepositoryJsonListener.cpp
+       DumpExportRepositoryJsonListenerTest.cpp
+
        StandardMetaData.cpp
        StandardMetaDataJsonEventListener.cpp
        StandardMetaDataJsonEventListenerTest.cpp
@@ -18,4 +25,7 @@ UnitTestLib haikudepottest.so :
 ;
 
 SEARCH on [ FGristFiles StandardMetaData.cpp 
StandardMetaDataJsonEventListener.cpp ]
-       = [ FDirName $(HAIKU_TOP) src apps haikudepot server ] ;
\ No newline at end of file
+       = [ FDirName $(HAIKU_TOP) src apps haikudepot server ] ;
+
+SEARCH on [ FGristFiles DumpExportRepositorySource.cpp 
DumpExportRepository.cpp DumpExportRepositoryJsonListener.cpp ]
+       = [ FDirName $(HAIKU_TOP) src apps haikudepot server 
dumpexportrepository ] ;
\ No newline at end of file


Other related posts:

  • » [haiku-commits] haiku: hrev51514 - in src: apps/haikudepot/server apps/haikudepot/model tests/apps/haikudepot apps/haikudepot - apl