FileFormatManager.cpp 3.55 KB
#include "FileFormatManager.h"

#include <cstring>

#include "../Common/Toolbox.h"

using namespace TREPS::Common;

namespace TREPS
{
	namespace File
	{
		FileFormatManagerClass::FileFormatManagerClass(void) : app(NULL), loader(NULL)
		{
			this->app = ApplicationClass::getInstance();
		}

		FileFormatManagerClass::~FileFormatManagerClass(void)
		{
			if (this->loader != NULL)
			{
				this->loader->close();
				delete this->loader;
				this->loader = NULL;
			}
		}

		bool FileFormatManagerClass::init(const char *format_path)
		{
			//create xml loader
			if (this->loader == NULL)
				this->loader = new XMLManagerClass();

			this->loader->close();

			if (!this->loader->isExist(format_path))
			{
				LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot find formats file : " << format_path);
				return false;
			}

			//load xml file
			if (!this->loader->loadFile(format_path))
			{
				LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Cannot load formats file : " << format_path);
				return false;
			}

			//file validation with xsd
			if (!this->loader->isValid(TREPS_FORMATS_XSD))
			{
				LOG4CXX_ERROR(this->app->getLog()->getPtr(),"Invalid formats file : " << format_path);
				return false;
			}

			return true;
		}

		t_FileFormat FileFormatManagerClass::getFileFormatFromId(const char *format_id)
		{
			if (strcmp(format_id,"ascii") == 0)
				return FF_ASCII;
			else if (strcmp(format_id,"votable") == 0)
				return FF_VOTABLE;
			else if (strcmp(format_id,"cdf") == 0)
				return FF_CDF;
			else if (strcmp(format_id,"netcdf") == 0)
				return FF_NETCDF;

			return FF_NONE;
		}

		string FileFormatManagerClass::getFileFormatIdFromFileFormat(t_FileFormat format)
		{
			switch (format)
			{
				case FF_ASCII :
					return "ascii";
				case FF_VOTABLE :
					return "votable";
				case FF_CDF :
					return "cdf";
				case FF_NETCDF :
					return "netcdf";
				case FF_NONE :
					return "";
			}

			return "";
		}

		t_FileFormat FileFormatManagerClass::detectFileFormat(const char *filePath)
		{
			string type = getFileMIMEType(filePath);

			LOG4CXX_INFO(this->app->getLog()->getPtr(),"File MIME Type : " << type);

			//remove charset
			size_t pos;
			pos = type.find(";");

			if (pos != string::npos)
				type = type.substr(0,pos);

			//ASCII file detection
			if (type.find("text/") != string::npos)
				return FF_ASCII;

			//VOTable detection (a VOTable is a xml file)
			if (type.compare("application/xml") == 0)
				return FF_VOTABLE;

			if ((type.compare("application/octet-stream") == 0))
			{
				//netcdf or cdf file detection
				
				//read magic number
				char buf[5];

				FILE *file = fopen(filePath, "rb");
				fread(buf, sizeof(char), 4, file);
				fclose(file);

				buf[4] = '\0';

				//get magic number (read a big-endian integer from a byte array)
				int magicNum1 = ((buf[0] & 0xff ) << 24 | ( buf[1] & 0xff ) << 16 | ( buf[2] & 0xff ) << 8 | ( buf[3] & 0xff ) << 0);

				//test magic number
				if ((magicNum1 & 0xfff00000) == 0xcdf00000)  //CDF >= 2.6
				{
					LOG4CXX_INFO(this->app->getLog()->getPtr(),"CDF detected - Version >= 2.6");
					return FF_CDF;
				}
				else if (magicNum1 == 0x0000ffff)
				{
					LOG4CXX_INFO(this->app->getLog()->getPtr(),"CDF detected - Version < 2.6");
					return FF_CDF;
				}

				//test key word
				buf[3] = '\0';
				if (strcmp(buf,"CDF") == 0) //NetCDF (it's not an error, the key word for netCDF is CDF ...)
				{
					LOG4CXX_INFO(this->app->getLog()->getPtr(),"NetCDF detected");
					return FF_NETCDF;
				}
			}

			LOG4CXX_ERROR(this->app->getLog()->getPtr(),"File format not supported");

			return FF_NONE;
		}
	}
}