<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed 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 "impl/external_commit_helper.hpp"
#include "impl/realm_coordinator.hpp"
#include "util/format.hpp"

#include <realm/util/assert.hpp>

#include <algorithm>
#include <errno.h>
#include <fcntl.h>
#include <sstream>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <system_error>
#include <unistd.h>

#ifdef __ANDROID__
#include <android/log.h>
#define ANDROID_LOG __android_log_print
#else
#define ANDROID_LOG(...)
#endif

using namespace realm;
using namespace realm::_impl;

#define LOGE(...) do { \
    fprintf(stderr, __VA_ARGS__); \
    ANDROID_LOG(ANDROID_LOG_ERROR, "REALM", __VA_ARGS__); \
} while (0)

namespace {
// Write a byte to a pipe to notify anyone waiting for data on the pipe
void notify_fd(int fd)
{
    while (true) {
        char c = 0;
        ssize_t ret = write(fd, &c, 1);
        if (ret == 1) {
            break;
        }

        // If the pipe's buffer is full, we need to read some of the old data in
        // it to make space. We don't just read in the code waiting for
        // notifications so that we can notify multiple waiters with a single
        // write.
        if (ret != 0) {
            int err = errno;
            if (err != EAGAIN) {
                throw std::system_error(err, std::system_category());
            }
        }
        std::vector<uint8_t> buff(1024);
        read(fd, buff.data(), buff.size());
    }
}
} // anonymous namespace

class ExternalCommitHelper::DaemonThread {
public:
    DaemonThread();
    ~DaemonThread();

    void add_commit_helper(ExternalCommitHelper* helper);
    // Return true if the m_helper_list is empty after removal.
    void remove_commit_helper(ExternalCommitHelper* helper);

    static DaemonThread& shared();
private:
    void listen();

    // To protect the accessing m_helpers on the daemon thread.
    std::mutex m_mutex;
    std::vector<ExternalCommitHelper*> m_helpers;
    // The listener thread
    std::thread m_thread;
    // File descriptor for epoll
    FdHolder m_epoll_fd;
    // The two ends of an anonymous pipe used to notify the kqueue() thread that it should be shut down.
    FdHolder m_shutdown_read_fd;
    FdHolder m_shutdown_write_fd;
    // Daemon thread id. For checking unexpected dead locks.
    std::thread::id m_thread_id;
};

void ExternalCommitHelper::FdHolder::close()
{
    if (m_fd != -1) {
        ::close(m_fd);
    }
    m_fd = -1;
}

ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
: m_parent(parent)
{
    std::string path;
    std::string temporary_dir = realm::get_temporary_directory();
    if (temporary_dir.empty()) {
        path = parent.get_path() + ".note";
    } else {
        // The fifo is always created in the temporary directory if it is provided.
        // See https://github.com/realm/realm-java/issues/3140
        // We create .note file on the temp directory always for simplicity no matter where the Realm file is.
        // Hash collisions are okay here because they just result in doing extra work.
        path = util::format("%1%2_realm.note", temporary_dir, std::hash<std::string>()(parent.get_path()));
    }

    // Create and open the named pipe
    int ret = mkfifo(path.c_str(), 0600);
    if (ret == -1) {
        int err = errno;
        // the fifo already existing isn't an error
        if (err != EEXIST) {
            // Workaround for a mkfifo bug on Blackberry devices:
            // When the fifo already exists, mkfifo fails with error ENOSYS which is not correct.
            // In this case, we use stat to check if the path exists and it is a fifo.
            struct stat stat_buf;
            if (err == ENOSYS && stat(path.c_str(), &stat_buf) == 0) {
                if ((stat_buf.st_mode & S_IFMT) != S_IFIFO) {
                    throw std::runtime_error(path + " exists and it is not a fifo.");
                }
            }
            else {
                throw std::system_error(err, std::system_category());
            }
        }
    }

    m_notify_fd = open(path.c_str(), O_RDWR);
    if (m_notify_fd == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Make writing to the pipe return -1 when the pipe's buffer is full
    // rather than blocking until there's space available
    ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
    if (ret == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Lock is inside add_commit_helper.
    DaemonThread::shared().add_commit_helper(this);
}

ExternalCommitHelper::~ExternalCommitHelper()
{
    DaemonThread::shared().remove_commit_helper(this);
}

ExternalCommitHelper::DaemonThread::DaemonThread()
{
    m_epoll_fd = epoll_create(1);
    if (m_epoll_fd == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Create the anonymous pipe
    int pipe_fd[2];
    int ret = pipe(pipe_fd);
    if (ret == -1) {
        throw std::system_error(errno, std::system_category());
    }

    m_shutdown_read_fd = pipe_fd[0];
    m_shutdown_write_fd = pipe_fd[1];

    struct epoll_event event;

    event.events = EPOLLIN;
    event.data.fd = m_shutdown_read_fd;
    ret = epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, m_shutdown_read_fd, &event);
    if (ret != 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }

    m_thread = std::thread([=] {
        try {
            listen();
        }
        catch (std::exception const& e) {
            LOGE("uncaught exception in notifier thread: %s: %s\n", typeid(e).name(), e.what());
            throw;
        }
        catch (...) {
            LOGE("uncaught exception in notifier thread\n");
            throw;
        }
    });
    m_thread_id = m_thread.get_id();
}

ExternalCommitHelper::DaemonThread::~DaemonThread()
{
    notify_fd(m_shutdown_write_fd);
    m_thread.join(); // Wait for the thread to exit
}

ExternalCommitHelper::DaemonThread& ExternalCommitHelper::DaemonThread::shared()
{
    static DaemonThread daemon_thread;
    return daemon_thread;
}

void ExternalCommitHelper::DaemonThread::add_commit_helper(ExternalCommitHelper* helper)
{
    // Called in the deamon thread loop, dead lock will happen.
    REALM_ASSERT(std::this_thread::get_id() != m_thread_id);

    std::lock_guard<std::mutex> lock(m_mutex);
    struct epoll_event event;

    m_helpers.push_back(helper);

    event.events = EPOLLIN | EPOLLET;
    event.data.fd = helper->m_notify_fd;
    int ret = epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, helper->m_notify_fd, &event);
    if (ret != 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }
}

void ExternalCommitHelper::DaemonThread::remove_commit_helper(ExternalCommitHelper* helper)
{
    // Called in the deamon thread loop, dead lock will happen.
    REALM_ASSERT(std::this_thread::get_id() != m_thread_id);

    std::lock_guard<std::mutex> lock(m_mutex);

    m_helpers.erase(std::remove(m_helpers.begin(), m_helpers.end(), helper), m_helpers.end());

    struct epoll_event event;

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-NULL pointer in event, even
    // though this argument is ignored. See man page of epoll_ctl.
    epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, helper->m_notify_fd, &event);
}

void ExternalCommitHelper::DaemonThread::listen()
{
    pthread_setname_np(pthread_self(), "Realm notification listener");

    int ret;

    while (true) {
        struct epoll_event ev;
        ret = epoll_wait(m_epoll_fd, &ev, 1, -1);

        if (ret == -1 && errno == EINTR) {
            // Interrupted system call, try again.
            continue;
        }

        if (ret == -1) {
            int err = errno;
            throw std::system_error(err, std::system_category());
        }
        if (ret == 0) {
            // Spurious wakeup; just wait again
            continue;
        }

        if (ev.data.u32 == (uint32_t)m_shutdown_read_fd) {
            return;
        }

        {
            std::lock_guard<std::mutex> lock(m_mutex);
            for (auto helper : m_helpers) {
                if (ev.data.u32 == (uint32_t)helper->m_notify_fd) {
                    helper->m_parent.on_change();
                }
            }
        }
    }
}

void ExternalCommitHelper::notify_others()
{
    notify_fd(m_notify_fd);
}
<commit_msg>Fix valgrind errors about passing uninitialized values to epoll<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed 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 "impl/external_commit_helper.hpp"
#include "impl/realm_coordinator.hpp"
#include "util/format.hpp"

#include <realm/util/assert.hpp>

#include <algorithm>
#include <errno.h>
#include <fcntl.h>
#include <sstream>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <system_error>
#include <unistd.h>

#ifdef __ANDROID__
#include <android/log.h>
#define ANDROID_LOG __android_log_print
#else
#define ANDROID_LOG(...)
#endif

using namespace realm;
using namespace realm::_impl;

#define LOGE(...) do { \
    fprintf(stderr, __VA_ARGS__); \
    ANDROID_LOG(ANDROID_LOG_ERROR, "REALM", __VA_ARGS__); \
} while (0)

namespace {
// Write a byte to a pipe to notify anyone waiting for data on the pipe
void notify_fd(int fd)
{
    while (true) {
        char c = 0;
        ssize_t ret = write(fd, &c, 1);
        if (ret == 1) {
            break;
        }

        // If the pipe's buffer is full, we need to read some of the old data in
        // it to make space. We don't just read in the code waiting for
        // notifications so that we can notify multiple waiters with a single
        // write.
        if (ret != 0) {
            int err = errno;
            if (err != EAGAIN) {
                throw std::system_error(err, std::system_category());
            }
        }
        std::vector<uint8_t> buff(1024);
        read(fd, buff.data(), buff.size());
    }
}
} // anonymous namespace

class ExternalCommitHelper::DaemonThread {
public:
    DaemonThread();
    ~DaemonThread();

    void add_commit_helper(ExternalCommitHelper* helper);
    // Return true if the m_helper_list is empty after removal.
    void remove_commit_helper(ExternalCommitHelper* helper);

    static DaemonThread& shared();
private:
    void listen();

    // To protect the accessing m_helpers on the daemon thread.
    std::mutex m_mutex;
    std::vector<ExternalCommitHelper*> m_helpers;
    // The listener thread
    std::thread m_thread;
    // File descriptor for epoll
    FdHolder m_epoll_fd;
    // The two ends of an anonymous pipe used to notify the kqueue() thread that it should be shut down.
    FdHolder m_shutdown_read_fd;
    FdHolder m_shutdown_write_fd;
    // Daemon thread id. For checking unexpected dead locks.
    std::thread::id m_thread_id;
};

void ExternalCommitHelper::FdHolder::close()
{
    if (m_fd != -1) {
        ::close(m_fd);
    }
    m_fd = -1;
}

ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
: m_parent(parent)
{
    std::string path;
    std::string temporary_dir = realm::get_temporary_directory();
    if (temporary_dir.empty()) {
        path = parent.get_path() + ".note";
    } else {
        // The fifo is always created in the temporary directory if it is provided.
        // See https://github.com/realm/realm-java/issues/3140
        // We create .note file on the temp directory always for simplicity no matter where the Realm file is.
        // Hash collisions are okay here because they just result in doing extra work.
        path = util::format("%1%2_realm.note", temporary_dir, std::hash<std::string>()(parent.get_path()));
    }

    // Create and open the named pipe
    int ret = mkfifo(path.c_str(), 0600);
    if (ret == -1) {
        int err = errno;
        // the fifo already existing isn't an error
        if (err != EEXIST) {
            // Workaround for a mkfifo bug on Blackberry devices:
            // When the fifo already exists, mkfifo fails with error ENOSYS which is not correct.
            // In this case, we use stat to check if the path exists and it is a fifo.
            struct stat stat_buf;
            if (err == ENOSYS && stat(path.c_str(), &stat_buf) == 0) {
                if ((stat_buf.st_mode & S_IFMT) != S_IFIFO) {
                    throw std::runtime_error(path + " exists and it is not a fifo.");
                }
            }
            else {
                throw std::system_error(err, std::system_category());
            }
        }
    }

    m_notify_fd = open(path.c_str(), O_RDWR);
    if (m_notify_fd == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Make writing to the pipe return -1 when the pipe's buffer is full
    // rather than blocking until there's space available
    ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
    if (ret == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Lock is inside add_commit_helper.
    DaemonThread::shared().add_commit_helper(this);
}

ExternalCommitHelper::~ExternalCommitHelper()
{
    DaemonThread::shared().remove_commit_helper(this);
}

ExternalCommitHelper::DaemonThread::DaemonThread()
{
    m_epoll_fd = epoll_create(1);
    if (m_epoll_fd == -1) {
        throw std::system_error(errno, std::system_category());
    }

    // Create the anonymous pipe
    int pipe_fd[2];
    int ret = pipe(pipe_fd);
    if (ret == -1) {
        throw std::system_error(errno, std::system_category());
    }

    m_shutdown_read_fd = pipe_fd[0];
    m_shutdown_write_fd = pipe_fd[1];

    epoll_event event{};
    event.events = EPOLLIN;
    event.data.fd = m_shutdown_read_fd;
    ret = epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, m_shutdown_read_fd, &event);
    if (ret != 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }

    m_thread = std::thread([=] {
        try {
            listen();
        }
        catch (std::exception const& e) {
            LOGE("uncaught exception in notifier thread: %s: %s\n", typeid(e).name(), e.what());
            throw;
        }
        catch (...) {
            LOGE("uncaught exception in notifier thread\n");
            throw;
        }
    });
    m_thread_id = m_thread.get_id();
}

ExternalCommitHelper::DaemonThread::~DaemonThread()
{
    notify_fd(m_shutdown_write_fd);
    m_thread.join(); // Wait for the thread to exit
}

ExternalCommitHelper::DaemonThread& ExternalCommitHelper::DaemonThread::shared()
{
    static DaemonThread daemon_thread;
    return daemon_thread;
}

void ExternalCommitHelper::DaemonThread::add_commit_helper(ExternalCommitHelper* helper)
{
    // Called in the deamon thread loop, dead lock will happen.
    REALM_ASSERT(std::this_thread::get_id() != m_thread_id);

    std::lock_guard<std::mutex> lock(m_mutex);

    m_helpers.push_back(helper);

    epoll_event event{};
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = helper->m_notify_fd;
    int ret = epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, helper->m_notify_fd, &event);
    if (ret != 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }
}

void ExternalCommitHelper::DaemonThread::remove_commit_helper(ExternalCommitHelper* helper)
{
    // Called in the deamon thread loop, dead lock will happen.
    REALM_ASSERT(std::this_thread::get_id() != m_thread_id);

    std::lock_guard<std::mutex> lock(m_mutex);

    m_helpers.erase(std::remove(m_helpers.begin(), m_helpers.end(), helper), m_helpers.end());

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-NULL pointer in event, even
    // though this argument is ignored. See man page of epoll_ctl.
    epoll_event event{};
    epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, helper->m_notify_fd, &event);
}

void ExternalCommitHelper::DaemonThread::listen()
{
    pthread_setname_np(pthread_self(), "Realm notification listener");

    int ret;

    while (true) {
        epoll_event ev{};
        ret = epoll_wait(m_epoll_fd, &ev, 1, -1);

        if (ret == -1 && errno == EINTR) {
            // Interrupted system call, try again.
            continue;
        }

        if (ret == -1) {
            int err = errno;
            throw std::system_error(err, std::system_category());
        }
        if (ret == 0) {
            // Spurious wakeup; just wait again
            continue;
        }

        if (ev.data.u32 == (uint32_t)m_shutdown_read_fd) {
            return;
        }

        {
            std::lock_guard<std::mutex> lock(m_mutex);
            for (auto helper : m_helpers) {
                if (ev.data.u32 == (uint32_t)helper->m_notify_fd) {
                    helper->m_parent.on_change();
                }
            }
        }
    }
}

void ExternalCommitHelper::notify_others()
{
    notify_fd(m_notify_fd);
}
<|endoftext|>


<commit_before>#include <boost/lexical_cast.hpp>
#include <sstream>
#include <climits>
#include "util/numconversions.h"
#include <iostream>

namespace xqp {
  bool NumConversions::strToInteger(const xqpString& aStr, xqp_integer& aInteger){
    try {
      aInteger = boost::lexical_cast<xqp_integer>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::integerToStr(xqp_integer aInteger){
    return boost::lexical_cast<std::string>(aInteger);
  }
  bool NumConversions::strToUInteger(const xqpString& aStr, xqp_uinteger& aUInteger){
    try {
      aUInteger = boost::lexical_cast<xqp_uinteger>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::uintegerToStr(xqp_uinteger aUInteger){
    return boost::lexical_cast<std::string>(aUInteger);
  }
  bool NumConversions::starCharToInt(const char* aStarChar, xqp_int& aInt){
    try {
      aInt =  boost::lexical_cast<xqp_int>(aStarChar);
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  bool NumConversions::strToInt(const xqpString& aStr, xqp_int& aInt) {
    return starCharToInt(aStr.c_str(), aInt);
  }
  xqpString NumConversions::intToStr(xqp_int aInt){
    return boost::lexical_cast<std::string>(aInt);
  }
  bool NumConversions::strToUInt(const xqpString& aStr, xqp_uint& aUInt){
    try {
      aUInt =  boost::lexical_cast<xqp_uint>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::uintToStr(xqp_uint aUInt){
    return boost::lexical_cast<std::string>(aUInt);
  }
  bool NumConversions::strToLong(const xqpString& aStr, xqp_long& aLong){
    try {
      aLong = boost::lexical_cast<xqp_long>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::longToStr(xqp_long aLong){
    return boost::lexical_cast<std::string>(aLong);
  }
  bool NumConversions::strToULong(const xqpString& aStr, xqp_ulong& aULong){
    try {
      aULong = boost::lexical_cast<xqp_long>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ulongToStr(xqp_ulong aULong){
    return boost::lexical_cast<std::string>(aULong);
  }
  bool NumConversions::strToShort(const xqpString& aStr, xqp_short& aShort){
    try {
      aShort = boost::lexical_cast<xqp_short>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::shortToStr(xqp_short aShort){
    return boost::lexical_cast<std::string>(aShort);
  }
  bool NumConversions::strToUShort(const xqpString& aStr, xqp_ushort& aUShort){
    try {
      aUShort = boost::lexical_cast<xqp_short>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ushortToStr(xqp_ushort aUShort){
    return boost::lexical_cast<std::string>(aUShort);
  }
  bool NumConversions::starCharToDecimal(const char* aStarChar, xqp_decimal& aDecimal){
    try {
      aDecimal = boost::lexical_cast<xqp_decimal>(aStarChar);
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  bool NumConversions::strToDecimal(const xqpString& aStr, xqp_decimal& aDecimal) {
    return starCharToDecimal(aStr.c_str(), aDecimal);
  }
  xqpString NumConversions::decimalToStr(xqp_decimal aDecimal){
    return boost::lexical_cast<std::string>(aDecimal);
  }
  bool NumConversions::starCharToFloat(const char* aCharStar, xqp_float& aFloat) {
    char* lEndPtr;
     aFloat = (xqp_float)strtod(aCharStar, &lEndPtr);//daniel: changed from strtof to compile on Windows
    if (*lEndPtr != '\0')
      return false;
    else
      return true;

  }
  bool NumConversions::strToFloat(const xqpString& aStr, xqp_float& aFloat){
    return NumConversions::starCharToFloat(aStr.c_str(), aFloat);
  }
  xqpString NumConversions::floatToStr(xqp_float aFloat){
    if (aFloat == std::numeric_limits<float>::infinity())
      return "INF";
    else if (aFloat == -std::numeric_limits<float>::infinity())
      return "-INF";
    else if (aFloat != aFloat)
      return "NaN";
    else {
      std::stringstream lStream;
      lStream << aFloat;
      return lStream.str();
    }
  }
  bool NumConversions::starCharToDouble(const char* aStarChar, xqp_double& aDouble){
    char* lEndPtr;
    aDouble = strtod(aStarChar, &lEndPtr);
    if (*lEndPtr != '\0')
      return false;
    else
      return true;
  }
  bool NumConversions::strToDouble(const xqpString& aStr, xqp_double& aDouble) {
    return starCharToDouble(aStr.c_str(), aDouble);
  }
  xqpString NumConversions::doubleToStr(xqp_double aDouble){
    if (aDouble == std::numeric_limits<double>::infinity())
      return "INF";
    else if (aDouble == -std::numeric_limits<double>::infinity())
      return "-INF";
    else if (aDouble != aDouble)
      return "NaN";
    else {
      std::stringstream lStream;
      lStream << aDouble;
      return lStream.str();
    }
  }
  bool NumConversions::strToByte(const xqpString& aStr, xqp_byte& aByte){
    try {
      aByte = boost::lexical_cast<xqp_byte>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::byteToStr(xqp_byte aByte){
    return boost::lexical_cast<std::string>(aByte);
  }
  bool NumConversions::strToUByte(const xqpString& aStr, xqp_ubyte& aUByte){
    try {
      aUByte = boost::lexical_cast<xqp_ubyte>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ubyteToStr(xqp_ubyte aUByte){
    return boost::lexical_cast<std::string>(aUByte);
  }
} /* namespace xqp */
<commit_msg>byte parsing bug fixed (workaround a boost bug implemented)<commit_after>#include <boost/lexical_cast.hpp>
#include <sstream>
#include <climits>
#include "util/numconversions.h"
#include <iostream>

namespace xqp {
  bool NumConversions::strToInteger(const xqpString& aStr, xqp_integer& aInteger){
    try {
      aInteger = boost::lexical_cast<xqp_integer>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::integerToStr(xqp_integer aInteger){
    return boost::lexical_cast<std::string>(aInteger);
  }
  bool NumConversions::strToUInteger(const xqpString& aStr, xqp_uinteger& aUInteger){
    try {
      aUInteger = boost::lexical_cast<xqp_uinteger>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::uintegerToStr(xqp_uinteger aUInteger){
    return boost::lexical_cast<std::string>(aUInteger);
  }
  bool NumConversions::starCharToInt(const char* aStarChar, xqp_int& aInt){
    try {
      aInt =  boost::lexical_cast<xqp_int>(aStarChar);
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  bool NumConversions::strToInt(const xqpString& aStr, xqp_int& aInt) {
    return starCharToInt(aStr.c_str(), aInt);
  }
  xqpString NumConversions::intToStr(xqp_int aInt){
    return boost::lexical_cast<std::string>(aInt);
  }
  bool NumConversions::strToUInt(const xqpString& aStr, xqp_uint& aUInt){
    try {
      aUInt =  boost::lexical_cast<xqp_uint>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::uintToStr(xqp_uint aUInt){
    return boost::lexical_cast<std::string>(aUInt);
  }
  bool NumConversions::strToLong(const xqpString& aStr, xqp_long& aLong){
    try {
      aLong = boost::lexical_cast<xqp_long>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::longToStr(xqp_long aLong){
    return boost::lexical_cast<std::string>(aLong);
  }
  bool NumConversions::strToULong(const xqpString& aStr, xqp_ulong& aULong){
    try {
      aULong = boost::lexical_cast<xqp_long>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ulongToStr(xqp_ulong aULong){
    return boost::lexical_cast<std::string>(aULong);
  }
  bool NumConversions::strToShort(const xqpString& aStr, xqp_short& aShort){
    try {
      aShort = boost::lexical_cast<xqp_short>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::shortToStr(xqp_short aShort){
    return boost::lexical_cast<std::string>(aShort);
  }
  bool NumConversions::strToUShort(const xqpString& aStr, xqp_ushort& aUShort){
    try {
      aUShort = boost::lexical_cast<xqp_short>(aStr.c_str());
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ushortToStr(xqp_ushort aUShort){
    return boost::lexical_cast<std::string>(aUShort);
  }
  bool NumConversions::starCharToDecimal(const char* aStarChar, xqp_decimal& aDecimal){
    try {
      aDecimal = boost::lexical_cast<xqp_decimal>(aStarChar);
      return true;
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  bool NumConversions::strToDecimal(const xqpString& aStr, xqp_decimal& aDecimal) {
    return starCharToDecimal(aStr.c_str(), aDecimal);
  }
  xqpString NumConversions::decimalToStr(xqp_decimal aDecimal){
    return boost::lexical_cast<std::string>(aDecimal);
  }
  bool NumConversions::starCharToFloat(const char* aCharStar, xqp_float& aFloat) {
    char* lEndPtr;
     aFloat = (xqp_float)strtod(aCharStar, &lEndPtr);//daniel: changed from strtof to compile on Windows
    if (*lEndPtr != '\0')
      return false;
    else
      return true;

  }
  bool NumConversions::strToFloat(const xqpString& aStr, xqp_float& aFloat){
    return NumConversions::starCharToFloat(aStr.c_str(), aFloat);
  }
  xqpString NumConversions::floatToStr(xqp_float aFloat){
    if (aFloat == std::numeric_limits<float>::infinity())
      return "INF";
    else if (aFloat == -std::numeric_limits<float>::infinity())
      return "-INF";
    else if (aFloat != aFloat)
      return "NaN";
    else {
      std::stringstream lStream;
      lStream << aFloat;
      return lStream.str();
    }
  }
  bool NumConversions::starCharToDouble(const char* aStarChar, xqp_double& aDouble){
    char* lEndPtr;
    aDouble = strtod(aStarChar, &lEndPtr);
    if (*lEndPtr != '\0')
      return false;
    else
      return true;
  }
  bool NumConversions::strToDouble(const xqpString& aStr, xqp_double& aDouble) {
    return starCharToDouble(aStr.c_str(), aDouble);
  }
  xqpString NumConversions::doubleToStr(xqp_double aDouble){
    if (aDouble == std::numeric_limits<double>::infinity())
      return "INF";
    else if (aDouble == -std::numeric_limits<double>::infinity())
      return "-INF";
    else if (aDouble != aDouble)
      return "NaN";
    else {
      std::stringstream lStream;
      lStream << aDouble;
      return lStream.str();
    }
  }
  bool NumConversions::strToByte(const xqpString& aStr, xqp_byte& aByte){
    try {
      xqp_int lInt = boost::lexical_cast<xqp_int>(aStr.c_str());
      if (lInt >= -128 && lInt <= 127) {
        aByte = lInt;
        return true;
      } else {
        return false;
      }
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::byteToStr(xqp_byte aByte){
    xqp_int lInt = aByte;
    return boost::lexical_cast<std::string>(lInt);
  }
  bool NumConversions::strToUByte(const xqpString& aStr, xqp_ubyte& aUByte){
    try {
      xqp_uint lUInt = boost::lexical_cast<xqp_uint>(aStr.c_str());
      if (lUInt >= 0 && lUInt <= 255) {
        aUByte = lUInt;
        return true;
      } else {
        return false;
      }
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
  }
  xqpString NumConversions::ubyteToStr(xqp_ubyte aUByte){
    xqp_uint lUInt = aUByte;
    return boost::lexical_cast<std::string>(lUInt);
  }
} /* namespace xqp */
<|endoftext|>


<commit_before>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <ossim/util/ossimSlopeUtil.h>
#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimPreferences.h>
#include <ossim/base/ossimGrect.h>
#include <ossim/base/ossimIrect.h>
#include <ossim/base/ossimException.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/elevation/ossimElevManager.h>
#include <ossim/projection/ossimEquDistCylProjection.h>
#include <ossim/projection/ossimImageViewProjectionTransform.h>
#include <ossim/imaging/ossimSlopeFilter.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
#include <ossim/imaging/ossimTiffWriter.h>
#include <ossim/imaging/ossimIndexToRgbLutFilter.h>
#include <ossim/imaging/ossimScalarRemapper.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/imaging/ossimImageRenderer.h>
#include <ossim/imaging/ossimImageMosaic.h>
#include <iostream>

using namespace std;

static const std::string IMAGE_SOURCE_KW = "image_source";
static const std::string ELEV_SOURCE_KW  = "elev_source";
const char* ossimSlopeUtil::DESCRIPTION  =
      "Utility for computing the slope at each elevation post and generating "
      "a corresponding slope image.";

ossimSlopeUtil::ossimSlopeUtil()
: m_recursiveCall (false)
{
}

ossimSlopeUtil::~ossimSlopeUtil()
{
}

void ossimSlopeUtil::setUsage(ossimArgumentParser& ap)
{
   // Add options.
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " [options] <output-image>";
   au->setCommandLineUsage(usageString);

   // Set the command line options:
<<<<<<< HEAD
   au->addCommandLineOption(
         "--center <lat> <lon>",
         "The center position of the output product. Required if no input DEM is specified.");
   au->addCommandLineOption(
         "--dem <filename>",
         "Specifies the input DEM filename. If none provided, the elevation database is referenced "
         "as specified in prefs file for the center and ROI specified.");
   au->addCommandLineOption(
         "--remap",
         "The range of slope angle (0.0 to 90.0) is remapped to 0-255 (one byte/pixel)");
   au->addCommandLineOption(
         "--lut <filename>",
         "Specifies the optional lookup table filename for mapping the single-band output "
         "image to an RGB. The LUT provided must be in the ossimIndexToRgbLutFilter format "
         "and should accommodate the output pixel range. This option forces remap to 8-bit, "
         "0-255 where 255 = 90 deg slope");
   au->addCommandLineOption(
         "--roi <meters>",
         "radius of interest surrounding the center point. If absent, the product defaults to "
         "1024 x 1024 pixels, with a radius of 512 * GSD. Alternatively, if a DEM file is "
         "specified, the product ROI defaults to the full DEM coverage.");

   ossimString description =
         "Utility for computing the slope at each elevation post and generating "
         "a corresponding slope image. The output scalar type is a normalized float with 1.0 = 90 "
         "degree angle from the local vertical. Optional 8-bit scalar type is available."
         "Examples:\n\n"
         "    ossim-slope [options] --dem <input-dem> <output-slope-image-file>\n"
         "    ossim-slope [options] --center <lat> <lon> --roi <meters> <output-slope-image-file>\n";
   au->setDescription(description);
=======
   au->setDescription(DESCRIPTION);
>>>>>>> dev

   // Base class has its own:
   ossimChipProcUtil::setUsage(ap);
}

bool ossimSlopeUtil::initialize(ossimArgumentParser& ap)
{
   if (!ossimChipProcUtil::initialize(ap))
      return false;

   processRemainingArgs(ap);
   return true;
}

void ossimSlopeUtil::initialize(const ossimKeywordlist& kwl)
{
   // This method
   clear();

   // Base class does the heavy work:
   ossimChipProcUtil::initialize(kwl);
}

void ossimSlopeUtil::initProcessingChain()
{
   ostringstream key;

   // Reinitialization needs to skip this method if called recursively:
   if (m_recursiveCall)
      return;

   // Need to establish list of DEM cells given either the bounding rect or explicit DEM cells:
   if (m_demSources.empty())
   {
      // Query elevation manager for cells providing needed coverage:
      std::vector<ossimFilename> cells;
      ossimElevManager::instance()->getCellsForBounds(m_aoiGroundRect, cells);

      // Insert the list of DEM cells into the KWL as input images:
      ossimConnectableObject::ConnectableObjectList elevChains;
      for(ossim_uint32 idx=0; idx<cells.size(); ++idx)
      {
         // Add the DEM as an image source to the KWL:
         ostringstream key;
         key<<IMAGE_SOURCE_KW<<ossimString::toString(idx)<<"."<<ossimKeywordNames::FILE_KW;
         m_kwl.addPair(key.str(), cells[idx].string() );
      }
   }
   else
   {
      // DEMs explicitly listed in keywordlist, use these:
      for(ossim_uint32 idx=0; idx<m_demSources.size(); ++idx)
      {
         // Add the DEM as an image source to the KWL:
         ostringstream key;
         key<<IMAGE_SOURCE_KW<<ossimString::toString(idx)<<"."<<ossimKeywordNames::FILE_KW;
         m_kwl.addPair(key.str(), m_demSources[idx].string() );
      }
   }

   // Remove any occurence of elev_source in the KWL:
   ossimString regex = ELEV_SOURCE_KW + ".*";
   m_kwl.removeKeysThatMatch(regex);

   // Reinitialize the object with the DEMs listed as input images and create a mosaic of them:
   m_recursiveCall = true;
   initialize(m_kwl);
   m_recursiveCall = false;
   ossimRefPtr<ossimImageSource> combiner = combineLayers(m_imgLayers);
   m_procChain->add(combiner.get());

   // Finally add the slope filter:
   ossimRefPtr<ossimSlopeFilter> slope_filter = new ossimSlopeFilter;
   slope_filter->setSlopeType(ossimSlopeFilter::NORMALIZED);
   m_procChain->add(slope_filter.get());

   finalizeChain();
}

<commit_msg>Merging the fix from dev into master ther was a merge conflict<commit_after>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <ossim/util/ossimSlopeUtil.h>
#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimPreferences.h>
#include <ossim/base/ossimGrect.h>
#include <ossim/base/ossimIrect.h>
#include <ossim/base/ossimException.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/elevation/ossimElevManager.h>
#include <ossim/projection/ossimEquDistCylProjection.h>
#include <ossim/projection/ossimImageViewProjectionTransform.h>
#include <ossim/imaging/ossimSlopeFilter.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
#include <ossim/imaging/ossimTiffWriter.h>
#include <ossim/imaging/ossimIndexToRgbLutFilter.h>
#include <ossim/imaging/ossimScalarRemapper.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/imaging/ossimImageRenderer.h>
#include <ossim/imaging/ossimImageMosaic.h>
#include <iostream>

using namespace std;

static const std::string IMAGE_SOURCE_KW = "image_source";
static const std::string ELEV_SOURCE_KW  = "elev_source";
const char* ossimSlopeUtil::DESCRIPTION  =
      "Utility for computing the slope at each elevation post and generating "
      "a corresponding slope image.";

ossimSlopeUtil::ossimSlopeUtil()
: m_recursiveCall (false)
{
}

ossimSlopeUtil::~ossimSlopeUtil()
{
}

void ossimSlopeUtil::setUsage(ossimArgumentParser& ap)
{
   // Add options.
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " [options] <output-image>";
   au->setCommandLineUsage(usageString);

   // Set the command line options:
   au->setDescription(DESCRIPTION);

   // Base class has its own:
   ossimChipProcUtil::setUsage(ap);
}

bool ossimSlopeUtil::initialize(ossimArgumentParser& ap)
{
   if (!ossimChipProcUtil::initialize(ap))
      return false;

   processRemainingArgs(ap);
   return true;
}

void ossimSlopeUtil::initialize(const ossimKeywordlist& kwl)
{
   // This method
   clear();

   // Base class does the heavy work:
   ossimChipProcUtil::initialize(kwl);
}

void ossimSlopeUtil::initProcessingChain()
{
   ostringstream key;

   // Reinitialization needs to skip this method if called recursively:
   if (m_recursiveCall)
      return;

   // Need to establish list of DEM cells given either the bounding rect or explicit DEM cells:
   if (m_demSources.empty())
   {
      // Query elevation manager for cells providing needed coverage:
      std::vector<ossimFilename> cells;
      ossimElevManager::instance()->getCellsForBounds(m_aoiGroundRect, cells);

      // Insert the list of DEM cells into the KWL as input images:
      ossimConnectableObject::ConnectableObjectList elevChains;
      for(ossim_uint32 idx=0; idx<cells.size(); ++idx)
      {
         // Add the DEM as an image source to the KWL:
         ostringstream key;
         key<<IMAGE_SOURCE_KW<<ossimString::toString(idx)<<"."<<ossimKeywordNames::FILE_KW;
         m_kwl.addPair(key.str(), cells[idx].string() );
      }
   }
   else
   {
      // DEMs explicitly listed in keywordlist, use these:
      for(ossim_uint32 idx=0; idx<m_demSources.size(); ++idx)
      {
         // Add the DEM as an image source to the KWL:
         ostringstream key;
         key<<IMAGE_SOURCE_KW<<ossimString::toString(idx)<<"."<<ossimKeywordNames::FILE_KW;
         m_kwl.addPair(key.str(), m_demSources[idx].string() );
      }
   }

   // Remove any occurence of elev_source in the KWL:
   ossimString regex = ELEV_SOURCE_KW + ".*";
   m_kwl.removeKeysThatMatch(regex);

   // Reinitialize the object with the DEMs listed as input images and create a mosaic of them:
   m_recursiveCall = true;
   initialize(m_kwl);
   m_recursiveCall = false;
   ossimRefPtr<ossimImageSource> combiner = combineLayers(m_imgLayers);
   m_procChain->add(combiner.get());

   // Finally add the slope filter:
   ossimRefPtr<ossimSlopeFilter> slope_filter = new ossimSlopeFilter;
   slope_filter->setSlopeType(ossimSlopeFilter::NORMALIZED);
   m_procChain->add(slope_filter.get());

   finalizeChain();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MasterPropertySetInfo.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-08 15:49:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _COMPHELPER_CHAINABLEPROPERTYSETINFO_HXX_
#include <comphelper/MasterPropertySetInfo.hxx>
#endif
#ifndef _COMPHELPER_TYPEGENERATION_HXX_
#include <comphelper/TypeGeneration.hxx>
#endif

using ::rtl::OUString;
using ::comphelper::PropertyInfo;
using ::comphelper::GenerateCppuType;
using ::comphelper::MasterPropertySetInfo;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Type;
using ::com::sun::star::uno::XWeak;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::beans::Property;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::beans::UnknownPropertyException;

MasterPropertySetInfo::MasterPropertySetInfo()
    throw()
{
}

MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo* pMap )
    throw()
{
    add ( pMap );
}

MasterPropertySetInfo::~MasterPropertySetInfo()
    throw()
{
    PropertyDataHash::iterator aEnd = maMap.end(), aIter = maMap.begin();
    while (aIter != aEnd )
    {
        delete (*aIter).second;
        aIter++;
    }
}

//XInterface
Any SAL_CALL MasterPropertySetInfo::queryInterface( const Type& rType )
    throw(RuntimeException)
{
    return ::cppu::queryInterface ( rType                                       ,
                                    // OWeakObject interfaces
                                    reinterpret_cast< XInterface*       > ( this )  ,
                                    static_cast < XWeak*                > ( this )  ,
                                    // my own interfaces
                                    static_cast < XPropertySetInfo*     > ( this ) );
}

void SAL_CALL MasterPropertySetInfo::acquire(  )
    throw()
{
    OWeakObject::acquire();
}
void SAL_CALL MasterPropertySetInfo::release(  )
    throw()
{
    OWeakObject::release();
}

void MasterPropertySetInfo::add( PropertyInfo* pMap, sal_Int32 nCount, sal_uInt8 nMapId )
    throw()
{
    // nCount < 0   => add all
    // nCount == 0  => add nothing
    // nCount > 0   => add at most nCount entries
    if( maProperties.getLength() )
        maProperties.realloc( 0 );

    for ( ; pMap->mpName && ( ( nCount < 0 ) || ( nCount > 0 ) ); --nCount, ++pMap )
    {
        OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );

#ifndef PRODUCT
        PropertyDataHash::iterator aIter = maMap.find( aName );
        if( aIter != maMap.end() )
            OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
#endif
        maMap[aName] = new PropertyData ( nMapId, pMap );
    }
}

void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId )
    throw()
{
    if( maProperties.getLength() )
        maProperties.realloc( 0 );
    PropertyInfoHash::iterator aIter = rHash.begin(), aEnd = rHash.end();

    while ( aIter != aEnd )
    {
#ifndef PRODUCT
        PropertyDataHash::iterator aDebugIter = maMap.find( (*aIter).first );
        if( aDebugIter != maMap.end() )
            OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
#endif
        maMap[(*aIter).first] = new PropertyData ( nMapId, (*aIter).second );
        aIter++;
    }
}

void MasterPropertySetInfo::remove( const rtl::OUString& aName )
    throw()
{
    maMap.erase ( aName );
    if ( maProperties.getLength() )
         maProperties.realloc( 0 );
}

Sequence< ::Property > SAL_CALL MasterPropertySetInfo::getProperties()
    throw(::com::sun::star::uno::RuntimeException)
{
    sal_Int32 nSize = maMap.size();
    if( maProperties.getLength() != nSize )
    {
        maProperties.realloc ( nSize );
        Property* pProperties = maProperties.getArray();

        PropertyDataHash::iterator aIter = maMap.begin();
        const PropertyDataHash::iterator aEnd = maMap.end();
        for ( ; aIter != aEnd; ++aIter, ++pProperties)
        {
            PropertyInfo* pInfo = (*aIter).second->mpInfo;

            pProperties->Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
            pProperties->Handle = pInfo->mnHandle;
            const Type* pType;
            GenerateCppuType ( pInfo->meCppuType, pType);
            pProperties->Type = *pType;
            pProperties->Attributes = pInfo->mnAttributes;
        }
    }
    return maProperties;
}

Property SAL_CALL MasterPropertySetInfo::getPropertyByName( const ::rtl::OUString& rName )
    throw(::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
{
    PropertyDataHash::iterator aIter = maMap.find( rName );

    if ( maMap.end() == aIter )
        throw UnknownPropertyException();

    PropertyInfo *pInfo = (*aIter).second->mpInfo;
    Property aProperty;
    aProperty.Name   = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
    aProperty.Handle = pInfo->mnHandle;
    const Type* pType;
    GenerateCppuType ( pInfo->meCppuType, pType );
    aProperty.Type = *pType;

    aProperty.Attributes = pInfo->mnAttributes;
    return aProperty;
}

sal_Bool SAL_CALL MasterPropertySetInfo::hasPropertyByName( const ::rtl::OUString& rName )
    throw(::com::sun::star::uno::RuntimeException)
{
    return static_cast < sal_Bool > ( maMap.find ( rName ) != maMap.end() );
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.118); FILE MERGED 2005/09/05 15:24:08 rt 1.3.118.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MasterPropertySetInfo.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 02:56:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _COMPHELPER_CHAINABLEPROPERTYSETINFO_HXX_
#include <comphelper/MasterPropertySetInfo.hxx>
#endif
#ifndef _COMPHELPER_TYPEGENERATION_HXX_
#include <comphelper/TypeGeneration.hxx>
#endif

using ::rtl::OUString;
using ::comphelper::PropertyInfo;
using ::comphelper::GenerateCppuType;
using ::comphelper::MasterPropertySetInfo;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Type;
using ::com::sun::star::uno::XWeak;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::beans::Property;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::beans::UnknownPropertyException;

MasterPropertySetInfo::MasterPropertySetInfo()
    throw()
{
}

MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo* pMap )
    throw()
{
    add ( pMap );
}

MasterPropertySetInfo::~MasterPropertySetInfo()
    throw()
{
    PropertyDataHash::iterator aEnd = maMap.end(), aIter = maMap.begin();
    while (aIter != aEnd )
    {
        delete (*aIter).second;
        aIter++;
    }
}

//XInterface
Any SAL_CALL MasterPropertySetInfo::queryInterface( const Type& rType )
    throw(RuntimeException)
{
    return ::cppu::queryInterface ( rType                                       ,
                                    // OWeakObject interfaces
                                    reinterpret_cast< XInterface*       > ( this )  ,
                                    static_cast < XWeak*                > ( this )  ,
                                    // my own interfaces
                                    static_cast < XPropertySetInfo*     > ( this ) );
}

void SAL_CALL MasterPropertySetInfo::acquire(  )
    throw()
{
    OWeakObject::acquire();
}
void SAL_CALL MasterPropertySetInfo::release(  )
    throw()
{
    OWeakObject::release();
}

void MasterPropertySetInfo::add( PropertyInfo* pMap, sal_Int32 nCount, sal_uInt8 nMapId )
    throw()
{
    // nCount < 0   => add all
    // nCount == 0  => add nothing
    // nCount > 0   => add at most nCount entries
    if( maProperties.getLength() )
        maProperties.realloc( 0 );

    for ( ; pMap->mpName && ( ( nCount < 0 ) || ( nCount > 0 ) ); --nCount, ++pMap )
    {
        OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );

#ifndef PRODUCT
        PropertyDataHash::iterator aIter = maMap.find( aName );
        if( aIter != maMap.end() )
            OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
#endif
        maMap[aName] = new PropertyData ( nMapId, pMap );
    }
}

void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId )
    throw()
{
    if( maProperties.getLength() )
        maProperties.realloc( 0 );
    PropertyInfoHash::iterator aIter = rHash.begin(), aEnd = rHash.end();

    while ( aIter != aEnd )
    {
#ifndef PRODUCT
        PropertyDataHash::iterator aDebugIter = maMap.find( (*aIter).first );
        if( aDebugIter != maMap.end() )
            OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
#endif
        maMap[(*aIter).first] = new PropertyData ( nMapId, (*aIter).second );
        aIter++;
    }
}

void MasterPropertySetInfo::remove( const rtl::OUString& aName )
    throw()
{
    maMap.erase ( aName );
    if ( maProperties.getLength() )
         maProperties.realloc( 0 );
}

Sequence< ::Property > SAL_CALL MasterPropertySetInfo::getProperties()
    throw(::com::sun::star::uno::RuntimeException)
{
    sal_Int32 nSize = maMap.size();
    if( maProperties.getLength() != nSize )
    {
        maProperties.realloc ( nSize );
        Property* pProperties = maProperties.getArray();

        PropertyDataHash::iterator aIter = maMap.begin();
        const PropertyDataHash::iterator aEnd = maMap.end();
        for ( ; aIter != aEnd; ++aIter, ++pProperties)
        {
            PropertyInfo* pInfo = (*aIter).second->mpInfo;

            pProperties->Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
            pProperties->Handle = pInfo->mnHandle;
            const Type* pType;
            GenerateCppuType ( pInfo->meCppuType, pType);
            pProperties->Type = *pType;
            pProperties->Attributes = pInfo->mnAttributes;
        }
    }
    return maProperties;
}

Property SAL_CALL MasterPropertySetInfo::getPropertyByName( const ::rtl::OUString& rName )
    throw(::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
{
    PropertyDataHash::iterator aIter = maMap.find( rName );

    if ( maMap.end() == aIter )
        throw UnknownPropertyException();

    PropertyInfo *pInfo = (*aIter).second->mpInfo;
    Property aProperty;
    aProperty.Name   = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
    aProperty.Handle = pInfo->mnHandle;
    const Type* pType;
    GenerateCppuType ( pInfo->meCppuType, pType );
    aProperty.Type = *pType;

    aProperty.Attributes = pInfo->mnAttributes;
    return aProperty;
}

sal_Bool SAL_CALL MasterPropertySetInfo::hasPropertyByName( const ::rtl::OUString& rName )
    throw(::com::sun::star::uno::RuntimeException)
{
    return static_cast < sal_Bool > ( maMap.find ( rName ) != maMap.end() );
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "LDAPErrorHandler.h"

//--- standard modules used ----------------------------------------------------
#include "Dbg.h"
#include "SystemLog.h"
#include "StringStream.h"
#include "TimeStamp.h"

//--- c-modules used -----------------------------------------------------------

//---- LDAPErrorHandler ----------------------------------------------------------------

LDAPErrorHandler::LDAPErrorHandler(Context &ctx, ParameterMapper *in, ResultMapper *out, String daName)
	: fCtx(ctx), fIn(in), fOut(out), fName(daName), fRetryState(eNoRetry)
{}

LDAPErrorHandler::~LDAPErrorHandler()
{
	fCtx.GetTmpStore().Remove("LDAPConnectionParams");
	fCtx.GetTmpStore().Remove("LDAPQueryParams");
}

void LDAPErrorHandler::HandleSessionError(LDAP *handle, String msg)
{
	StartTrace(LDAPErrorHandler.HandleSessionError);

	Anything error;
	error["Msg"] = msg;
	if (handle) {
		int rc;
		ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &rc);
		error["LdapCode"] = rc;
		error["LdapMsg"] = ldap_err2string(rc);
	} else {
		if ( fRetryState == eNoRetry ) {
			error["LdapMsg"] = "Connection does not exist (no handle available).";
		} else {
			error["LdapMsg"] = "Connection failure using LDAPPooledConnections.";
		}
	}

	// get connection parameters + append
	error["LdapConnectionParams"] = GetConnectionParams().DeepClone();

	String msgAsString = WriteSysLog(error, msg);
	error["MsgAsString"] = msgAsString;
	WriteError(error);
}

void LDAPErrorHandler::HandleUnbindError(LDAP *handle)
{
	StartTrace(LDAPErrorHandler.HandleUnbindError);

	int rc;
	String msg;
	msg << TimeStamp::Now().AsStringWithZ();
	if ( handle ) {
		ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &rc);
		String msg;
		msg << " LdapCode: [" << rc << "] LdapMsg: [" << ldap_err2string(rc) << "] ldap_unbind";
	} else {
		msg << " LdapCode: [no valid handle] LdapMsg: [no valid handle] ldap_unbind";
	}
	SystemLog::Error(msg);
	Trace(msg);
}

void LDAPErrorHandler::HandleError(String msg, Anything args, String argDescr)
{
	StartTrace(LDAPErrorHandler.HandleError);

	Anything error;
	error["Msg"] = msg;
	if ( !args.IsNull() ) {
		error[argDescr] = args;
	}

	// get query parameters + append
	error["LdapQueryParams"] = GetQueryParams().DeepClone();

	String msgAsString = WriteSysLog(error, msg);
	error["MsgAsString"] = msgAsString;
	WriteError(error);
}

String LDAPErrorHandler::WriteSysLog(Anything error, String &msg)
{
	Anything anyOldPWD;
	if ( error.LookupPath(anyOldPWD, "LdapConnectionParams.BindPW") ) {
		error["LdapConnectionParams"]["BindPW"] = "WipedOut";
	}
	String sSysLog;
	OStringStream ossSysLog(&sSysLog);
	error.PrintOn(ossSysLog, false);
	ossSysLog.flush();
	// log all ldap session errors in SystemLog
	SystemLog::Error(TimeStamp::Now().AsStringWithZ() << " " <<  msg << " " << fName << " " << sSysLog);
	String msgAsString;
	msgAsString << "LdapDataAccess: [" << fName << "]";
	for ( long l = 0; l < error.GetSize(); ++l ) {
		if ( error[l].GetType() == AnyArrayType ) {
			String sMsgDetails;
			OStringStream ossMsgDetails(&sMsgDetails);
			error[l].PrintOn(ossMsgDetails, false);
			ossMsgDetails.flush();
			msgAsString << " " << error.SlotName(l) << " [" <<	sMsgDetails << "]";
		} else {
			msgAsString << " " << error.SlotName(l) << " [" << error[l].AsString() << "]";
		}
	}
	// Restore password
	if ( !anyOldPWD.IsNull() ) {
		error["LdapConnectionParams"]["BindPW"] = anyOldPWD.AsCharPtr();
	}
	return msgAsString;
}

void LDAPErrorHandler::WriteError(Anything &error)
{
	StartTrace(LDAPErrorHandler.WriteError);
	String key("LDAPError.");
	key << fName;
	Trace("WriteKey: " << key);
	TraceAny(error, "Error content:");
	fOut->Put(key, error, fCtx);
}

bool LDAPErrorHandler::GetError(Anything &error)
{
	StartTrace(LDAPErrorHandler.GetError);
	String key;
	key << "LDAPError." << fName;
	Trace("ReadKey: " << key);
	return fIn->Get(key, error, fCtx);
}

void LDAPErrorHandler::CleanUp()
{
	StartTrace(LDAPErrorHandler.CleanUp);
	Anything tmp = fCtx.GetTmpStore();
	tmp["LDAPError"].Remove(fName);
	if ( tmp["LDAPError"].GetSize() == 0L ) {
		tmp.Remove("LDAPError");
	}
	tmp["LDAPResult"].Remove(fName);
	if ( tmp["LDAPResult"].GetSize() == 0L ) {
		tmp.Remove("LDAPResult");
	}
}

ROAnything LDAPErrorHandler::GetQueryParams()
{
	return (ROAnything)fQueryParams;
}

void LDAPErrorHandler::PutQueryParams(Anything qp)
{
	fQueryParams = qp;
}

ROAnything LDAPErrorHandler::GetConnectionParams()
{
	return (ROAnything)fConnectionParams;
}

void LDAPErrorHandler::PutConnectionParams(Anything cp)
{
	fConnectionParams = cp;
}

void LDAPErrorHandler::SetRetryState(eRetryState retryState)
{
	StartTrace(LDAPErrorHandler.SetRetryState);
	Trace("Setting: [" << RetryStateAsString(retryState) << "]");
	fRetryState = retryState;
}

void LDAPErrorHandler::SetShouldRetry()
{
	StartTrace(LDAPErrorHandler.SetShouldRetry);
	String msg;
	if (!IsRetry()) {
		fRetryState = LDAPErrorHandler::eRetry;
		msg << "Setting retry state: [" << RetryStateAsString(fRetryState) << "]";
	} else {
		msg << "Retry already attempted. Not setting retry state: [" << RetryStateAsString(fRetryState) << "]";
	}
	SystemLog::Info(msg);
}

LDAPErrorHandler::eRetryState LDAPErrorHandler::GetRetryState()
{
	StartTrace(LDAPErrorHandler.GetRetryState);
	Trace("Getting: [" << RetryStateAsString(fRetryState) << "]");
	return fRetryState;
}

bool LDAPErrorHandler::IsRetry()
{
	StartTrace(LDAPErrorHandler.IsRetry);
	bool ret =	(fRetryState == LDAPErrorHandler::eIsInRetrySequence);
	Trace("IsRetry: " << ret);
	return ret;
}

String LDAPErrorHandler::RetryStateAsString(eRetryState retryState)
{
	switch ( retryState) {
		case eRetry:
			return "eRetry";
			break;
		case eIsInRetrySequence:
			return "eIsInRetrySequence";
			break;
		case eNoRetry:
			return "eNoRetry";
			break;
		default:
			return "Unknown!";
			break;
	}
}
<commit_msg>fixed compiler warnings<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "LDAPErrorHandler.h"

//--- standard modules used ----------------------------------------------------
#include "Dbg.h"
#include "SystemLog.h"
#include "StringStream.h"
#include "TimeStamp.h"

//--- c-modules used -----------------------------------------------------------

//---- LDAPErrorHandler ----------------------------------------------------------------

LDAPErrorHandler::LDAPErrorHandler(Context &ctx, ParameterMapper *in, ResultMapper *out, String daName)
	: fCtx(ctx), fIn(in), fOut(out), fName(daName), fRetryState(eNoRetry)
{}

LDAPErrorHandler::~LDAPErrorHandler()
{
	fCtx.GetTmpStore().Remove("LDAPConnectionParams");
	fCtx.GetTmpStore().Remove("LDAPQueryParams");
}

void LDAPErrorHandler::HandleSessionError(LDAP *handle, String msg)
{
	StartTrace(LDAPErrorHandler.HandleSessionError);

	Anything error;
	error["Msg"] = msg;
	if (handle) {
		int rc;
		ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &rc);
		error["LdapCode"] = rc;
		error["LdapMsg"] = ldap_err2string(rc);
	} else {
		if ( fRetryState == eNoRetry ) {
			error["LdapMsg"] = "Connection does not exist (no handle available).";
		} else {
			error["LdapMsg"] = "Connection failure using LDAPPooledConnections.";
		}
	}

	// get connection parameters + append
	error["LdapConnectionParams"] = GetConnectionParams().DeepClone();

	String msgAsString = WriteSysLog(error, msg);
	error["MsgAsString"] = msgAsString;
	WriteError(error);
}

void LDAPErrorHandler::HandleUnbindError(LDAP *handle)
{
	StartTrace(LDAPErrorHandler.HandleUnbindError);

	int rc;
	String msg;
	msg << TimeStamp::Now().AsStringWithZ();
	if ( handle ) {
		ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &rc);
		msg << " LdapCode: [" << rc << "] LdapMsg: [" << ldap_err2string(rc) << "] ldap_unbind";
	} else {
		msg << " LdapCode: [no valid handle] LdapMsg: [no valid handle] ldap_unbind";
	}
	SystemLog::Error(msg);
	Trace(msg);
}

void LDAPErrorHandler::HandleError(String msg, Anything args, String argDescr)
{
	StartTrace(LDAPErrorHandler.HandleError);

	Anything error;
	error["Msg"] = msg;
	if ( !args.IsNull() ) {
		error[argDescr] = args;
	}

	// get query parameters + append
	error["LdapQueryParams"] = GetQueryParams().DeepClone();

	String msgAsString = WriteSysLog(error, msg);
	error["MsgAsString"] = msgAsString;
	WriteError(error);
}

String LDAPErrorHandler::WriteSysLog(Anything error, String &msg)
{
	Anything anyOldPWD;
	if ( error.LookupPath(anyOldPWD, "LdapConnectionParams.BindPW") ) {
		error["LdapConnectionParams"]["BindPW"] = "WipedOut";
	}
	String sSysLog;
	OStringStream ossSysLog(&sSysLog);
	error.PrintOn(ossSysLog, false);
	ossSysLog.flush();
	// log all ldap session errors in SystemLog
	SystemLog::Error(TimeStamp::Now().AsStringWithZ() << " " <<  msg << " " << fName << " " << sSysLog);
	String msgAsString;
	msgAsString << "LdapDataAccess: [" << fName << "]";
	for ( long l = 0; l < error.GetSize(); ++l ) {
		if ( error[l].GetType() == AnyArrayType ) {
			String sMsgDetails;
			OStringStream ossMsgDetails(&sMsgDetails);
			error[l].PrintOn(ossMsgDetails, false);
			ossMsgDetails.flush();
			msgAsString << " " << error.SlotName(l) << " [" <<	sMsgDetails << "]";
		} else {
			msgAsString << " " << error.SlotName(l) << " [" << error[l].AsString() << "]";
		}
	}
	// Restore password
	if ( !anyOldPWD.IsNull() ) {
		error["LdapConnectionParams"]["BindPW"] = anyOldPWD.AsCharPtr();
	}
	return msgAsString;
}

void LDAPErrorHandler::WriteError(Anything &error)
{
	StartTrace(LDAPErrorHandler.WriteError);
	String key("LDAPError.");
	key << fName;
	Trace("WriteKey: " << key);
	TraceAny(error, "Error content:");
	fOut->Put(key, error, fCtx);
}

bool LDAPErrorHandler::GetError(Anything &error)
{
	StartTrace(LDAPErrorHandler.GetError);
	String key;
	key << "LDAPError." << fName;
	Trace("ReadKey: " << key);
	return fIn->Get(key, error, fCtx);
}

void LDAPErrorHandler::CleanUp()
{
	StartTrace(LDAPErrorHandler.CleanUp);
	Anything tmp = fCtx.GetTmpStore();
	tmp["LDAPError"].Remove(fName);
	if ( tmp["LDAPError"].GetSize() == 0L ) {
		tmp.Remove("LDAPError");
	}
	tmp["LDAPResult"].Remove(fName);
	if ( tmp["LDAPResult"].GetSize() == 0L ) {
		tmp.Remove("LDAPResult");
	}
}

ROAnything LDAPErrorHandler::GetQueryParams()
{
	return (ROAnything)fQueryParams;
}

void LDAPErrorHandler::PutQueryParams(Anything qp)
{
	fQueryParams = qp;
}

ROAnything LDAPErrorHandler::GetConnectionParams()
{
	return (ROAnything)fConnectionParams;
}

void LDAPErrorHandler::PutConnectionParams(Anything cp)
{
	fConnectionParams = cp;
}

void LDAPErrorHandler::SetRetryState(eRetryState retryState)
{
	StartTrace(LDAPErrorHandler.SetRetryState);
	Trace("Setting: [" << RetryStateAsString(retryState) << "]");
	fRetryState = retryState;
}

void LDAPErrorHandler::SetShouldRetry()
{
	StartTrace(LDAPErrorHandler.SetShouldRetry);
	String msg;
	if (!IsRetry()) {
		fRetryState = LDAPErrorHandler::eRetry;
		msg << "Setting retry state: [" << RetryStateAsString(fRetryState) << "]";
	} else {
		msg << "Retry already attempted. Not setting retry state: [" << RetryStateAsString(fRetryState) << "]";
	}
	SystemLog::Info(msg);
}

LDAPErrorHandler::eRetryState LDAPErrorHandler::GetRetryState()
{
	StartTrace(LDAPErrorHandler.GetRetryState);
	Trace("Getting: [" << RetryStateAsString(fRetryState) << "]");
	return fRetryState;
}

bool LDAPErrorHandler::IsRetry()
{
	StartTrace(LDAPErrorHandler.IsRetry);
	bool ret =	(fRetryState == LDAPErrorHandler::eIsInRetrySequence);
	Trace("IsRetry: " << ret);
	return ret;
}

String LDAPErrorHandler::RetryStateAsString(eRetryState retryState)
{
	switch ( retryState) {
		case eRetry:
			return "eRetry";
			break;
		case eIsInRetrySequence:
			return "eIsInRetrySequence";
			break;
		case eNoRetry:
			return "eNoRetry";
			break;
		default:
			break;
	}
	return "Unknown!";
}
<|endoftext|>


<commit_before>// 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 <netlink/cache.h>
#include <netlink/errno.h>

#include <netlink/idiag/msg.h>

#include <stout/error.hpp>
#include <stout/try.hpp>

#include "linux/routing/internal.hpp"

#include "linux/routing/diagnosis/diagnosis.hpp"

using namespace std;

namespace routing {

template <>
inline void cleanup(struct idiagnl_msg* msg)
{
  idiagnl_msg_put(msg);
}

namespace diagnosis {
namespace socket {

static Option<net::IP> IP(nl_addr* _ip)
{
  Option<net::IP> result;
  if (_ip != nullptr && nl_addr_get_len(_ip) != 0) {
    struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(_ip);
    result = net::IP(*addr);
  }

  return result;
}

Try<vector<Info>> infos(int family, int states)
{
  Try<Netlink<struct nl_sock>> socket = routing::socket(NETLINK_INET_DIAG);
  if (socket.isError()) {
    return Error(socket.error());
  }

  struct nl_cache* c = nullptr;
  int error = idiagnl_msg_alloc_cache(socket.get().get(), family, states, &c);
  if (error != 0) {
    return Error(nl_geterror(error));
  }

  Netlink<struct nl_cache> cache(c);

  vector<Info> results;
  results.reserve(nl_cache_nitems(cache.get()));
  for (struct nl_object* o = nl_cache_get_first(cache.get());
       o != nullptr; o = nl_cache_get_next(o)) {
    struct idiagnl_msg* msg = (struct idiagnl_msg*)o;

    // For 'state', libnl-idiag only returns the number of left
    // shifts. Convert it back to power-of-2 number.

    results.emplace_back(
        idiagnl_msg_get_family(msg),
        1 << idiagnl_msg_get_state(msg),
        idiagnl_msg_get_inode(msg),
        idiagnl_msg_get_sport(msg),
        idiagnl_msg_get_dport(msg),
        IP(idiagnl_msg_get_src(msg)),
        IP(idiagnl_msg_get_dst(msg)),
        idiagnl_msg_get_tcpinfo(msg));
  }

  return results;
}

} // namespace socket {
} // namespace diagnosis {
} // namespace routing {
<commit_msg>Removed diagnostic socket IPv4 assumptions.<commit_after>// 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 <netlink/cache.h>
#include <netlink/errno.h>

#include <netlink/idiag/msg.h>

#include <stout/error.hpp>
#include <stout/try.hpp>

#include "linux/routing/internal.hpp"

#include "linux/routing/diagnosis/diagnosis.hpp"

using namespace std;

namespace routing {

template <>
inline void cleanup(struct idiagnl_msg* msg)
{
  idiagnl_msg_put(msg);
}

namespace diagnosis {
namespace socket {

static Option<net::IP> IP(nl_addr* _ip)
{
  if (_ip != nullptr && nl_addr_get_len(_ip) != 0) {
    if (nl_addr_get_family(_ip) == AF_INET) {
      struct in_addr* addr = (struct in_addr*)nl_addr_get_binary_addr(_ip);
      return net::IP(*addr);
    }

    if (nl_addr_get_family(_ip) == AF_INET6) {
      struct in6_addr* addr = (struct in6_addr*)nl_addr_get_binary_addr(_ip);
      return net::IP(*addr);
    }
  }

  return None();
}

Try<vector<Info>> infos(int family, int states)
{
  Try<Netlink<struct nl_sock>> socket = routing::socket(NETLINK_INET_DIAG);
  if (socket.isError()) {
    return Error(socket.error());
  }

  struct nl_cache* c = nullptr;
  int error = idiagnl_msg_alloc_cache(socket.get().get(), family, states, &c);
  if (error != 0) {
    return Error(nl_geterror(error));
  }

  Netlink<struct nl_cache> cache(c);

  vector<Info> results;
  results.reserve(nl_cache_nitems(cache.get()));
  for (struct nl_object* o = nl_cache_get_first(cache.get());
       o != nullptr; o = nl_cache_get_next(o)) {
    struct idiagnl_msg* msg = (struct idiagnl_msg*)o;

    // For 'state', libnl-idiag only returns the number of left
    // shifts. Convert it back to power-of-2 number.

    results.emplace_back(
        idiagnl_msg_get_family(msg),
        1 << idiagnl_msg_get_state(msg),
        idiagnl_msg_get_inode(msg),
        idiagnl_msg_get_sport(msg),
        idiagnl_msg_get_dport(msg),
        IP(idiagnl_msg_get_src(msg)),
        IP(idiagnl_msg_get_dst(msg)),
        idiagnl_msg_get_tcpinfo(msg));
  }

  return results;
}

} // namespace socket {
} // namespace diagnosis {
} // namespace routing {
<|endoftext|>


<commit_before>/*
 * 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 "DataOutputStream.h"
#include <activemq/util/Endian.h>
#include <activemq/util/Config.h>

using namespace activemq;
using namespace activemq::io;
using namespace activemq::util;

////////////////////////////////////////////////////////////////////////////////
DataOutputStream::DataOutputStream( OutputStream* outputStream, bool own )
 : FilterOutputStream( outputStream, own )
{
    // Init the written count
    written = 0;
}

////////////////////////////////////////////////////////////////////////////////
DataOutputStream::~DataOutputStream()
{
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char c ) throw ( IOException ) {
    try {
        outputStream->write( c );
        written++;
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const std::vector<unsigned char>& buffer )
    throw ( IOException ) {

    try {

        if( buffer.size() == 0 ){
            // nothing to write.
            return;
        }

        outputStream->write( &buffer[0], buffer.size() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char* buffer, std::size_t len )
    throw ( IOException ) {

    try {
        outputStream->write( buffer, len );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char* buffer,
                              std::size_t offset,
                              std::size_t len ) throw ( IOException )
{

    try {
        outputStream->write( buffer+offset, len );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeBoolean( bool value ) throw ( IOException ) {
    try {
        unsigned char ivalue = 0;
        value == true ? ivalue = 1 : ivalue = 0;

        this->write( ivalue );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeByte( unsigned char value ) throw ( IOException ) {
    try {
        this->write( value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeShort( short value ) throw ( IOException ) {
    try {
        this->writeUnsignedShort( (unsigned short)value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeUnsignedShort( unsigned short value )
    throw ( IOException )
{
    try {
        write( (unsigned char)( (value & 0xFF00) >> 8 ) );
        write( (unsigned char)( (value & 0x00FF) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeChar( char value ) throw ( IOException ) {
    try {
        write( value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeInt( int value ) throw ( IOException ) {
    try {
        this->write( (unsigned char)( (value & 0xFF000000) >> 24 ) );
        this->write( (unsigned char)( (value & 0x00FF0000) >> 16 ) );
        this->write( (unsigned char)( (value & 0x0000FF00) >> 8 ) );
        this->write( (unsigned char)( (value & 0x000000FF) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeLong( long long value ) throw ( IOException ) {
    try {
        this->write( (unsigned char)( (value & 0xFF00000000000000ULL) >> 56 ) );
        this->write( (unsigned char)( (value & 0x00FF000000000000ULL) >> 48 ) );
        this->write( (unsigned char)( (value & 0x0000FF0000000000ULL) >> 40 ) );
        this->write( (unsigned char)( (value & 0x000000FF00000000ULL) >> 32 ) );
        this->write( (unsigned char)( (value & 0x00000000FF000000ULL) >> 24 ) );
        this->write( (unsigned char)( (value & 0x0000000000FF0000ULL) >> 16 ) );
        this->write( (unsigned char)( (value & 0x000000000000FF00ULL) >> 8 ) );
        this->write( (unsigned char)( (value & 0x00000000000000FFULL) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeFloat( float value ) throw ( IOException ) {
    try {
        unsigned int lvalue = 0;
        memcpy( &lvalue, &value, sizeof( float ) );
        this->writeInt( lvalue );
        memcpy( &value, &lvalue, sizeof( unsigned int ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeDouble( double value ) throw ( IOException ) {
    try {
        unsigned long long lvalue = 0;
        memcpy( &lvalue, &value, sizeof( double ) );
        this->writeLong( lvalue );
        memcpy( &value, &lvalue, sizeof( unsigned long long ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeBytes( const std::string& value ) throw ( IOException ) {
    try {
        // do not add one so that we don't write the NULL
        this->write( (const unsigned char*)value.c_str(), value.length() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeChars( const std::string& value ) throw ( IOException ) {
    try {
        // add one so that we write the NULL
        this->write( (const unsigned char*)value.c_str(), value.length() + 1 );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeUTF( const std::string& value ) throw ( IOException ) {
    try {
        this->writeUnsignedShort( (unsigned short)value.length() );
        this->write( (const unsigned char*)value.c_str(), value.length() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}
<commit_msg>https://issues.apache.org/activemq/browse/AMQCPP-93<commit_after>/*
 * 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 "DataOutputStream.h"
#include <activemq/util/Endian.h>
#include <activemq/util/Config.h>

using namespace activemq;
using namespace activemq::io;
using namespace activemq::util;

////////////////////////////////////////////////////////////////////////////////
DataOutputStream::DataOutputStream( OutputStream* outputStream, bool own )
 : FilterOutputStream( outputStream, own )
{
    // Init the written count
    written = 0;
}

////////////////////////////////////////////////////////////////////////////////
DataOutputStream::~DataOutputStream()
{
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char c ) throw ( IOException ) {
    try {
        outputStream->write( c );
        written++;
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const std::vector<unsigned char>& buffer )
    throw ( IOException ) {

    try {

        if( buffer.size() == 0 ){
            // nothing to write.
            return;
        }

        outputStream->write( &buffer[0], buffer.size() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char* buffer, std::size_t len )
    throw ( IOException ) {

    try {
        outputStream->write( buffer, len );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::write( const unsigned char* buffer,
                              std::size_t offset,
                              std::size_t len ) throw ( IOException )
{

    try {
        outputStream->write( buffer+offset, len );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeBoolean( bool value ) throw ( IOException ) {
    try {
        unsigned char ivalue = 0;
        value == true ? ivalue = 1 : ivalue = 0;

        this->write( ivalue );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeByte( unsigned char value ) throw ( IOException ) {
    try {
        this->write( value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeShort( short value ) throw ( IOException ) {
    try {
        this->writeUnsignedShort( (unsigned short)value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeUnsignedShort( unsigned short value )
    throw ( IOException )
{
    try {
        write( (unsigned char)( (value & 0xFF00) >> 8 ) );
        write( (unsigned char)( (value & 0x00FF) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeChar( char value ) throw ( IOException ) {
    try {
        write( value );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeInt( int value ) throw ( IOException ) {
    try {
        this->write( (unsigned char)( (value & 0xFF000000) >> 24 ) );
        this->write( (unsigned char)( (value & 0x00FF0000) >> 16 ) );
        this->write( (unsigned char)( (value & 0x0000FF00) >> 8 ) );
        this->write( (unsigned char)( (value & 0x000000FF) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeLong( long long value ) throw ( IOException ) {
    try {
        this->write( (unsigned char)( (value & 0xFF00000000000000ULL) >> 56 ) );
        this->write( (unsigned char)( (value & 0x00FF000000000000ULL) >> 48 ) );
        this->write( (unsigned char)( (value & 0x0000FF0000000000ULL) >> 40 ) );
        this->write( (unsigned char)( (value & 0x000000FF00000000ULL) >> 32 ) );
        this->write( (unsigned char)( (value & 0x00000000FF000000ULL) >> 24 ) );
        this->write( (unsigned char)( (value & 0x0000000000FF0000ULL) >> 16 ) );
        this->write( (unsigned char)( (value & 0x000000000000FF00ULL) >> 8 ) );
        this->write( (unsigned char)( (value & 0x00000000000000FFULL) >> 0 ) );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeFloat( float value ) throw ( IOException ) {
    try {
        unsigned int lvalue = 0;
        memcpy( &lvalue, &value, sizeof( float ) );
        this->writeInt( lvalue );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeDouble( double value ) throw ( IOException ) {
    try {
        unsigned long long lvalue = 0;
        memcpy( &lvalue, &value, sizeof( double ) );
        this->writeLong( lvalue );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeBytes( const std::string& value ) throw ( IOException ) {
    try {
        // do not add one so that we don't write the NULL
        this->write( (const unsigned char*)value.c_str(), value.length() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeChars( const std::string& value ) throw ( IOException ) {
    try {
        // add one so that we write the NULL
        this->write( (const unsigned char*)value.c_str(), value.length() + 1 );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}

////////////////////////////////////////////////////////////////////////////////
void DataOutputStream::writeUTF( const std::string& value ) throw ( IOException ) {
    try {
        this->writeUnsignedShort( (unsigned short)value.length() );
        this->write( (const unsigned char*)value.c_str(), value.length() );
    }
    AMQ_CATCH_RETHROW( IOException )
    AMQ_CATCHALL_THROW( IOException )
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2014-2018 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "display.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/itilecallback.h"
#include "renderer/modeling/project/project.h"
#include "renderer/utility/plugin.h"
#include "renderer/utility/pluginstore.h"

// appleseed.foundation headers.
#include "foundation/platform/sharedlibrary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <memory>
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// Display class implementation.
//

namespace
{
    const UniqueID g_class_uid = new_guid();
}

struct Display::Impl
{
    unique_ptr<Plugin>                      m_plugin;
    auto_release_ptr<ITileCallbackFactory>  m_tile_callback_factory;
};

UniqueID Display::get_class_uid()
{
    return g_class_uid;
}

Display::Display(
    const char*         name,
    const ParamArray&   params)
  : Entity(g_class_uid, params)
  , impl(nullptr)
{
    set_name(name);
}

Display::~Display()
{
    close();
}

void Display::release()
{
    delete this;
}

bool Display::open(const Project& project)
{
    string plugin_path;

    // Retrieve plugin name.
    try
    {
        plugin_path = m_params.get("plugin_name");
    }
    catch (const ExceptionDictionaryKeyNotFound&)
    {
        RENDERER_LOG_ERROR("cannot open display: missing \"plugin_name\" parameter.");
        return false;
    }

    // Construct the path to the plugin file.
    plugin_path += SharedLibrary::get_default_file_extension();
    plugin_path = to_string(project.search_paths().qualify(plugin_path));

    // Load the plugin.
    try
    {
        impl = new Impl();
        impl->m_plugin.reset(project.get_plugin_store().load_plugin(plugin_path.c_str()));
    }
    catch (const ExceptionCannotLoadSharedLib& e)
    {
        RENDERER_LOG_ERROR("cannot open display: %s", e.what());
        return false;
    }

    // Create the tile callback factory.
    if (impl->m_plugin)
    {
        try
        {
            typedef ITileCallbackFactory* (*CreateFnType)(const ParamArray*);

            const auto create_tile_callback_factory =
                reinterpret_cast<CreateFnType>(impl->m_plugin->get_symbol("create_tile_callback_factory", false));

            impl->m_tile_callback_factory.reset(create_tile_callback_factory(&m_params));
        }
        catch (const ExceptionSharedLibCannotGetSymbol& e)
        {
            RENDERER_LOG_ERROR("initialization of display plugin %s failed: %s", plugin_path.c_str(), e.what());
            return false;
        }
    }

    return true;
}

void Display::close()
{
    delete impl;
    impl = nullptr;
}

ITileCallbackFactory* Display::get_tile_callback_factory() const
{
    return
        impl != nullptr
            ? impl->m_tile_callback_factory.get()
            : nullptr;
}

//
// DisplayFactory class implementation.
//

auto_release_ptr<Display> DisplayFactory::create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<Display>(new Display(name, params));
}

}   // namespace renderer
<commit_msg>Fix double plugin free in Displays<commit_after>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2014-2018 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "display.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/rendering/itilecallback.h"
#include "renderer/modeling/project/project.h"
#include "renderer/utility/plugin.h"
#include "renderer/utility/pluginstore.h"

// appleseed.foundation headers.
#include "foundation/platform/sharedlibrary.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <memory>
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// Display class implementation.
//

namespace
{
    const UniqueID g_class_uid = new_guid();
}

struct Display::Impl
{
    auto_release_ptr<ITileCallbackFactory>  m_tile_callback_factory;
};

UniqueID Display::get_class_uid()
{
    return g_class_uid;
}

Display::Display(
    const char*         name,
    const ParamArray&   params)
  : Entity(g_class_uid, params)
  , impl(nullptr)
{
    set_name(name);
}

Display::~Display()
{
    close();
}

void Display::release()
{
    delete this;
}

bool Display::open(const Project& project)
{
    string plugin_path;

    // Retrieve plugin name.
    try
    {
        plugin_path = m_params.get("plugin_name");
    }
    catch (const ExceptionDictionaryKeyNotFound&)
    {
        RENDERER_LOG_ERROR("cannot open display: missing \"plugin_name\" parameter.");
        return false;
    }

    // Construct the path to the plugin file.
    plugin_path += SharedLibrary::get_default_file_extension();
    plugin_path = to_string(project.search_paths().qualify(plugin_path));

    // Load the plugin.
    Plugin* plugin = nullptr;

    try
    {
        impl = new Impl();
        plugin = project.get_plugin_store().load_plugin(plugin_path.c_str());
    }
    catch (const ExceptionCannotLoadSharedLib& e)
    {
        RENDERER_LOG_ERROR("cannot open display: %s", e.what());
        return false;
    }

    // Create the tile callback factory.
    if (plugin)
    {
        try
        {
            typedef ITileCallbackFactory* (*CreateFnType)(const ParamArray*);

            const auto create_tile_callback_factory =
                reinterpret_cast<CreateFnType>(plugin->get_symbol("create_tile_callback_factory", false));

            impl->m_tile_callback_factory.reset(create_tile_callback_factory(&m_params));
        }
        catch (const ExceptionSharedLibCannotGetSymbol& e)
        {
            RENDERER_LOG_ERROR("initialization of display plugin %s failed: %s", plugin_path.c_str(), e.what());
            return false;
        }
    }

    return true;
}

void Display::close()
{
    delete impl;
    impl = nullptr;
}

ITileCallbackFactory* Display::get_tile_callback_factory() const
{
    return
        impl != nullptr
            ? impl->m_tile_callback_factory.get()
            : nullptr;
}

//
// DisplayFactory class implementation.
//

auto_release_ptr<Display> DisplayFactory::create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<Display>(new Display(name, params));
}

}   // namespace renderer
<|endoftext|>