// Throws AIAlert::ErrorCode with the http status as 'code' (HTTP_OK on XML parse error).
void HippoGridInfo::getGridInfo()
{
	if (mLoginUri.empty())
	{
		// By passing 0 we automatically get GridInfoErrorInstruction appended.
		THROW_ALERTC(0, "GridInfoErrorNoLoginURI");
	}

	// Make sure the uri ends on a '/'.
	std::string uri = mLoginUri;
	if (uri.compare(uri.length() - 1, 1, "/") != 0)
	{
		uri += '/';
	}

	std::string reply;
	int result = LLHTTPClient::blockingGetRaw(uri + "get_grid_info", reply);
	if (result != HTTP_OK)
	{
		char const* xml_desc;
		switch (result)
		{
			case HTTP_NOT_FOUND:
				xml_desc = "GridInfoErrorNotFound";
				break;
			case HTTP_METHOD_NOT_ALLOWED:
				xml_desc = "GridInfoErrorNotAllowed";
				break;
			default:
				xml_desc = "AIError";
				break;
		}
		// LLHTTPClient::blockingGetRaw puts any error message in the reply.
		THROW_ALERTC(result, xml_desc, AIArgs("[ERROR]", reply));
	}

	llinfos << "Received: " << reply << llendl;

	XML_Parser parser = XML_ParserCreate(0);
	XML_SetUserData(parser, this);
	XML_SetElementHandler(parser, onXmlElementStart, onXmlElementEnd);
	XML_SetCharacterDataHandler(parser, onXmlCharacterData);
	mXmlState = XML_VOID;
	if (!XML_Parse(parser, reply.data(), reply.size(), TRUE)) 
	{
		THROW_ALERTC(HTTP_OK, "GridInfoParseError", AIArgs("[XML_ERROR]", XML_ErrorString(XML_GetErrorCode(parser))));
	}
	XML_ParserFree(parser);
}
//static
void AIFile::rename(std::string const& filename, std::string const& newname)
{
    if (LLFile::rename_nowarn(filename, newname) < 0)
    {
        THROW_ERROR("AIFile_rename_Failed_to_rename_FILE_to_NEWFILE", AIArgs("[FILE]", filename)("[NEWFILE]", newname));
    }
}
//static
void AIFile::rmdir(std::string const& dirname)
{
    int rc = LLFile::rmdir_nowarn(dirname);
    if (rc < 0 && errno != ENOENT)
    {
        THROW_ERROR("AIFile_rmdir_Failed_to_remove_DIRNAME", AIArgs("[DIRNAME]", dirname));
    }
}
//static
void AIFile::mkdir(std::string const& dirname, int perms)
{
    int rc = LLFile::mkdir_nowarn(dirname, perms);
    if (rc < 0 && errno != EEXIST)
    {
        THROW_ERROR("AIFile_mkdir_Failed_to_create_DIRNAME", AIArgs("[DIRNAME]", dirname));
    }
}
//static
void AIFile::remove(std::string const& filename)
{
    int rc = LLFile::remove_nowarn(filename);
    if (rc < 0 && errno != ENOENT)
    {
        THROW_ERROR("AIFile_remove_Failed_to_remove_FILENAME", AIArgs("[FILENAME]", filename));
    }
}
//static
LLFILE*	AIFile::fopen(std::string const& filename, const char* mode)
{
    LLFILE* fp = LLFile::fopen(filename, mode);
    if (!fp)
    {
        THROW_ERROR("AIFile_fopen_Failed_to_open_FILENAME", AIArgs("[FILENAME]", filename));
    }
    return fp;
}
AIArchetype::MetaData::MetaData(AIXMLElementParser const& parser)
{
    char const* missing = NULL;
    if (!parser.attribute("path", mPath))
    {
        missing = "path";
    }
    if (!parser.attribute("name", mName))
    {
        missing = "name";
    }
    if (!parser.attribute("description", mDescription))
    {
        missing = "description";
    }
    if (missing)
    {
        THROW_ALERT("AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE", AIArgs("[ATTRIBUTE]", missing));
    }
}