//
// Copyright 2011 The Android Open Source Project
//
// Abstraction of calls to system to make directories and delete files and
// wrapper to image processing.
#ifndef CACHE_UPDATER_H
#define CACHE_UPDATER_H
#include <utils/String8.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "Images.h"
#ifdef HAVE_MS_C_RUNTIME
#include <direct.h>
#endif
using namespace android;
/** CacheUpdater
* This is a pure virtual class that declares abstractions of functions useful
* for managing a cache files. This manager is set up to be used in a
* mirror cache where the source tree is duplicated and filled with processed
* images. This class is abstracted to allow for dependency injection during
* unit testing.
* Usage:
* To update/add a file to the cache, call processImage
* To remove a file from the cache, call deleteFile
*/
class CacheUpdater {
public:
virtual ~CacheUpdater() {}
// Make sure all the directories along this path exist
virtual void ensureDirectoriesExist(String8 path) = 0;
// Delete a file
virtual void deleteFile(String8 path) = 0;
// Process an image from source out to dest
virtual void processImage(String8 source, String8 dest) = 0;
private:
};
/** SystemCacheUpdater
* This is an implementation of the above virtual cache updater specification.
* This implementations hits the filesystem to manage a cache and calls out to
* the PNG crunching in images.h to process images out to its cache components.
*/
class SystemCacheUpdater : public CacheUpdater {
public:
// Constructor to set bundle to pass to preProcessImage
SystemCacheUpdater (Bundle* b)
: bundle(b) { };
// Make sure all the directories along this path exist
virtual void ensureDirectoriesExist(String8 path)
{
// Check to see if we're dealing with a fully qualified path
String8 existsPath;
String8 toCreate;
String8 remains;
struct stat s;
// Check optomistically to see if all directories exist.
// If something in the path doesn't exist, then walk the path backwards
// and find the place to start creating directories forward.
if (stat(path.string(),&s) == -1) {
// Walk backwards to find place to start creating directories
existsPath = path;
do {
// As we remove the end of existsPath add it to
// the string of paths to create.
toCreate = existsPath.getPathLeaf().appendPath(toCreate);
existsPath = existsPath.getPathDir();
} while (stat(existsPath.string(),&s) == -1);
// Walk forwards and build directories as we go
do {
// Advance to the next segment of the path
existsPath.appendPath(toCreate.walkPath(&remains));
toCreate = remains;
#ifdef HAVE_MS_C_RUNTIME
_mkdir(existsPath.string());
#else
mkdir(existsPath.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
#endif
} while (remains.length() > 0);
} //if
};
// Delete a file
virtual void deleteFile(String8 path)
{
if (remove(path.string()) != 0)
fprintf(stderr,"ERROR DELETING %s\n",path.string());
};
// Process an image from source out to dest
virtual void processImage(String8 source, String8 dest)
{
// Make sure we're trying to write to a directory that is extant
ensureDirectoriesExist(dest.getPathDir());
preProcessImageToCache(bundle, source, dest);
};
private:
Bundle* bundle;
};
#endif // CACHE_UPDATER_H