<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/password_manager/password_store_x.h"

#include <algorithm>
#include <map>
#include <vector>

#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/password_manager/password_store_change.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"

using std::vector;
using webkit_glue::PasswordForm;

PasswordStoreX::PasswordStoreX(LoginDatabase* login_db,
                               Profile* profile,
                               WebDataService* web_data_service,
                               NativeBackend* backend)
    : PasswordStoreDefault(login_db, profile, web_data_service),
      backend_(backend), migration_checked_(!backend), allow_fallback_(false) {
}

PasswordStoreX::~PasswordStoreX() {
}

void PasswordStoreX::AddLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->AddLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::AddLoginImpl(form);
  }
}

void PasswordStoreX::UpdateLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->UpdateLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::UpdateLoginImpl(form);
  }
}

void PasswordStoreX::RemoveLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->RemoveLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::RemoveLoginImpl(form);
  }
}

void PasswordStoreX::RemoveLoginsCreatedBetweenImpl(
    const base::Time& delete_begin,
    const base::Time& delete_end) {
  CheckMigration();
  vector<PasswordForm*> forms;
  if (use_native_backend() &&
      backend_->GetLoginsCreatedBetween(delete_begin, delete_end, &forms) &&
      backend_->RemoveLoginsCreatedBetween(delete_begin, delete_end)) {
    PasswordStoreChangeList changes;
    for (vector<PasswordForm*>::const_iterator it = forms.begin();
         it != forms.end(); ++it) {
      changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
                                            **it));
    }
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(delete_begin,
                                                         delete_end);
  }
  STLDeleteElements(&forms);
}

namespace {
struct LoginLessThan {
  bool operator()(const PasswordForm* a, const PasswordForm* b) {
    return a->origin < b->origin;
  }
};
}  // anonymous namespace

void PasswordStoreX::SortLoginsByOrigin(NativeBackend::PasswordFormList* list) {
  // In login_database.cc, the query has ORDER BY origin_url. Simulate that.
  std::sort(list->begin(), list->end(), LoginLessThan());
}

void PasswordStoreX::GetLoginsImpl(GetLoginsRequest* request,
                                   const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->GetLogins(form, &request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetLoginsImpl(request, form);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

void PasswordStoreX::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
  CheckMigration();
  if (use_native_backend() &&
      backend_->GetAutofillableLogins(&request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetAutofillableLoginsImpl(request);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

void PasswordStoreX::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
  CheckMigration();
  if (use_native_backend() &&
      backend_->GetBlacklistLogins(&request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetBlacklistLoginsImpl(request);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

bool PasswordStoreX::FillAutofillableLogins(vector<PasswordForm*>* forms) {
  CheckMigration();
  if (use_native_backend() && backend_->GetAutofillableLogins(forms)) {
    allow_fallback_ = false;
    return true;
  }
  if (allow_default_store())
    return PasswordStoreDefault::FillAutofillableLogins(forms);
  return false;
}

bool PasswordStoreX::FillBlacklistLogins(vector<PasswordForm*>* forms) {
  CheckMigration();
  if (use_native_backend() && backend_->GetBlacklistLogins(forms)) {
    allow_fallback_ = false;
    return true;
  }
  if (allow_default_store())
    return PasswordStoreDefault::FillBlacklistLogins(forms);
  return false;
}

void PasswordStoreX::CheckMigration() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
  if (migration_checked_ || !backend_.get())
    return;
  migration_checked_ = true;
  ssize_t migrated = MigrateLogins();
  if (migrated > 0) {
    VLOG(1) << "Migrated " << migrated << " passwords to native store.";
  } else if (migrated == 0) {
    // As long as we are able to migrate some passwords, we know the native
    // store is working. But if there is nothing to migrate, the "migration"
    // can succeed even when the native store would fail. In this case we
    // allow a later fallback to the default store. Once any later operation
    // succeeds on the native store, we will no longer allow it.
    allow_fallback_ = true;
  } else {
    LOG(WARNING) << "Native password store migration failed! " <<
                 "Falling back on default (unencrypted) store.";
    backend_.reset(NULL);
  }
}

bool PasswordStoreX::allow_default_store() {
  if (allow_fallback_) {
    LOG(WARNING) << "Native password store failed! " <<
                 "Falling back on default (unencrypted) store.";
    backend_.reset(NULL);
    // Don't warn again. We'll use the default store because backend_ is NULL.
    allow_fallback_ = false;
  }
  return !backend_.get();
}

ssize_t PasswordStoreX::MigrateLogins() {
  DCHECK(backend_.get());
  vector<PasswordForm*> forms;
  bool ok = PasswordStoreDefault::FillAutofillableLogins(&forms) &&
      PasswordStoreDefault::FillBlacklistLogins(&forms);
  if (ok) {
    // We add all the passwords (and blacklist entries) to the native backend
    // before attempting to remove any from the login database, to make sure we
    // don't somehow end up with some of the passwords in one store and some in
    // another. We'll always have at least one intact store this way.
    for (size_t i = 0; i < forms.size(); ++i) {
      if (!backend_->AddLogin(*forms[i])) {
        ok = false;
        break;
      }
    }
    if (forms.empty()) {
      // If there's nothing to migrate, then we try to insert a dummy login form
      // just to force the native store to unlock if it was locked. We delete it
      // right away if we are successful. If the first operation we try to do is
      // a read, then in some cases this is just an error rather than an action
      // that causes the native store to prompt the user to unlock.
      // TODO(mdm): this means we no longer need the allow_fallback mechanism.
      // Remove it once this preemptive unlock by write is baked for a while.
      PasswordForm dummy;
      dummy.origin = GURL("http://www.example.com/force-keyring-unlock");
      dummy.signon_realm = "www.example.com";
      if (backend_->AddLogin(dummy))
        backend_->RemoveLogin(dummy);
      else
        ok = false;
    }
    if (ok) {
      for (size_t i = 0; i < forms.size(); ++i) {
        // If even one of these calls to RemoveLoginImpl() succeeds, then we
        // should prefer the native backend to the now-incomplete login
        // database. Thus we want to return a success status even in the case
        // where some fail. The only real problem with this is that we might
        // leave passwords in the login database and never come back to clean
        // them out if any of these calls do fail.
        PasswordStoreDefault::RemoveLoginImpl(*forms[i]);
      }
      // Finally, delete the database file itself. We remove the passwords from
      // it before deleting the file just in case there is some problem deleting
      // the file (e.g. directory is not writable, but file is), which would
      // otherwise cause passwords to re-migrate next (or maybe every) time.
      DeleteAndRecreateDatabaseFile();
    }
  }
  ssize_t result = ok ? forms.size() : -1;
  STLDeleteElements(&forms);
  return result;
}
<commit_msg>Linux: remove the forced keyring unlock on password store initialization. It is no longer required for our gnome keyring integration to work correctly.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/password_manager/password_store_x.h"

#include <algorithm>
#include <map>
#include <vector>

#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/password_manager/password_store_change.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"

using std::vector;
using webkit_glue::PasswordForm;

PasswordStoreX::PasswordStoreX(LoginDatabase* login_db,
                               Profile* profile,
                               WebDataService* web_data_service,
                               NativeBackend* backend)
    : PasswordStoreDefault(login_db, profile, web_data_service),
      backend_(backend), migration_checked_(!backend), allow_fallback_(false) {
}

PasswordStoreX::~PasswordStoreX() {
}

void PasswordStoreX::AddLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->AddLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::AddLoginImpl(form);
  }
}

void PasswordStoreX::UpdateLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->UpdateLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::UpdateLoginImpl(form);
  }
}

void PasswordStoreX::RemoveLoginImpl(const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->RemoveLogin(form)) {
    PasswordStoreChangeList changes;
    changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::RemoveLoginImpl(form);
  }
}

void PasswordStoreX::RemoveLoginsCreatedBetweenImpl(
    const base::Time& delete_begin,
    const base::Time& delete_end) {
  CheckMigration();
  vector<PasswordForm*> forms;
  if (use_native_backend() &&
      backend_->GetLoginsCreatedBetween(delete_begin, delete_end, &forms) &&
      backend_->RemoveLoginsCreatedBetween(delete_begin, delete_end)) {
    PasswordStoreChangeList changes;
    for (vector<PasswordForm*>::const_iterator it = forms.begin();
         it != forms.end(); ++it) {
      changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
                                            **it));
    }
    NotificationService::current()->Notify(
        NotificationType::LOGINS_CHANGED,
        Source<PasswordStore>(this),
        Details<PasswordStoreChangeList>(&changes));
    allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(delete_begin,
                                                         delete_end);
  }
  STLDeleteElements(&forms);
}

namespace {
struct LoginLessThan {
  bool operator()(const PasswordForm* a, const PasswordForm* b) {
    return a->origin < b->origin;
  }
};
}  // anonymous namespace

void PasswordStoreX::SortLoginsByOrigin(NativeBackend::PasswordFormList* list) {
  // In login_database.cc, the query has ORDER BY origin_url. Simulate that.
  std::sort(list->begin(), list->end(), LoginLessThan());
}

void PasswordStoreX::GetLoginsImpl(GetLoginsRequest* request,
                                   const PasswordForm& form) {
  CheckMigration();
  if (use_native_backend() && backend_->GetLogins(form, &request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    // The native backend may succeed and return no data even while locked, if
    // the query did not match anything stored. So we continue to allow fallback
    // until we perform a write operation, or until a read returns actual data.
    if (request->value.size() > 0)
      allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetLoginsImpl(request, form);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

void PasswordStoreX::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
  CheckMigration();
  if (use_native_backend() &&
      backend_->GetAutofillableLogins(&request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    // See GetLoginsImpl() for why we disallow fallback conditionally here.
    if (request->value.size() > 0)
      allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetAutofillableLoginsImpl(request);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

void PasswordStoreX::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
  CheckMigration();
  if (use_native_backend() &&
      backend_->GetBlacklistLogins(&request->value)) {
    SortLoginsByOrigin(&request->value);
    ForwardLoginsResult(request);
    // See GetLoginsImpl() for why we disallow fallback conditionally here.
    if (request->value.size() > 0)
      allow_fallback_ = false;
  } else if (allow_default_store()) {
    PasswordStoreDefault::GetBlacklistLoginsImpl(request);
  } else {
    // The consumer will be left hanging unless we reply.
    ForwardLoginsResult(request);
  }
}

bool PasswordStoreX::FillAutofillableLogins(vector<PasswordForm*>* forms) {
  CheckMigration();
  if (use_native_backend() && backend_->GetAutofillableLogins(forms)) {
    // See GetLoginsImpl() for why we disallow fallback conditionally here.
    if (forms->size() > 0)
      allow_fallback_ = false;
    return true;
  }
  if (allow_default_store())
    return PasswordStoreDefault::FillAutofillableLogins(forms);
  return false;
}

bool PasswordStoreX::FillBlacklistLogins(vector<PasswordForm*>* forms) {
  CheckMigration();
  if (use_native_backend() && backend_->GetBlacklistLogins(forms)) {
    // See GetLoginsImpl() for why we disallow fallback conditionally here.
    if (forms->size() > 0)
      allow_fallback_ = false;
    return true;
  }
  if (allow_default_store())
    return PasswordStoreDefault::FillBlacklistLogins(forms);
  return false;
}

void PasswordStoreX::CheckMigration() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
  if (migration_checked_ || !backend_.get())
    return;
  migration_checked_ = true;
  ssize_t migrated = MigrateLogins();
  if (migrated > 0) {
    VLOG(1) << "Migrated " << migrated << " passwords to native store.";
  } else if (migrated == 0) {
    // As long as we are able to migrate some passwords, we know the native
    // store is working. But if there is nothing to migrate, the "migration"
    // can succeed even when the native store would fail. In this case we
    // allow a later fallback to the default store. Once any later operation
    // succeeds on the native store, we will no longer allow fallback.
    allow_fallback_ = true;
  } else {
    LOG(WARNING) << "Native password store migration failed! " <<
                 "Falling back on default (unencrypted) store.";
    backend_.reset(NULL);
  }
}

bool PasswordStoreX::allow_default_store() {
  if (allow_fallback_) {
    LOG(WARNING) << "Native password store failed! " <<
                 "Falling back on default (unencrypted) store.";
    backend_.reset(NULL);
    // Don't warn again. We'll use the default store because backend_ is NULL.
    allow_fallback_ = false;
  }
  return !backend_.get();
}

ssize_t PasswordStoreX::MigrateLogins() {
  DCHECK(backend_.get());
  vector<PasswordForm*> forms;
  bool ok = PasswordStoreDefault::FillAutofillableLogins(&forms) &&
      PasswordStoreDefault::FillBlacklistLogins(&forms);
  if (ok) {
    // We add all the passwords (and blacklist entries) to the native backend
    // before attempting to remove any from the login database, to make sure we
    // don't somehow end up with some of the passwords in one store and some in
    // another. We'll always have at least one intact store this way.
    for (size_t i = 0; i < forms.size(); ++i) {
      if (!backend_->AddLogin(*forms[i])) {
        ok = false;
        break;
      }
    }
    if (ok) {
      for (size_t i = 0; i < forms.size(); ++i) {
        // If even one of these calls to RemoveLoginImpl() succeeds, then we
        // should prefer the native backend to the now-incomplete login
        // database. Thus we want to return a success status even in the case
        // where some fail. The only real problem with this is that we might
        // leave passwords in the login database and never come back to clean
        // them out if any of these calls do fail.
        PasswordStoreDefault::RemoveLoginImpl(*forms[i]);
      }
      // Finally, delete the database file itself. We remove the passwords from
      // it before deleting the file just in case there is some problem deleting
      // the file (e.g. directory is not writable, but file is), which would
      // otherwise cause passwords to re-migrate next (or maybe every) time.
      DeleteAndRecreateDatabaseFile();
    }
  }
  ssize_t result = ok ? forms.size() : -1;
  STLDeleteElements(&forms);
  return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/message/network_address.hpp>
#include <boost/iostreams/stream.hpp>
#include <bitcoin/bitcoin/utility/container_sink.hpp>
#include <bitcoin/bitcoin/utility/container_source.hpp>
#include <bitcoin/bitcoin/utility/istream.hpp>
#include <bitcoin/bitcoin/utility/ostream.hpp>

namespace libbitcoin {
namespace message {

ip_address null_address = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

network_address network_address::factory_from_data(const data_chunk& data,
    bool with_timestamp /*= false*/)
{
    network_address instance;
    instance.from_data(data, with_timestamp);
    return instance;
}

network_address network_address::factory_from_data(std::istream& stream,
    bool with_timestamp /*= false*/)
{
    network_address instance;
    instance.from_data(stream, with_timestamp);
    return instance;
}

bool network_address::is_valid() const
{
    return (timestamp != 0) ||
        (services != 0) ||
        (port != 0) ||
        (ip != null_address);
}

void network_address::reset()
{
    timestamp = 0;
    services = 0;
    ip.fill(0);
    port = 0;
}

bool network_address::from_data(const data_chunk& data, bool with_timestamp)
{
    boost::iostreams::stream<byte_source<data_chunk>> istream(data);
    return from_data(istream, with_timestamp);
}

bool network_address::from_data(std::istream& stream, bool with_timestamp)
{
    reset();

    if (with_timestamp)
        timestamp = read_4_bytes(stream);

    services = read_8_bytes(stream);
    ip= read_bytes<16>(stream);
    port = read_big_endian<uint16_t>(stream);

    if (!stream)
        reset();

    return stream;
}

data_chunk network_address::to_data(bool with_timestamp) const
{
    data_chunk data;
    boost::iostreams::stream<byte_sink<data_chunk>> ostream(data);
    to_data(ostream, with_timestamp);
    BOOST_ASSERT(data.size() == satoshi_size());
    return data;
}

void network_address::to_data(std::ostream& stream, bool with_timestamp) const
{
    if (with_timestamp)
        write_4_bytes(stream, timestamp);

    write_8_bytes(stream, services);
    write_data(stream, ip);
    write_big_endian<uint16_t>(stream, port);
}

uint64_t network_address::satoshi_size(bool with_timestamp) const
{
    return network_address::satoshi_fixed_size(with_timestamp);
}

uint64_t network_address::satoshi_fixed_size(bool with_timestamp)
{
    uint64_t result = 26;

    if (with_timestamp)
        result += 4;

    return result;
}

} // end message
} // end libbitcoin
<commit_msg>Correct error in assert.<commit_after>/*
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/message/network_address.hpp>
#include <boost/iostreams/stream.hpp>
#include <bitcoin/bitcoin/utility/container_sink.hpp>
#include <bitcoin/bitcoin/utility/container_source.hpp>
#include <bitcoin/bitcoin/utility/istream.hpp>
#include <bitcoin/bitcoin/utility/ostream.hpp>

namespace libbitcoin {
namespace message {

ip_address null_address = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

network_address network_address::factory_from_data(const data_chunk& data,
    bool with_timestamp /*= false*/)
{
    network_address instance;
    instance.from_data(data, with_timestamp);
    return instance;
}

network_address network_address::factory_from_data(std::istream& stream,
    bool with_timestamp /*= false*/)
{
    network_address instance;
    instance.from_data(stream, with_timestamp);
    return instance;
}

bool network_address::is_valid() const
{
    return (timestamp != 0) ||
        (services != 0) ||
        (port != 0) ||
        (ip != null_address);
}

void network_address::reset()
{
    timestamp = 0;
    services = 0;
    ip.fill(0);
    port = 0;
}

bool network_address::from_data(const data_chunk& data, bool with_timestamp)
{
    boost::iostreams::stream<byte_source<data_chunk>> istream(data);
    return from_data(istream, with_timestamp);
}

bool network_address::from_data(std::istream& stream, bool with_timestamp)
{
    reset();

    if (with_timestamp)
        timestamp = read_4_bytes(stream);

    services = read_8_bytes(stream);
    ip= read_bytes<16>(stream);
    port = read_big_endian<uint16_t>(stream);

    if (!stream)
        reset();

    return stream;
}

data_chunk network_address::to_data(bool with_timestamp) const
{
    data_chunk data;
    boost::iostreams::stream<byte_sink<data_chunk>> ostream(data);
    to_data(ostream, with_timestamp);
    BOOST_ASSERT(data.size() == satoshi_size(with_timestamp));
    return data;
}

void network_address::to_data(std::ostream& stream, bool with_timestamp) const
{
    if (with_timestamp)
        write_4_bytes(stream, timestamp);

    write_8_bytes(stream, services);
    write_data(stream, ip);
    write_big_endian<uint16_t>(stream, port);
}

uint64_t network_address::satoshi_size(bool with_timestamp) const
{
    return network_address::satoshi_fixed_size(with_timestamp);
}

uint64_t network_address::satoshi_fixed_size(bool with_timestamp)
{
    uint64_t result = 26;

    if (with_timestamp)
        result += 4;

    return result;
}

} // end message
} // end libbitcoin
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_loader.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: vg $ $Date: 2007-10-11 15:52:28 $
 *
 *  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
 *
 ************************************************************************/

#include <pyuno/pyuno.hxx>

#include <osl/module.hxx>
#include <osl/process.h>
#include <osl/file.h>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OString;

using pyuno::PyRef;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module(
        PyImport_ImportModule( const_cast< char * >("pythonloader") ),
        SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "pythonloader: Couldn't load pythonloader module" ) ),
            Reference< XInterface > () );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.pyuno.Loader" ) );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Python" ) );
    return Sequence< OUString > ( &serviceName, 1 );
}

static OUString getLibDir()
{
    static OUString *pLibDir;
    if( !pLibDir )
    {
        osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
        if( ! pLibDir )
        {
            static OUString libDir;

            if( osl::Module::getUrlFromAddress(
                    reinterpret_cast< oslGenericFunction >(getLibDir) , libDir ) )
            {
                libDir = OUString( libDir.getStr(), libDir.lastIndexOf('/' ) );
            }
            pLibDir = &libDir;
        }
    }
    return *pLibDir;
}

static void setPythonHome ( const OUString & pythonHome )
{
    OUString systemPythonHome;
    osl_getSystemPathFromFileURL( pythonHome.pData, &(systemPythonHome.pData) );
    OString o = rtl::OUStringToOString( systemPythonHome, osl_getThreadTextEncoding() );
    rtl_string_acquire(o.pData); // leak this string (thats the api!)
    Py_SetPythonHome( o.pData->buffer);
}

static void prependPythonPath( const OUString & pythonPathBootstrap )
{
    rtl::OStringBuffer bufPYTHONPATH( 256 );
    bufPYTHONPATH.append( "PYTHONPATH=");
    sal_Int32 nIndex = 0;
    while( 1 )
    {
        sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
        OUString fileUrl;
        if( nNew == -1 )
        {
            fileUrl = OUString( &( pythonPathBootstrap[nIndex] ) );
        }
        else
        {
            fileUrl = OUString( &(pythonPathBootstrap[nIndex]) , nNew - nIndex );
        }
        OUString systemPath;
        osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
        bufPYTHONPATH.append( rtl::OUStringToOString( systemPath.pData, osl_getThreadTextEncoding() ));
        bufPYTHONPATH.append( SAL_PATHSEPARATOR );
        if( nNew == -1 )
            break;
        nIndex = nNew + 1;
    }
    const char * oldEnv = getenv( "PYTHONPATH");
    if( oldEnv )
        bufPYTHONPATH.append( oldEnv );
    OString result = bufPYTHONPATH.makeStringAndClear();
    rtl_string_acquire( result.pData );

//     printf( "Setting %s\n" , result.pData->buffer );
    putenv( result.pData->buffer );

}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        OUString pythonPath;
        OUString pythonHome;
        OUString path = getLibDir();
        if( path.getLength() )
        {
            path += OUString( RTL_CONSTASCII_USTRINGPARAM( "/" SAL_CONFIGFILE("pythonloader.uno" )));
            rtl::Bootstrap bootstrap(path);

            // look for pythonhome
            bootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "PYUNO_LOADER_PYTHONHOME") ), pythonHome );
            bootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "PYUNO_LOADER_PYTHONPATH" ) ) , pythonPath );
        }

        // pythonhome+pythonpath must be set before Py_Initialize(), otherwise there appear warning on the console
        // sadly, there is no api for setting the pythonpath, we have to use the environment variable
        if( pythonHome.getLength() )
            setPythonHome( pythonHome );

        if( pythonPath.getLength() )
            prependPythonPath( pythonPath );

        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

<commit_msg>INTEGRATION: CWS changefileheader (1.10.12); FILE MERGED 2008/03/31 07:24:58 rt 1.10.12.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: pyuno_loader.cxx,v $
 * $Revision: 1.11 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <pyuno/pyuno.hxx>

#include <osl/module.hxx>
#include <osl/process.h>
#include <osl/file.h>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OString;

using pyuno::PyRef;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module(
        PyImport_ImportModule( const_cast< char * >("pythonloader") ),
        SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "pythonloader: Couldn't load pythonloader module" ) ),
            Reference< XInterface > () );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.pyuno.Loader" ) );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Python" ) );
    return Sequence< OUString > ( &serviceName, 1 );
}

static OUString getLibDir()
{
    static OUString *pLibDir;
    if( !pLibDir )
    {
        osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
        if( ! pLibDir )
        {
            static OUString libDir;

            if( osl::Module::getUrlFromAddress(
                    reinterpret_cast< oslGenericFunction >(getLibDir) , libDir ) )
            {
                libDir = OUString( libDir.getStr(), libDir.lastIndexOf('/' ) );
            }
            pLibDir = &libDir;
        }
    }
    return *pLibDir;
}

static void setPythonHome ( const OUString & pythonHome )
{
    OUString systemPythonHome;
    osl_getSystemPathFromFileURL( pythonHome.pData, &(systemPythonHome.pData) );
    OString o = rtl::OUStringToOString( systemPythonHome, osl_getThreadTextEncoding() );
    rtl_string_acquire(o.pData); // leak this string (thats the api!)
    Py_SetPythonHome( o.pData->buffer);
}

static void prependPythonPath( const OUString & pythonPathBootstrap )
{
    rtl::OStringBuffer bufPYTHONPATH( 256 );
    bufPYTHONPATH.append( "PYTHONPATH=");
    sal_Int32 nIndex = 0;
    while( 1 )
    {
        sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
        OUString fileUrl;
        if( nNew == -1 )
        {
            fileUrl = OUString( &( pythonPathBootstrap[nIndex] ) );
        }
        else
        {
            fileUrl = OUString( &(pythonPathBootstrap[nIndex]) , nNew - nIndex );
        }
        OUString systemPath;
        osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
        bufPYTHONPATH.append( rtl::OUStringToOString( systemPath.pData, osl_getThreadTextEncoding() ));
        bufPYTHONPATH.append( SAL_PATHSEPARATOR );
        if( nNew == -1 )
            break;
        nIndex = nNew + 1;
    }
    const char * oldEnv = getenv( "PYTHONPATH");
    if( oldEnv )
        bufPYTHONPATH.append( oldEnv );
    OString result = bufPYTHONPATH.makeStringAndClear();
    rtl_string_acquire( result.pData );

//     printf( "Setting %s\n" , result.pData->buffer );
    putenv( result.pData->buffer );

}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        OUString pythonPath;
        OUString pythonHome;
        OUString path = getLibDir();
        if( path.getLength() )
        {
            path += OUString( RTL_CONSTASCII_USTRINGPARAM( "/" SAL_CONFIGFILE("pythonloader.uno" )));
            rtl::Bootstrap bootstrap(path);

            // look for pythonhome
            bootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "PYUNO_LOADER_PYTHONHOME") ), pythonHome );
            bootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "PYUNO_LOADER_PYTHONPATH" ) ) , pythonPath );
        }

        // pythonhome+pythonpath must be set before Py_Initialize(), otherwise there appear warning on the console
        // sadly, there is no api for setting the pythonpath, we have to use the environment variable
        if( pythonHome.getLength() )
            setPythonHome( pythonHome );

        if( pythonPath.getLength() )
            prependPythonPath( pythonPath );

        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_loader.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:50:38 $
 *
 *  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
 *
 ************************************************************************/
#include <osl/module.hxx>
#include <osl/process.h>
#include <osl/file.h>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

#include <pyuno/pyuno.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OString;

using pyuno::PyRef;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module( PyImport_ImportModule( "pythonloader" ), SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "pythonloader: Couldn't load pythonloader module" ) ),
            Reference< XInterface > () );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.pyuno.Loader" ) );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Python" ) );
    return Sequence< OUString > ( &serviceName, 1 );
}

static OUString getLibDir()
{
    static OUString *pLibDir;
    if( !pLibDir )
    {
        osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
        if( ! pLibDir )
        {
            static OUString libDir;

            // changed from reinterpret_cast<void*> this is not allowed
            // in gcc 3.3 without permissive.  Us simple C cast.
            if( osl::Module::getUrlFromAddress( (void*)(getLibDir) , libDir ) )
            {
                libDir = OUString( libDir.getStr(), libDir.lastIndexOf('/' ) );
            }
            pLibDir = &libDir;
        }
    }
    return *pLibDir;
}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        // in case python path is already set, nothing is done ...
        const OUString pythonPath ( RTL_CONSTASCII_USTRINGPARAM( "PYTHONPATH" ) );

        // otherwise, try to get the PYTHONPATH bootstrap variable
        OUStringBuffer bufPYTHONPATH( 256 );
        OUString path = getLibDir();
        if( path.getLength() )
        {
            path += OUString( RTL_CONSTASCII_USTRINGPARAM( "/" SAL_CONFIGFILE("pythonloader.uno" )));
            rtl::Bootstrap bootstrap(path);

            // look for pythonhome
            OUString pythonHome;
            if( bootstrap.getFrom( OUString ( RTL_CONSTASCII_USTRINGPARAM( "PYTHONHOME") ),
                                   pythonHome ) )
            {
                osl_getFileURLFromSystemPath( pythonHome.pData, &(pythonHome.pData) );
                rtl::OStringBuffer stringBuffer( pythonHome.getLength() +20);
                stringBuffer.append( "PYTHONHOME=" );
                stringBuffer.append(
                    rtl::OUStringToOString( pythonHome, osl_getThreadTextEncoding() ) );

                OString env2= stringBuffer.makeStringAndClear();
                rtl_string_acquire(env2.pData );
                putenv( env2.pData->buffer );

            }

            // check for pythonpath
            OUString pythonPathBootstrap;
            bootstrap.getFrom( pythonPath , pythonPathBootstrap );

            sal_Int32 nIndex = 0;
            while( 1 )
            {
                sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
                OUString fileUrl;
                if( nNew == -1 )
                {
                    fileUrl = OUString( &( pythonPathBootstrap[nIndex] ) );
                }
                else
                {
                    fileUrl = OUString( &(pythonPathBootstrap[nIndex]) , nNew - nIndex );
                }
                OUString systemPath;
                osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
                bufPYTHONPATH.append( systemPath );
                if( nNew == -1 )
                    break;
                bufPYTHONPATH.append( (sal_Unicode) SAL_PATHSEPARATOR );
                nIndex = nNew + 1;
            }
        }

        OUString value;
        osl_getEnvironment( pythonPath.pData,  &value.pData );
        bufPYTHONPATH.append( value );

        rtl::OStringBuffer stringBuffer;
        stringBuffer.append( "PYTHONPATH=" );
        stringBuffer.append(
            rtl::OUStringToOString( bufPYTHONPATH.makeStringAndClear(), osl_getThreadTextEncoding()));

        OString env = stringBuffer.makeStringAndClear();

        // leak this string (putenv does not make a copy)
        rtl_string_acquire( env.pData );
        putenv( env.pData->buffer );

        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

<commit_msg>INTEGRATION: CWS warnings01 (1.6.14); FILE MERGED 2005/09/23 02:07:33 sb 1.6.14.2: RESYNC: (1.6-1.7); FILE MERGED 2005/09/09 15:31:16 sb 1.6.14.1: #i53898# Made code warning-free.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_loader.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:02:53 $
 *
 *  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
 *
 ************************************************************************/

#include <pyuno/pyuno.hxx>

#include <osl/module.hxx>
#include <osl/process.h>
#include <osl/file.h>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OString;

using pyuno::PyRef;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface> () );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module(
        PyImport_ImportModule( const_cast< char * >("pythonloader") ),
        SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "pythonloader: Couldn't load pythonloader module" ) ),
            Reference< XInterface > () );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.pyuno.Loader" ) );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Python" ) );
    return Sequence< OUString > ( &serviceName, 1 );
}

static OUString getLibDir()
{
    static OUString *pLibDir;
    if( !pLibDir )
    {
        osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
        if( ! pLibDir )
        {
            static OUString libDir;

            if( osl::Module::getUrlFromAddress(
                    reinterpret_cast< oslGenericFunction >(getLibDir) , libDir ) )
            {
                libDir = OUString( libDir.getStr(), libDir.lastIndexOf('/' ) );
            }
            pLibDir = &libDir;
        }
    }
    return *pLibDir;
}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        // in case python path is already set, nothing is done ...
        const OUString pythonPath ( RTL_CONSTASCII_USTRINGPARAM( "PYTHONPATH" ) );

        // otherwise, try to get the PYTHONPATH bootstrap variable
        OUStringBuffer bufPYTHONPATH( 256 );
        OUString path = getLibDir();
        if( path.getLength() )
        {
            path += OUString( RTL_CONSTASCII_USTRINGPARAM( "/" SAL_CONFIGFILE("pythonloader.uno" )));
            rtl::Bootstrap bootstrap(path);

            // look for pythonhome
            OUString pythonHome;
            if( bootstrap.getFrom( OUString ( RTL_CONSTASCII_USTRINGPARAM( "PYTHONHOME") ),
                                   pythonHome ) )
            {
                osl_getFileURLFromSystemPath( pythonHome.pData, &(pythonHome.pData) );
                rtl::OStringBuffer stringBuffer( pythonHome.getLength() +20);
                stringBuffer.append( "PYTHONHOME=" );
                stringBuffer.append(
                    rtl::OUStringToOString( pythonHome, osl_getThreadTextEncoding() ) );

                OString env2= stringBuffer.makeStringAndClear();
                rtl_string_acquire(env2.pData );
                putenv( env2.pData->buffer );

            }

            // check for pythonpath
            OUString pythonPathBootstrap;
            bootstrap.getFrom( pythonPath , pythonPathBootstrap );

            sal_Int32 nIndex = 0;
            while( 1 )
            {
                sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
                OUString fileUrl;
                if( nNew == -1 )
                {
                    fileUrl = OUString( &( pythonPathBootstrap[nIndex] ) );
                }
                else
                {
                    fileUrl = OUString( &(pythonPathBootstrap[nIndex]) , nNew - nIndex );
                }
                OUString systemPath;
                osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
                bufPYTHONPATH.append( systemPath );
                if( nNew == -1 )
                    break;
                bufPYTHONPATH.append( (sal_Unicode) SAL_PATHSEPARATOR );
                nIndex = nNew + 1;
            }
        }

        OUString value;
        osl_getEnvironment( pythonPath.pData,  &value.pData );
        bufPYTHONPATH.append( value );

        rtl::OStringBuffer stringBuffer;
        stringBuffer.append( "PYTHONPATH=" );
        stringBuffer.append(
            rtl::OUStringToOString( bufPYTHONPATH.makeStringAndClear(), osl_getThreadTextEncoding()));

        OString env = stringBuffer.makeStringAndClear();

        // leak this string (putenv does not make a copy)
        rtl_string_acquire( env.pData );
        putenv( env.pData->buffer );

        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

<|endoftext|>


<commit_before>/**
 * @file llmessageconfig_tut.cpp
 * @date   March 2007
 * @brief LLMessageConfig unit tests
 *
 * $LicenseInfo:firstyear=2006&license=viewergpl$
 *
 * Copyright (c) 2006-2007, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlife.com/developers/opensource/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at http://secondlife.com/developers/opensource/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include "llmessageconfig.h"
#include "lltut.h"
#include "llsdserialize.h"
#include "llfile.h"
#include "lltimer.h"
#include "llframetimer.h"
#include "llsdutil.h"

namespace tut
{
	struct LLMessageConfigTestData {
		std::string mTestConfigDir;

		LLMessageConfigTestData()
		{
			LLUUID random;
			random.generate();
			// generate temp dir
			std::ostringstream oStr;
			oStr << "/tmp/llmessage-config-test-" << random;
			mTestConfigDir = oStr.str();
			LLFile::mkdir(mTestConfigDir.c_str());
			writeConfigFile(LLSD());
			LLMessageConfig::initClass("simulator", mTestConfigDir);
		}

		~LLMessageConfigTestData()
		{
			// rm contents of temp dir
			int rmfile = LLFile::remove((mTestConfigDir + "/message.xml").c_str());
			ensure_equals("rmfile value", rmfile, 0);
			// rm temp dir
			int rmdir = LLFile::rmdir(mTestConfigDir.c_str());
			ensure_equals("rmdir value", rmdir, 0);
		}

		void writeConfigFile(const LLSD& config)
		{
			llofstream file((mTestConfigDir + "/message.xml").c_str());
			if (file.is_open())
			{
				LLSDSerialize::toPrettyXML(config, file);
			}
			file.close();
		}
	};

	typedef test_group<LLMessageConfigTestData> LLMessageConfigTestGroup;
	typedef LLMessageConfigTestGroup::object LLMessageConfigTestObject;
	LLMessageConfigTestGroup llMessageConfigTestGroup("LLMessageConfig");

	template<> template<>
	void LLMessageConfigTestObject::test<1>()
		// tests server defaults
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure server default is not template",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::TEMPLATE_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<2>()
		// tests message flavors
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "template";
		config["messages"]["msg2"]["flavor"] = "llsd";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg template flavor",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::TEMPLATE_FLAVOR);
		ensure_equals("Ensure msg llsd flavor",
					  LLMessageConfig::getMessageFlavor("msg2"),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<4>()
		// tests message flavor defaults
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "llsd";
		config["messages"]["msg1"]["trusted-sender"] = true;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure missing message gives no flavor",
					  LLMessageConfig::getMessageFlavor("Test"),
					  LLMessageConfig::NO_FLAVOR);
		ensure_equals("Ensure missing flavor is NO_FLAVOR even with sender trustedness set",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::NO_FLAVOR);
		ensure_equals("Ensure server default is llsd",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<3>()
		// tests trusted/untrusted senders
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		config["messages"]["msg1"]["trusted-sender"] = false;
		config["messages"]["msg2"]["flavor"] = "llsd";
		config["messages"]["msg2"]["trusted-sender"] = true;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure untrusted is untrusted",
					  LLMessageConfig::getSenderTrustedness("msg1"),
					  LLMessageConfig::UNTRUSTED);
		ensure_equals("Ensure trusted is trusted",
					  LLMessageConfig::getSenderTrustedness("msg2"),
					  LLMessageConfig::TRUSTED);
		ensure_equals("Ensure missing trustedness is NOT_SET",
					  LLMessageConfig::getSenderTrustedness("msg3"),
					  LLMessageConfig::NOT_SET);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<5>()
		// tests trusted/untrusted without flag, only flavor
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg1 exists, has llsd flavor",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::LLSD_FLAVOR);
		ensure_equals("Ensure missing trusted is not set",
					  LLMessageConfig::getSenderTrustedness("msg1"),
					  LLMessageConfig::NOT_SET);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<6>()
	{
		LLSD config;
		config["capBans"]["MapLayer"] = true;
		config["capBans"]["MapLayerGod"] = false;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure cap ban true MapLayer",
					  LLMessageConfig::isCapBanned("MapLayer"),
					  true);
		ensure_equals("Ensure cap ban false",
					  LLMessageConfig::isCapBanned("MapLayerGod"),
					  false);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<7>()
		// tests that config changes are picked up/refreshed periodically
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "llsd";
		writeConfigFile(config);

		// wait for it to reload after N seconds
		ms_sleep(6*1000);
		LLFrameTimer::updateFrameTime();
		ensure_equals("Ensure reload after 6 seconds",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<8>()
		// tests that config changes are picked up/refreshed periodically
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		config["messages"]["msg1"]["only-send-latest"] = true;
		config["messages"]["msg2"]["flavor"] = "llsd";
		config["messages"]["msg2"]["only-send-latest"] = false;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg1 exists, sent latest-only",
					  LLMessageConfig::onlySendLatest("msg1"),
					  true);
		ensure_equals("Ensure msg2 exists, sent latest-only",
					  LLMessageConfig::onlySendLatest("msg2"),
					  false);
	}
}
<commit_msg>Fixed unit test failure on Windows, "/tmp" doesn't exist on Win32.  Ported from Havok4 branch, reviewed with Kelly, OK with Josh.<commit_after>/**
 * @file llmessageconfig_tut.cpp
 * @date   March 2007
 * @brief LLMessageConfig unit tests
 *
 * $LicenseInfo:firstyear=2006&license=viewergpl$
 *
 * Copyright (c) 2006-2007, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlife.com/developers/opensource/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at http://secondlife.com/developers/opensource/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include "llmessageconfig.h"
#include "lltut.h"
#include "llsdserialize.h"
#include "llfile.h"
#include "lltimer.h"
#include "llframetimer.h"
#include "llsdutil.h"

namespace tut
{
	struct LLMessageConfigTestData {
		std::string mTestConfigDir;

		LLMessageConfigTestData()
		{
			LLUUID random;
			random.generate();
			// generate temp dir
			std::ostringstream oStr;
#if LL_WINDOWS
			oStr << "llmessage-config-test-" << random;
#else
			oStr << "/tmp/llmessage-config-test-" << random;
#endif
			mTestConfigDir = oStr.str();
			LLFile::mkdir(mTestConfigDir.c_str());
			writeConfigFile(LLSD());
			LLMessageConfig::initClass("simulator", mTestConfigDir);
		}

		~LLMessageConfigTestData()
		{
			// rm contents of temp dir
			int rmfile = LLFile::remove((mTestConfigDir + "/message.xml").c_str());
			ensure_equals("rmfile value", rmfile, 0);
			// rm temp dir
			int rmdir = LLFile::rmdir(mTestConfigDir.c_str());
			ensure_equals("rmdir value", rmdir, 0);
		}

		void writeConfigFile(const LLSD& config)
		{
			llofstream file((mTestConfigDir + "/message.xml").c_str());
			if (file.is_open())
			{
				LLSDSerialize::toPrettyXML(config, file);
			}
			file.close();
		}
	};

	typedef test_group<LLMessageConfigTestData> LLMessageConfigTestGroup;
	typedef LLMessageConfigTestGroup::object LLMessageConfigTestObject;
	LLMessageConfigTestGroup llMessageConfigTestGroup("LLMessageConfig");

	template<> template<>
	void LLMessageConfigTestObject::test<1>()
		// tests server defaults
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure server default is not template",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::TEMPLATE_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<2>()
		// tests message flavors
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "template";
		config["messages"]["msg2"]["flavor"] = "llsd";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg template flavor",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::TEMPLATE_FLAVOR);
		ensure_equals("Ensure msg llsd flavor",
					  LLMessageConfig::getMessageFlavor("msg2"),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<4>()
		// tests message flavor defaults
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "llsd";
		config["messages"]["msg1"]["trusted-sender"] = true;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure missing message gives no flavor",
					  LLMessageConfig::getMessageFlavor("Test"),
					  LLMessageConfig::NO_FLAVOR);
		ensure_equals("Ensure missing flavor is NO_FLAVOR even with sender trustedness set",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::NO_FLAVOR);
		ensure_equals("Ensure server default is llsd",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<3>()
		// tests trusted/untrusted senders
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		config["messages"]["msg1"]["trusted-sender"] = false;
		config["messages"]["msg2"]["flavor"] = "llsd";
		config["messages"]["msg2"]["trusted-sender"] = true;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure untrusted is untrusted",
					  LLMessageConfig::getSenderTrustedness("msg1"),
					  LLMessageConfig::UNTRUSTED);
		ensure_equals("Ensure trusted is trusted",
					  LLMessageConfig::getSenderTrustedness("msg2"),
					  LLMessageConfig::TRUSTED);
		ensure_equals("Ensure missing trustedness is NOT_SET",
					  LLMessageConfig::getSenderTrustedness("msg3"),
					  LLMessageConfig::NOT_SET);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<5>()
		// tests trusted/untrusted without flag, only flavor
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg1 exists, has llsd flavor",
					  LLMessageConfig::getMessageFlavor("msg1"),
					  LLMessageConfig::LLSD_FLAVOR);
		ensure_equals("Ensure missing trusted is not set",
					  LLMessageConfig::getSenderTrustedness("msg1"),
					  LLMessageConfig::NOT_SET);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<6>()
	{
		LLSD config;
		config["capBans"]["MapLayer"] = true;
		config["capBans"]["MapLayerGod"] = false;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure cap ban true MapLayer",
					  LLMessageConfig::isCapBanned("MapLayer"),
					  true);
		ensure_equals("Ensure cap ban false",
					  LLMessageConfig::isCapBanned("MapLayerGod"),
					  false);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<7>()
		// tests that config changes are picked up/refreshed periodically
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "llsd";
		writeConfigFile(config);

		// wait for it to reload after N seconds
		ms_sleep(6*1000);
		LLFrameTimer::updateFrameTime();
		ensure_equals("Ensure reload after 6 seconds",
					  LLMessageConfig::getServerDefaultFlavor(),
					  LLMessageConfig::LLSD_FLAVOR);
	}

	template<> template<>
	void LLMessageConfigTestObject::test<8>()
		// tests that config changes are picked up/refreshed periodically
	{
		LLSD config;
		config["serverDefaults"]["simulator"] = "template";
		config["messages"]["msg1"]["flavor"] = "llsd";
		config["messages"]["msg1"]["only-send-latest"] = true;
		config["messages"]["msg2"]["flavor"] = "llsd";
		config["messages"]["msg2"]["only-send-latest"] = false;
		LLMessageConfig::useConfig(config);
		ensure_equals("Ensure msg1 exists, sent latest-only",
					  LLMessageConfig::onlySendLatest("msg1"),
					  true);
		ensure_equals("Ensure msg2 exists, sent latest-only",
					  LLMessageConfig::onlySendLatest("msg2"),
					  false);
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pyuno_except.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hjs $ $Date: 2003-08-18 15:01:33 $
 *
 *  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: Ralph Thomas
 *
 *   Copyright: 2000 by Sun Microsystems, Inc.
 *
 *   All Rights Reserved.
 *
 *   Contributor(s): Ralph Thomas, Joerg Budischewski
 *
 *
 ************************************************************************/
#include "pyuno_impl.hxx"

#include <rtl/ustrbuf.hxx>

#include <typelib/typedescription.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OUStringToOString;

using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Type;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::TypeDescription;

namespace pyuno
{

void raisePyExceptionWithAny( const com::sun::star::uno::Any &anyExc )
{
    try
    {
        Runtime runtime;
        PyRef exc = runtime.any2PyObject( anyExc );
        if( exc.is() )
        {
            PyRef type( getClass( anyExc.getValueType().getTypeName(),runtime ) );
            PyErr_SetObject( type.get(), exc.get());
        }
        else
        {
            com::sun::star::uno::Exception e;
            anyExc >>= e;

            OUStringBuffer buf;
            buf.appendAscii( "Couldn't convert uno exception to a python exception (" );
            buf.append(anyExc.getValueType().getTypeName());
            buf.appendAscii( ": " );
            buf.append(e.Message );
            buf.appendAscii( ")" );
            PyErr_SetString(
                PyExc_SystemError,
                OUStringToOString(buf.makeStringAndClear(),RTL_TEXTENCODING_ASCII_US) );
        }
    }
    catch( com::sun::star::lang::IllegalArgumentException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
    catch( com::sun::star::script::CannotConvertException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
    catch( RuntimeException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
}

static PyRef createClass( const OUString & name, const Runtime &runtime )
    throw ( RuntimeException )
{
    // assuming that this is never deleted !
    // note I don't have the knowledge how to initialize these type objects correctly !
    TypeDescription desc( name );
    if( ! desc.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pyuno.getClass: uno exception " );
        buf.append(name).appendAscii( " is unknown" );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
    }

    sal_Bool isStruct = desc.get()->eTypeClass == typelib_TypeClass_STRUCT;
    sal_Bool isExc = desc.get()->eTypeClass == typelib_TypeClass_EXCEPTION;
    sal_Bool isInterface = desc.get()->eTypeClass == typelib_TypeClass_INTERFACE;
    if( !isStruct  && !isExc && ! isInterface )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pyuno.getClass: " ).append(name).appendAscii( "is a " );
        buf.appendAscii(
            typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
        buf.appendAscii( ", expected EXCEPTION, STRUCT or INTERFACE" );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>() );
    }

    // retrieve base class
    PyRef base;
    if( isInterface )
    {
        typelib_InterfaceTypeDescription *pDesc = (typelib_InterfaceTypeDescription * )desc.get();
        if( pDesc->pBaseTypeDescription )
        {
            base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime );
        }
        else
        {
            // must be XInterface !
        }
    }
    else
    {
        typelib_CompoundTypeDescription *pDesc = (typelib_CompoundTypeDescription*)desc.get();
        if( pDesc->pBaseTypeDescription )
        {
            base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime );
        }
        else
        {
            if( isExc )
                // we are currently creating the root UNO exception
                base = PyRef(PyExc_Exception);
        }
    }
    PyRef args( PyTuple_New( 3 ), SAL_NO_ACQUIRE );

    PyRef pyTypeName = ustring2PyString( name /*.replace( '.', '_' )*/ );

    PyRef bases;
    if( base.is() )
    {
        { // for CC, keeping ref-count being 1
        bases = PyRef( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        }
        PyTuple_SetItem( bases.get(), 0 , base.getAcquired() );
    }
    else
    {
        bases = PyRef( PyTuple_New( 0 ), SAL_NO_ACQUIRE );
    }

    PyTuple_SetItem( args.get(), 0, pyTypeName.getAcquired());
    PyTuple_SetItem( args.get(), 1, bases.getAcquired() );
    PyTuple_SetItem( args.get(), 2, PyDict_New() );

    PyRef ret(
        PyObject_CallObject(reinterpret_cast<PyObject *>(&PyClass_Type) , args.get()),
        SAL_NO_ACQUIRE );

    // now overwrite ctor and attrib functions
    if( isInterface )
    {
        PyObject_SetAttrString( ret.get(), "__pyunointerface__" , ustring2PyString(name).get() );
    }
    else
    {
        PyRef ctor = getObjectFromUnoModule( runtime,"_uno_struct__init__" );
        PyRef setter = getObjectFromUnoModule( runtime,"_uno_struct__setattr__" );
        PyRef getter = getObjectFromUnoModule( runtime,"_uno_struct__getattr__" );
        PyRef repr = getObjectFromUnoModule( runtime,"_uno_struct__repr__" );
        PyRef eq = getObjectFromUnoModule( runtime,"_uno_struct__eq__" );

        PyObject_SetAttrString( ret.get(), "__pyunostruct__" , ustring2PyString(name).get() );
        PyObject_SetAttrString( ret.get(), "typeName", ustring2PyString(name).get() );
        PyObject_SetAttrString( ret.get(), "__init__" , ctor.get() );
        PyObject_SetAttrString( ret.get(), "__getattr__", getter.get() );
        PyObject_SetAttrString( ret.get(), "__setattr__", setter.get() );
        PyObject_SetAttrString( ret.get(), "__repr__", repr.get() );
        PyObject_SetAttrString( ret.get(), "__str__", repr.get() );
        PyObject_SetAttrString( ret.get(), "__eq__", eq.get() );
    }
    return ret;
}

sal_Bool isInstanceOfStructOrException( const Runtime & runtime, PyObject *obj)
{
    PyRef attr(PyObject_GetAttrString(obj,"__class__"), SAL_NO_ACQUIRE );
    return PyObject_HasAttrString(attr.get(),"__pyunostruct__");
}

sal_Bool isInterfaceClass( const Runtime &runtime, PyObject * obj )
{
    const ClassSet & set = runtime.getImpl()->cargo->interfaceSet;
    return set.find( obj ) != set.end();
}

PyRef getClass( const OUString & name , const Runtime &runtime)
{
    PyRef ret;

    RuntimeCargo *cargo =runtime.getImpl()->cargo;
    ExceptionClassMap::iterator ii = cargo->exceptionMap.find( name );
    if( ii == cargo->exceptionMap.end() )
    {
        ret = createClass( name, runtime );
        cargo->exceptionMap[name] = ret;
        if( PyObject_HasAttrString( ret.get() , "__pyunointerface__" ) )
            cargo->interfaceSet.insert( ret );

        PyObject_SetAttrString( ret.get(), "__pyunointerface__" , ustring2PyString(name).get() );
    }
    else
    {
        ret = ii->second;
    }

    return ret;
}

}
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.54); FILE MERGED 2005/09/05 18:39:21 rt 1.2.54.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_except.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:52:20 $
 *
 *  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
 *
 ************************************************************************/
#include "pyuno_impl.hxx"

#include <rtl/ustrbuf.hxx>

#include <typelib/typedescription.hxx>

using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OUStringToOString;

using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Type;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::TypeDescription;

namespace pyuno
{

void raisePyExceptionWithAny( const com::sun::star::uno::Any &anyExc )
{
    try
    {
        Runtime runtime;
        PyRef exc = runtime.any2PyObject( anyExc );
        if( exc.is() )
        {
            PyRef type( getClass( anyExc.getValueType().getTypeName(),runtime ) );
            PyErr_SetObject( type.get(), exc.get());
        }
        else
        {
            com::sun::star::uno::Exception e;
            anyExc >>= e;

            OUStringBuffer buf;
            buf.appendAscii( "Couldn't convert uno exception to a python exception (" );
            buf.append(anyExc.getValueType().getTypeName());
            buf.appendAscii( ": " );
            buf.append(e.Message );
            buf.appendAscii( ")" );
            PyErr_SetString(
                PyExc_SystemError,
                OUStringToOString(buf.makeStringAndClear(),RTL_TEXTENCODING_ASCII_US) );
        }
    }
    catch( com::sun::star::lang::IllegalArgumentException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
    catch( com::sun::star::script::CannotConvertException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
    catch( RuntimeException & e)
    {
        PyErr_SetString( PyExc_SystemError,
                         OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US) );
    }
}

static PyRef createClass( const OUString & name, const Runtime &runtime )
    throw ( RuntimeException )
{
    // assuming that this is never deleted !
    // note I don't have the knowledge how to initialize these type objects correctly !
    TypeDescription desc( name );
    if( ! desc.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pyuno.getClass: uno exception " );
        buf.append(name).appendAscii( " is unknown" );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
    }

    sal_Bool isStruct = desc.get()->eTypeClass == typelib_TypeClass_STRUCT;
    sal_Bool isExc = desc.get()->eTypeClass == typelib_TypeClass_EXCEPTION;
    sal_Bool isInterface = desc.get()->eTypeClass == typelib_TypeClass_INTERFACE;
    if( !isStruct  && !isExc && ! isInterface )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pyuno.getClass: " ).append(name).appendAscii( "is a " );
        buf.appendAscii(
            typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
        buf.appendAscii( ", expected EXCEPTION, STRUCT or INTERFACE" );
        throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>() );
    }

    // retrieve base class
    PyRef base;
    if( isInterface )
    {
        typelib_InterfaceTypeDescription *pDesc = (typelib_InterfaceTypeDescription * )desc.get();
        if( pDesc->pBaseTypeDescription )
        {
            base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime );
        }
        else
        {
            // must be XInterface !
        }
    }
    else
    {
        typelib_CompoundTypeDescription *pDesc = (typelib_CompoundTypeDescription*)desc.get();
        if( pDesc->pBaseTypeDescription )
        {
            base = getClass( pDesc->pBaseTypeDescription->aBase.pTypeName, runtime );
        }
        else
        {
            if( isExc )
                // we are currently creating the root UNO exception
                base = PyRef(PyExc_Exception);
        }
    }
    PyRef args( PyTuple_New( 3 ), SAL_NO_ACQUIRE );

    PyRef pyTypeName = ustring2PyString( name /*.replace( '.', '_' )*/ );

    PyRef bases;
    if( base.is() )
    {
        { // for CC, keeping ref-count being 1
        bases = PyRef( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        }
        PyTuple_SetItem( bases.get(), 0 , base.getAcquired() );
    }
    else
    {
        bases = PyRef( PyTuple_New( 0 ), SAL_NO_ACQUIRE );
    }

    PyTuple_SetItem( args.get(), 0, pyTypeName.getAcquired());
    PyTuple_SetItem( args.get(), 1, bases.getAcquired() );
    PyTuple_SetItem( args.get(), 2, PyDict_New() );

    PyRef ret(
        PyObject_CallObject(reinterpret_cast<PyObject *>(&PyClass_Type) , args.get()),
        SAL_NO_ACQUIRE );

    // now overwrite ctor and attrib functions
    if( isInterface )
    {
        PyObject_SetAttrString( ret.get(), "__pyunointerface__" , ustring2PyString(name).get() );
    }
    else
    {
        PyRef ctor = getObjectFromUnoModule( runtime,"_uno_struct__init__" );
        PyRef setter = getObjectFromUnoModule( runtime,"_uno_struct__setattr__" );
        PyRef getter = getObjectFromUnoModule( runtime,"_uno_struct__getattr__" );
        PyRef repr = getObjectFromUnoModule( runtime,"_uno_struct__repr__" );
        PyRef eq = getObjectFromUnoModule( runtime,"_uno_struct__eq__" );

        PyObject_SetAttrString( ret.get(), "__pyunostruct__" , ustring2PyString(name).get() );
        PyObject_SetAttrString( ret.get(), "typeName", ustring2PyString(name).get() );
        PyObject_SetAttrString( ret.get(), "__init__" , ctor.get() );
        PyObject_SetAttrString( ret.get(), "__getattr__", getter.get() );
        PyObject_SetAttrString( ret.get(), "__setattr__", setter.get() );
        PyObject_SetAttrString( ret.get(), "__repr__", repr.get() );
        PyObject_SetAttrString( ret.get(), "__str__", repr.get() );
        PyObject_SetAttrString( ret.get(), "__eq__", eq.get() );
    }
    return ret;
}

sal_Bool isInstanceOfStructOrException( const Runtime & runtime, PyObject *obj)
{
    PyRef attr(PyObject_GetAttrString(obj,"__class__"), SAL_NO_ACQUIRE );
    return PyObject_HasAttrString(attr.get(),"__pyunostruct__");
}

sal_Bool isInterfaceClass( const Runtime &runtime, PyObject * obj )
{
    const ClassSet & set = runtime.getImpl()->cargo->interfaceSet;
    return set.find( obj ) != set.end();
}

PyRef getClass( const OUString & name , const Runtime &runtime)
{
    PyRef ret;

    RuntimeCargo *cargo =runtime.getImpl()->cargo;
    ExceptionClassMap::iterator ii = cargo->exceptionMap.find( name );
    if( ii == cargo->exceptionMap.end() )
    {
        ret = createClass( name, runtime );
        cargo->exceptionMap[name] = ret;
        if( PyObject_HasAttrString( ret.get() , "__pyunointerface__" ) )
            cargo->interfaceSet.insert( ret );

        PyObject_SetAttrString( ret.get(), "__pyunointerface__" , ustring2PyString(name).get() );
    }
    else
    {
        ret = ii->second;
    }

    return ret;
}

}
<|endoftext|>