blob: fa6a98c59741504f89cebf0a97de50339945e6cf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/system.h>
#include <log4cxx/helpers/filesystempath.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/properties.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <apr_file_io.h>
#include <apr_user.h>
#include <apr_env.h>
#ifdef _WIN32
#include <windows.h>
#elif __APPLE__
#include <mach-o/dyld.h>
#elif (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
#include <unistd.h> // getpid
#endif
#include <sstream>
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
LogString System::getProperty(const LogString& lkey)
{
if (lkey.empty())
{
throw IllegalArgumentException(LOG4CXX_STR("key is empty"));
}
LogString rv;
if (lkey == LOG4CXX_STR("java.io.tmpdir"))
{
Pool p;
const char* dir = NULL;
apr_status_t stat = apr_temp_dir_get(&dir, p.getAPRPool());
if (stat == APR_SUCCESS)
{
Transcoder::decode(dir, rv);
}
return rv;
}
if (lkey == LOG4CXX_STR("user.dir"))
{
Pool p;
char* dir = NULL;
apr_status_t stat = apr_filepath_get(&dir, APR_FILEPATH_NATIVE,
p.getAPRPool());
if (stat == APR_SUCCESS)
{
Transcoder::decode(dir, rv);
}
return rv;
}
#if APR_HAS_USER
if (lkey == LOG4CXX_STR("user.home") || lkey == LOG4CXX_STR("user.name"))
{
Pool pool;
apr_uid_t userid;
apr_gid_t groupid;
apr_pool_t* p = pool.getAPRPool();
apr_status_t stat = apr_uid_current(&userid, &groupid, p);
if (stat == APR_SUCCESS)
{
char* username = NULL;
stat = apr_uid_name_get(&username, userid, p);
if (stat == APR_SUCCESS)
{
if (lkey == LOG4CXX_STR("user.name"))
{
Transcoder::decode(username, rv);
}
else
{
char* dirname = NULL;
stat = apr_uid_homepath_get(&dirname, username, p);
if (stat == APR_SUCCESS)
{
Transcoder::decode(dirname, rv);
}
}
}
}
return rv;
}
#endif
LOG4CXX_ENCODE_CHAR(key, lkey);
Pool p;
char* value = NULL;
apr_status_t stat = apr_env_get(&value, key.c_str(),
p.getAPRPool());
if (stat == APR_SUCCESS)
{
Transcoder::decode((const char*) value, rv);
}
return rv;
}
void System::addProgramFilePathComponents(Properties& props)
{
// Find the executable file name
static const int bufSize = 4096;
char buf[bufSize+1] = {0}, pathSepar = '/';
#if defined(_WIN32)
if (0 == GetModuleFileName(NULL, buf, bufSize))
{
Pool p;
LogString lsErrorCode;
StringHelper::toString((int)GetLastError(), p, lsErrorCode);
LogLog::warn(LOG4CXX_STR("GetModuleFileName error ") + lsErrorCode);
return;
}
pathSepar = '\\';
#elif defined(__APPLE__)
uint32_t bufCount = bufSize;
if (0 != _NSGetExecutablePath(buf, &bufCount))
{
LogLog::warn(LOG4CXX_STR("_NSGetExecutablePath failed"));
return;
}
#elif (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
int bufCount = 0;
std::ostringstream exeLink;
exeLink << "/proc/" << getpid() << "/exe";
if ((bufCount = readlink(exeLink.str().c_str(), buf, bufSize)) <= 0)
{
LOG4CXX_DECODE_CHAR(lsExeLink, exeLink.str());
LogLog::warn(LOG4CXX_STR("Failed to read ") + lsExeLink);
return;
}
if (bufSize < bufCount)
buf[bufSize] = 0;
else
buf[bufCount] = 0;
#else
LogLog::warn(LOG4CXX_STR("Unable to determine the name of the executable file on this system"));
return;
#endif
// Add the path to the properties
std::string programFileName(buf);
if (programFileName.empty())
{
LogLog::warn(LOG4CXX_STR("Current executable's file name is empty"));
return;
}
LOG4CXX_DECODE_CHAR(lsProgramFileName, programFileName);
LogString prefix{ LOG4CXX_STR("PROGRAM_FILE_PATH") };
props.setProperty(prefix, lsProgramFileName);
#if LOG4CXX_HAS_FILESYSTEM_PATH
// Add the path components to the properties
prefix += '.';
FilesystemPath programPath(programFileName);
#if LOG4CXX_LOGCHAR_IS_WCHAR
auto root_name = programPath.root_name().wstring();
if (!root_name.empty())
props.setProperty(prefix + LOG4CXX_STR("ROOT_NAME"), root_name);
auto root_directory = programPath.root_directory().wstring();
props.setProperty(prefix + LOG4CXX_STR("ROOT_DIRECTORY"),root_directory);
auto root_path = programPath.root_path().wstring();
props.setProperty(prefix + LOG4CXX_STR("ROOT_PATH"), root_path);
auto relative_path = programPath.relative_path().wstring();
props.setProperty(prefix + LOG4CXX_STR("RELATIVE_PATH"), relative_path);
auto parent_path = programPath.parent_path().wstring();
props.setProperty(prefix + LOG4CXX_STR("PARENT_PATH"), parent_path);
auto filename = programPath.filename().wstring();
props.setProperty(prefix + LOG4CXX_STR("FILENAME"), filename);
auto stem = programPath.stem().wstring();
props.setProperty(prefix + LOG4CXX_STR("STEM"), stem);
auto extension = programPath.extension().wstring();
if (!extension.empty())
props.setProperty(prefix + LOG4CXX_STR("EXTENSION"), extension);
#else
LOG4CXX_DECODE_CHAR(root_name, programPath.root_name().string());
if (!root_name.empty())
props.setProperty(prefix + LOG4CXX_STR("ROOT_NAME"), root_name);
LOG4CXX_DECODE_CHAR(root_directory, programPath.root_directory().string());
props.setProperty(prefix + LOG4CXX_STR("ROOT_DIRECTORY"),root_directory);
LOG4CXX_DECODE_CHAR(root_path, programPath.root_path().string());
props.setProperty(prefix + LOG4CXX_STR("ROOT_PATH"), root_path);
LOG4CXX_DECODE_CHAR(relative_path, programPath.relative_path().string());
props.setProperty(prefix + LOG4CXX_STR("RELATIVE_PATH"), relative_path);
LOG4CXX_DECODE_CHAR(parent_path, programPath.parent_path().string());
props.setProperty(prefix + LOG4CXX_STR("PARENT_PATH"), parent_path);
LOG4CXX_DECODE_CHAR(filename, programPath.filename().string());
props.setProperty(prefix + LOG4CXX_STR("FILENAME"), filename);
LOG4CXX_DECODE_CHAR(stem, programPath.stem().string());
props.setProperty(prefix + LOG4CXX_STR("STEM"), stem);
LOG4CXX_DECODE_CHAR(extension, programPath.extension().string());
if (!extension.empty())
props.setProperty(prefix + LOG4CXX_STR("EXTENSION"), extension);
#endif
#endif // LOG4CXX_HAS_FILESYSTEM_PATH
}