text:
// Copyright 2017 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 "ash/components/arc/session/arc_session_impl.h"

#include <fcntl.h>
#include <grp.h>
#include <poll.h>
#include <unistd.h>

#include <utility>
#include <vector>

#include "ash/components/arc/arc_features.h"
#include "ash/components/arc/arc_util.h"
#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
#include "ash/components/arc/session/arc_bridge_host_impl.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/process_metrics.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/memory/memory.h"
#include "chromeos/system/scheduler_configuration_manager_base.h"
#include "components/user_manager/user_manager.h"
#include "components/version_info/channel.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "mojo/public/cpp/platform/socket_utils_posix.h"
#include "mojo/public/cpp/system/invitation.h"

namespace arc {

namespace {

constexpr char kOn[] = "on";
constexpr char kOff[] = "off";

// Used to classify device based on memory available, 4G, 8GB, 16GB.
constexpr int kClassify4GbDeviceInKb = 3500000;
constexpr int kClassify8GbDeviceInKb = 7500000;
constexpr int kClassify16GbDeviceInKb = 15500000;

std::string GenerateRandomToken() {
  char random_bytes[16];
  base::RandBytes(random_bytes, 16);
  return base::HexEncode(random_bytes, 16);
}

// Waits until |raw_socket_fd| is readable.
// The operation may be cancelled originally triggered by user interaction to
// disable ARC, or ARC instance is unexpectedly stopped (e.g. crash).
// To notify such a situation, |raw_cancel_fd| is also passed to here, and the
// write side will be closed in such a case.
bool WaitForSocketReadable(int raw_socket_fd, int raw_cancel_fd) {
  struct pollfd fds[2] = {
      {raw_socket_fd, POLLIN, 0},
      {raw_cancel_fd, POLLIN, 0},
  };

  if (HANDLE_EINTR(poll(fds, base::size(fds), -1)) <= 0) {
    PLOG(ERROR) << "poll()";
    return false;
  }

  if (fds[1].revents) {
    // Notified that Stop() is invoked. Cancel the Mojo connecting.
    VLOG(1) << "Stop() was called during ConnectMojo()";
    return false;
  }

  DCHECK(fds[0].revents);
  return true;
}

// Applies dalvik memory profile to the ARC mini instance start params.
// Profile is determined based on enable feature and available memory on the
// device. Possible profiles 16G,8G and 4G. For low memory devices dalvik
// profile is not overridden. If |memory_stat_file_for_testing| is set,
// it specifies the file to read in tests instead of /proc/meminfo in
// production.
void ApplyDalvikMemoryProfile(
    ArcSessionImpl::SystemMemoryInfoCallback system_memory_info_callback,
    StartParams* params) {
  base::SystemMemoryInfoKB mem_info;
  if (!system_memory_info_callback.Run(&mem_info)) {
    LOG(ERROR) << "Failed to get system memory info";
    return;
  }

  std::string log_profile_name;
  if (mem_info.total >= kClassify16GbDeviceInKb) {
    params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M16G;
    log_profile_name = "high-memory 16G";
  } else if (mem_info.total >= kClassify8GbDeviceInKb) {
    params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M8G;
    log_profile_name = "high-memory 8G";
  } else if (mem_info.total >= kClassify4GbDeviceInKb) {
    params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M4G;
    log_profile_name = "high-memory 4G";
  } else {
    params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::DEFAULT;
    log_profile_name = "default low-memory";
  }
  VLOG(1) << "Applied " << log_profile_name << " profile for the "
          << (mem_info.total / 1024) << "Mb device.";
}

// Applies USAP profile to the ARC mini instance start params.
// Profile is determined based on enable feature and available memory on the
// device. Possible profiles 16G,8G and 4G. For low memory devices USAP
// profile is not overridden. If |memory_stat_file_for_testing| is set,
// it specifies the file to read in tests instead of /proc/meminfo in
// production.
// Note: This is only used for VM. This profile does nothing for container.
void ApplyUsapProfile(
    ArcSessionImpl::SystemMemoryInfoCallback system_memory_info_callback,
    StartParams* params) {
  // Check if enabled.
  if (!base::FeatureList::IsEnabled(arc::kEnableUsap)) {
    VLOG(1) << "USAP profile is not enabled.";
    return;
  }

  base::SystemMemoryInfoKB mem_info;
  if (!system_memory_info_callback.Run(&mem_info)) {
    LOG(ERROR) << "Failed to get system memory info";
    return;
  }

  if (mem_info.total >= kClassify16GbDeviceInKb) {
    params->usap_profile = StartParams::UsapProfile::M16G;
  } else if (mem_info.total >= kClassify8GbDeviceInKb) {
    params->usap_profile = StartParams::UsapProfile::M8G;
  } else if (mem_info.total >= kClassify4GbDeviceInKb) {
    params->usap_profile = StartParams::UsapProfile::M4G;
  } else {
    params->usap_profile = StartParams::UsapProfile::DEFAULT;
  }
}

void ApplyDisableDownloadProvider(StartParams* params) {
  params->disable_download_provider =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kArcDisableDownloadProvider);
}

void ApplyDisableUreadahed(StartParams* params) {
  params->disable_ureadahead = IsUreadaheadDisabled();
}

// Real Delegate implementation to connect Mojo.
class ArcSessionDelegateImpl : public ArcSessionImpl::Delegate {
 public:
  ArcSessionDelegateImpl(ArcBridgeService* arc_bridge_service,
                         version_info::Channel channel);

  ArcSessionDelegateImpl(const ArcSessionDelegateImpl&) = delete;
  ArcSessionDelegateImpl& operator=(const ArcSessionDelegateImpl&) = delete;

  ~ArcSessionDelegateImpl() override = default;

  // ArcSessionImpl::Delegate override.
  void CreateSocket(CreateSocketCallback callback) override;

  base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
                             ConnectMojoCallback callback) override;
  void GetFreeDiskSpace(GetFreeDiskSpaceCallback callback) override;
  version_info::Channel GetChannel() override;
  std::unique_ptr<ArcClientAdapter> CreateClient() override;

 private:
  // Synchronously create a UNIX domain socket. This is designed to run on a
  // blocking thread. Unlinks any existing files at socket address.
  static base::ScopedFD CreateSocketInternal();

  // Synchronously accepts a connection on |server_endpoint| and then processes
  // the connected socket's file descriptor. This is designed to run on a
  // blocking thread.
  static mojo::ScopedMessagePipeHandle ConnectMojoInternal(
      base::ScopedFD socket_fd,
      base::ScopedFD cancel_fd);

  // Called when Mojo connection is established or canceled.
  // In case of cancel or error, |server_pipe| is invalid.
  void OnMojoConnected(ConnectMojoCallback callback,
                       mojo::ScopedMessagePipeHandle server_pipe);

  // Owned by ArcServiceManager.
  ArcBridgeService* const arc_bridge_service_;

  const version_info::Channel channel_;

  // WeakPtrFactory to use callbacks.
  base::WeakPtrFactory<ArcSessionDelegateImpl> weak_factory_{this};
};

ArcSessionDelegateImpl::ArcSessionDelegateImpl(
    ArcBridgeService* arc_bridge_service,
    version_info::Channel channel)
    : arc_bridge_service_(arc_bridge_service), channel_(channel) {}

void ArcSessionDelegateImpl::CreateSocket(CreateSocketCallback callback) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()},
      base::BindOnce(&ArcSessionDelegateImpl::CreateSocketInternal),
      std::move(callback));
}

base::ScopedFD ArcSessionDelegateImpl::ConnectMojo(
    base::ScopedFD socket_fd,
    ConnectMojoCallback callback) {
  // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
  // Stop().
  base::ScopedFD cancel_fd;
  base::ScopedFD return_fd;
  if (!base::CreatePipe(&cancel_fd, &return_fd, true)) {
    PLOG(ERROR) << "Failed to create a pipe to cancel accept()";
    return base::ScopedFD();
  }

  // For production, |socket_fd| passed from session_manager is either a valid
  // socket or a valid file descriptor (/dev/null). For testing, |socket_fd|
  // might be invalid.
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()},
      base::BindOnce(&ArcSessionDelegateImpl::ConnectMojoInternal,
                     std::move(socket_fd), std::move(cancel_fd)),
      base::BindOnce(&ArcSessionDelegateImpl::OnMojoConnected,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
  return return_fd;
}

void ArcSessionDelegateImpl::GetFreeDiskSpace(
    GetFreeDiskSpaceCallback callback) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()},
      base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
                     base::FilePath("/home")),
      std::move(callback));
}

version_info::Channel ArcSessionDelegateImpl::GetChannel() {
  return channel_;
}

std::unique_ptr<ArcClientAdapter> ArcSessionDelegateImpl::CreateClient() {
  return ArcClientAdapter::Create();
}

// static
base::ScopedFD ArcSessionDelegateImpl::CreateSocketInternal() {
  constexpr char kArcBridgeSocketPath[] = "/run/chrome/arc_bridge.sock";
  constexpr char kArcVmBridgeSocketPath[] = "/run/chrome/arc/arc_bridge.sock";
  constexpr char kArcBridgeSocketGroup[] = "arc-bridge";

  const base::FilePath socket_path(IsArcVmEnabled() ? kArcVmBridgeSocketPath
                                                    : kArcBridgeSocketPath);
  if (IsArcVmEnabled()) {
    base::File::Error error;
    const base::FilePath socket_dir(socket_path.DirName());
    if (!base::CreateDirectoryAndGetError(socket_dir, &error)) {
      LOG(ERROR) << "Failed to create " << socket_dir << ": "
                 << base::File::ErrorToString(error);
      return base::ScopedFD();
    }
    if (!base::SetPosixFilePermissions(socket_dir, 0700)) {
      PLOG(ERROR) << "Could not set permissions: " << socket_dir;
      return base::ScopedFD();
    }
  }

  auto endpoint = mojo::NamedPlatformChannel({socket_path.value()});
  // TODO(cmtm): use NamedPlatformChannel to bootstrap mojo connection after
  // libchrome uprev in android.
  base::ScopedFD socket_fd =
      endpoint.TakeServerEndpoint().TakePlatformHandle().TakeFD();
  if (!socket_fd.is_valid()) {
    LOG(ERROR) << "Socket creation failed";
    return socket_fd;
  }

  // Change permissions on the socket. Note that since arcvm doesn't directly
  // share the socket with ARC, it can use 0600 and the default group. arcvm
  // build doesn't have |kArcBridgeSocketGroup| in the first place.
  if (!IsArcVmEnabled()) {
    struct group arc_bridge_group;
    struct group* arc_bridge_group_res = nullptr;
    int ret = 0;
    char buf[10000];
    do {
      ret = getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf,
                       sizeof(buf), &arc_bridge_group_res);
    } while (ret == EINTR);
    if (ret != 0) {
      LOG(ERROR) << "getgrnam_r: " << strerror_r(ret, buf, sizeof(buf));
      return base::ScopedFD();
    }

    if (!arc_bridge_group_res) {
      LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found";
      return base::ScopedFD();
    }

    if (chown(socket_path.value().c_str(), -1, arc_bridge_group.gr_gid) < 0) {
      PLOG(ERROR) << "chown failed";
      return base::ScopedFD();
    }
  }

  if (!base::SetPosixFilePermissions(socket_path,
                                     IsArcVmEnabled() ? 0600 : 0660)) {
    PLOG(ERROR) << "Could not set permissions: " << socket_path;
    return base::ScopedFD();
  }

  return socket_fd;
}

// static
mojo::ScopedMessagePipeHandle ArcSessionDelegateImpl::ConnectMojoInternal(
    base::ScopedFD socket_fd,
    base::ScopedFD cancel_fd) {
  if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) {
    VLOG(1) << "Mojo connection was cancelled.";
    return mojo::ScopedMessagePipeHandle();
  }

  base::ScopedFD connection_fd;
  if (!mojo::AcceptSocketConnection(socket_fd.get(), &connection_fd,
                                    /* check_peer_user = */ false) ||
      !connection_fd.is_valid()) {
    return mojo::ScopedMessagePipeHandle();
  }

  mojo::PlatformChannel channel;
  mojo::OutgoingInvitation invitation;
  // Generate an arbitrary 32-byte string. ARC uses this length as a protocol
  // version identifier.
  std::string token = GenerateRandomToken();
  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
  mojo::OutgoingInvitation::Send(std::move(invitation),
                                 base::kNullProcessHandle,
                                 channel.TakeLocalEndpoint());

  std::vector<base::ScopedFD> fds;
  fds.emplace_back(channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD());

  // Version of protocol chrome is using.
  uint8_t protocol_version = 0;

  // We need to send the length of the message as a single byte, so make sure it
  // fits.
  DCHECK_LT(token.size(), 256u);
  uint8_t message_length = static_cast<uint8_t>(token.size());

  struct iovec iov[] = {{&protocol_version, sizeof(protocol_version)},
                        {&message_length, sizeof(message_length)},
                        {const_cast<char*>(token.c_str()), token.size()}};
  ssize_t result = mojo::SendmsgWithHandles(connection_fd.get(), iov,
                                            sizeof(iov) / sizeof(iov[0]), fds);
  if (result == -1) {
    PLOG(ERROR) << "sendmsg";
    return mojo::ScopedMessagePipeHandle();
  }

  return pipe;
}

void ArcSessionDelegateImpl::OnMojoConnected(
    ConnectMojoCallback callback,
    mojo::ScopedMessagePipeHandle server_pipe) {
  if (!server_pipe.is_valid()) {
    LOG(ERROR) << "Invalid pipe";
    std::move(callback).Run(nullptr);
    return;
  }

  std::move(callback).Run(std::make_unique<ArcBridgeHostImpl>(
      arc_bridge_service_,
      mojo::PendingReceiver<mojom::ArcBridgeHost>(std::move(server_pipe))));
}

}  // namespace

// static
std::unique_ptr<ArcSessionImpl::Delegate> ArcSessionImpl::CreateDelegate(
    ArcBridgeService* arc_bridge_service,
    version_info::Channel channel) {
  return std::make_unique<ArcSessionDelegateImpl>(arc_bridge_service, channel);
}

ArcSessionImpl::ArcSessionImpl(
    std::unique_ptr<Delegate> delegate,
    chromeos::SchedulerConfigurationManagerBase*
        scheduler_configuration_manager,
    AdbSideloadingAvailabilityDelegate* adb_sideloading_availability_delegate)
    : delegate_(std::move(delegate)),
      client_(delegate_->CreateClient()),
      scheduler_configuration_manager_(scheduler_configuration_manager),
      adb_sideloading_availability_delegate_(
          adb_sideloading_availability_delegate),
      system_memory_info_callback_(
          base::BindRepeating(&base::GetSystemMemoryInfo)) {
  DCHECK(client_);
  client_->AddObserver(this);
}

ArcSessionImpl::~ArcSessionImpl() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
  client_->RemoveObserver(this);
  if (scheduler_configuration_manager_)  // for testing
    scheduler_configuration_manager_->RemoveObserver(this);
}

void ArcSessionImpl::StartMiniInstance() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::NOT_STARTED);

  const auto& last_reply = scheduler_configuration_manager_->GetLastReply();
  if (last_reply) {
    state_ = State::STARTING_MINI_INSTANCE;
    DoStartMiniInstance(last_reply->first ? last_reply->second : 0);
  } else {
    state_ = State::WAITING_FOR_NUM_CORES;
    scheduler_configuration_manager_->AddObserver(this);
  }
}

void ArcSessionImpl::DoStartMiniInstance(size_t num_cores_disabled) {
  DCHECK_GT(lcd_density_, 0);
  StartParams params;
  params.native_bridge_experiment =
      base::FeatureList::IsEnabled(arc::kNativeBridgeToggleFeature);
  params.arc_file_picker_experiment =
      base::FeatureList::IsEnabled(arc::kFilePickerExperimentFeature);
  // Enable Custom Tabs only on Dev and Canary.
  const bool is_custom_tab_enabled =
      base::FeatureList::IsEnabled(arc::kCustomTabsExperimentFeature) &&
      delegate_->GetChannel() != version_info::Channel::STABLE &&
      delegate_->GetChannel() != version_info::Channel::BETA;
  params.arc_custom_tabs_experiment = is_custom_tab_enabled;
  params.enable_keyboard_shortcut_helper_integration =
      base::FeatureList::IsEnabled(
          arc::kKeyboardShortcutHelperIntegrationFeature);
  params.lcd_density = lcd_density_;
  params.num_cores_disabled = num_cores_disabled;
  params.enable_notifications_refresh =
      ash::features::IsNotificationsRefreshEnabled();

  // TODO (b/196460968): Remove after CTS run is complete.
  if (params.enable_notifications_refresh) {
    VLOG(1) << "Notifications Refresh is enabled";
  }

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kArcPlayStoreAutoUpdate)) {
    const std::string value =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            chromeos::switches::kArcPlayStoreAutoUpdate);
    if (value == kOn) {
      params.play_store_auto_update =
          StartParams::PlayStoreAutoUpdate::AUTO_UPDATE_ON;
      VLOG(1) << "Play Store auto-update is forced on";
    } else if (value == kOff) {
      params.play_store_auto_update =
          StartParams::PlayStoreAutoUpdate::AUTO_UPDATE_OFF;
      VLOG(1) << "Play Store auto-update is forced off";
    } else {
      LOG(ERROR) << "Invalid parameter " << value << " for "
                 << chromeos::switches::kArcPlayStoreAutoUpdate;
    }
  }

  params.arc_disable_system_default_app =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kArcDisableSystemDefaultApps);
  if (params.arc_disable_system_default_app)
    VLOG(1) << "System default app(s) are disabled";

  params.disable_media_store_maintenance =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kArcDisableMediaStoreMaintenance);
  if (params.disable_media_store_maintenance)
    VLOG(1) << "MediaStore maintenance task(s) are disabled";

  params.arc_generate_play_auto_install =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kArcGeneratePlayAutoInstall);

  VLOG(1) << "Starting ARC mini instance with lcd_density="
          << params.lcd_density
          << ", num_cores_disabled=" << params.num_cores_disabled;

  ApplyDalvikMemoryProfile(system_memory_info_callback_, &params);
  ApplyUsapProfile(system_memory_info_callback_, &params);
  ApplyDisableDownloadProvider(&params);
  ApplyDisableUreadahed(&params);

  client_->StartMiniArc(std::move(params),
                        base::BindOnce(&ArcSessionImpl::OnMiniInstanceStarted,
                                       weak_factory_.GetWeakPtr()));
}

void ArcSessionImpl::SetSystemMemoryInfoCallbackForTesting(
    SystemMemoryInfoCallback callback) {
  system_memory_info_callback_ = callback;
}

void ArcSessionImpl::RequestUpgrade(UpgradeParams params) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!params.locale.empty());

  upgrade_requested_ = true;
  upgrade_params_ = std::move(params);

  VLOG(1) << "Upgrade requested. state: " << state_;

  switch (state_) {
    case State::NOT_STARTED:
      NOTREACHED();
      break;
    case State::WAITING_FOR_NUM_CORES:
    case State::STARTING_MINI_INSTANCE:
      // OnMiniInstanceStarted() will restart a full instance.
      break;
    case State::RUNNING_MINI_INSTANCE:
      DoUpgrade();
      break;
    case State::STARTING_FULL_INSTANCE:
    case State::CONNECTING_MOJO:
    case State::RUNNING_FULL_INSTANCE:
    case State::STOPPED:
      // These mean RequestUpgrade() is called twice or called after
      // stopped, which are invalid operations.
      NOTREACHED();
      break;
  }
}

void ArcSessionImpl::OnMiniInstanceStarted(bool result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::STARTING_MINI_INSTANCE);

  if (!result) {
    LOG(ERROR) << "Failed to start ARC mini container";
    OnStopped(ArcStopReason::GENERIC_BOOT_FAILURE);
    return;
  }

  VLOG(2) << "ARC mini container has been successfully started.";
  state_ = State::RUNNING_MINI_INSTANCE;

  if (stop_requested_) {
    // The ARC instance has started to run. Request to stop.
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  if (upgrade_requested_)
    // RequestUpgrade() has been called during the D-Bus call.
    DoUpgrade();
}

void ArcSessionImpl::DoUpgrade() {
  DCHECK_EQ(state_, State::RUNNING_MINI_INSTANCE);

  VLOG(2) << "Upgrading an existing ARC mini instance";
  state_ = State::STARTING_FULL_INSTANCE;

  // Getting the free disk space doesn't take long.
  delegate_->GetFreeDiskSpace(base::BindOnce(&ArcSessionImpl::OnFreeDiskSpace,
                                             weak_factory_.GetWeakPtr()));
}

void ArcSessionImpl::OnFreeDiskSpace(int64_t space) {
  // Ensure there's sufficient space on disk for the container.
  if (space == -1) {
    LOG(ERROR) << "Could not determine free disk space";
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  } else if (space < kMinimumFreeDiskSpaceBytes) {
    VLOG(1) << "There is not enough disk space to start the ARC container";
    insufficient_disk_space_ = true;
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  adb_sideloading_availability_delegate_->CanChangeAdbSideloading(
      base::BindOnce(&ArcSessionImpl::OnCanChangeAdbSideloading,
                     weak_factory_.GetWeakPtr()));
}

void ArcSessionImpl::OnCanChangeAdbSideloading(
    bool can_change_adb_sideloading) {
  upgrade_params_.is_managed_adb_sideloading_allowed =
      can_change_adb_sideloading;

  delegate_->CreateSocket(base::BindOnce(&ArcSessionImpl::OnSocketCreated,
                                         weak_factory_.GetWeakPtr()));
}

void ArcSessionImpl::OnSocketCreated(base::ScopedFD socket_fd) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::STARTING_FULL_INSTANCE);

  if (stop_requested_) {
    // The ARC instance has started to run. Request to stop.
    VLOG(1) << "Stop() called while creating socket";
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  if (!socket_fd.is_valid()) {
    LOG(ERROR) << "ARC: Error creating socket";
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  VLOG(2) << "Socket is created. Start loading ARC data snapshot";
  StartLoadingDataSnapshot(base::BindOnce(&ArcSessionImpl::OnDataSnapshotLoaded,
                                          weak_factory_.GetWeakPtr(),
                                          std::move(socket_fd)));
}

void ArcSessionImpl::StartLoadingDataSnapshot(base::OnceClosure callback) {
  auto* arc_data_snapshotd_manager =
      arc::data_snapshotd::ArcDataSnapshotdManager::Get();
  if (arc_data_snapshotd_manager)
    arc_data_snapshotd_manager->StartLoadingSnapshot(std::move(callback));
  else
    std::move(callback).Run();
}

void ArcSessionImpl::OnDataSnapshotLoaded(base::ScopedFD socket_fd) {
  VLOG(2) << "Starting ARC container";
  client_->UpgradeArc(
      std::move(upgrade_params_),
      base::BindOnce(&ArcSessionImpl::OnUpgraded, weak_factory_.GetWeakPtr(),
                     std::move(socket_fd)));
}

void ArcSessionImpl::OnUpgraded(base::ScopedFD socket_fd, bool result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::STARTING_FULL_INSTANCE);

  if (!result) {
    LOG(ERROR) << "Failed to upgrade ARC container";
    return;
  }

  VLOG(2) << "ARC instance is successfully upgraded.";

  if (stop_requested_) {
    // The ARC instance has started to run. Request to stop.
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  VLOG(2) << "Connecting mojo...";
  state_ = State::CONNECTING_MOJO;
  accept_cancel_pipe_ = delegate_->ConnectMojo(
      std::move(socket_fd), base::BindOnce(&ArcSessionImpl::OnMojoConnected,
                                           weak_factory_.GetWeakPtr()));
  if (!accept_cancel_pipe_.is_valid()) {
    // Failed to post a task to accept() the request.
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }
}

void ArcSessionImpl::OnMojoConnected(
    std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::CONNECTING_MOJO);
  accept_cancel_pipe_.reset();

  if (stop_requested_) {
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
    return;
  }

  if (!arc_bridge_host.get()) {
    LOG(ERROR) << "Invalid pipe.";
    // If we can't establish the connection with ARC bridge, it could
    // be a problem inside ARC thus setting |should_backup_log| to back up log
    // before container is shutdown.
    StopArcInstance(/*on_shutdown=*/false, /*should_backup_log*/ true);
    return;
  }
  arc_bridge_host_ = std::move(arc_bridge_host);

  VLOG(0) << "ARC ready.";
  state_ = State::RUNNING_FULL_INSTANCE;

  // Some memory parameters may be changed when ARC is launched.
  chromeos::UpdateMemoryParameters();
}

void ArcSessionImpl::Stop() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  VLOG(2) << "Stopping ARC session is requested.";

  // For second time or later, just do nothing.
  // It is already in the stopping phase.
  if (stop_requested_)
    return;

  stop_requested_ = true;
  arc_bridge_host_.reset();
  switch (state_) {
    case State::WAITING_FOR_NUM_CORES:
      if (scheduler_configuration_manager_)  // for testing
        scheduler_configuration_manager_->RemoveObserver(this);
      FALLTHROUGH;
    case State::NOT_STARTED:
      // If |Stop()| is called while waiting for LCD density or CPU cores
      // information, it can directly move to stopped state.
      VLOG(1) << "ARC session is not started. state: " << state_;
      OnStopped(ArcStopReason::SHUTDOWN);
      return;
    case State::STARTING_MINI_INSTANCE:
    case State::STARTING_FULL_INSTANCE:
      // Before starting the ARC instance, we do nothing here.
      // At some point, a callback will be invoked on UI thread,
      // and stopping procedure will be run there.
      // On Chrome shutdown, it is not the case because the message loop is
      // already stopped here. Practically, it is not a problem because;
      // - On starting instance, the container instance can be leaked.
      // Practically it is not problematic because the session manager will
      // clean it up.
      return;

    case State::RUNNING_MINI_INSTANCE:
    case State::RUNNING_FULL_INSTANCE:
      // An ARC {mini,full} instance is running. Request to stop it.
      StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/false);
      return;

    case State::CONNECTING_MOJO:
      // Mojo connection is being waited on ThreadPool's thread.
      // Request to cancel it. Following stopping procedure will run
      // in its callback.
      accept_cancel_pipe_.reset();
      return;

    case State::STOPPED:
      VLOG(1) << "ARC session is already stopped.";
      // The instance is already stopped. Do nothing.
      return;
  }
}

void ArcSessionImpl::StopArcInstance(bool on_shutdown, bool should_backup_log) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(state_ == State::WAITING_FOR_NUM_CORES ||
         state_ == State::STARTING_MINI_INSTANCE ||
         state_ == State::RUNNING_MINI_INSTANCE ||
         state_ == State::STARTING_FULL_INSTANCE ||
         state_ == State::CONNECTING_MOJO ||
         state_ == State::RUNNING_FULL_INSTANCE);

  VLOG(1) << "Requesting session_manager to stop ARC instance"
          << " on_shutdown: " << on_shutdown
          << " should_backup_log: " << should_backup_log;

  // When the instance is full instance, change the |state_| in
  // ArcInstanceStopped().
  client_->StopArcInstance(on_shutdown, should_backup_log);
}

void ArcSessionImpl::ArcInstanceStopped(bool is_system_shutdown) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_NE(state_, State::STARTING_MINI_INSTANCE);
  VLOG(1) << "Notified that ARC instance is stopped";

  // In case that crash happens during before the Mojo channel is connected,
  // unlock the ThreadPool's thread.
  accept_cancel_pipe_.reset();

  ArcStopReason reason;
  if (stop_requested_ || is_system_shutdown) {
    // If the ARC instance is stopped after its explicit request or as part of
    // system shutdown, return SHUTDOWN.
    reason = ArcStopReason::SHUTDOWN;
  } else if (insufficient_disk_space_) {
    // ARC mini container is stopped because of upgarde failure due to low
    // disk space.
    reason = ArcStopReason::LOW_DISK_SPACE;
  } else if (state_ == State::STARTING_FULL_INSTANCE ||
             state_ == State::CONNECTING_MOJO) {
    // If the ARC instance is stopped during the upgrade, but it is not
    // explicitly requested, return GENERIC_BOOT_FAILURE for the case.
    reason = ArcStopReason::GENERIC_BOOT_FAILURE;
  } else {
    // Otherwise, this is caused by CRASH occured inside of the ARC instance.
    reason = ArcStopReason::CRASH;
  }
  OnStopped(reason);
}

bool ArcSessionImpl::IsStopRequested() {
  return stop_requested_;
}

void ArcSessionImpl::OnStopped(ArcStopReason reason) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // OnStopped() should be called once per instance.
  DCHECK_NE(state_, State::STOPPED);
  VLOG(1) << "ARC session is stopped."
          << " reason: " << reason << " state: " << state_;

  const bool was_running = (state_ == State::RUNNING_FULL_INSTANCE);
  arc_bridge_host_.reset();
  state_ = State::STOPPED;
  for (auto& observer : observer_list_)
    observer.OnSessionStopped(reason, was_running, upgrade_requested_);
}

void ArcSessionImpl::OnShutdown() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  stop_requested_ = true;
  if (state_ == State::STOPPED)
    return;

  // Here, the message loop is already stopped, and the Chrome will be soon
  // shutdown. Thus, it is not necessary to take care about restarting case.
  // If ArcSession is waiting for mojo connection, cancels it.
  accept_cancel_pipe_.reset();

  // Stops the ARC instance to let it graceful shutdown.
  // Note that this may fail if ARC container is not actually running, but
  // ignore an error as described below.
  if (state_ == State::STARTING_MINI_INSTANCE ||
      state_ == State::RUNNING_MINI_INSTANCE ||
      state_ == State::STARTING_FULL_INSTANCE ||
      state_ == State::CONNECTING_MOJO ||
      state_ == State::RUNNING_FULL_INSTANCE) {
    StopArcInstance(/*on_shutdown=*/true, /*should_backup_log*/ false);
  }

  // Directly set to the STOPPED state by OnStopped(). Note that calling
  // StopArcInstance() may not work well. At least, because the UI thread is
  // already stopped here, ArcInstanceStopped() callback cannot be invoked.
  OnStopped(ArcStopReason::SHUTDOWN);
}

void ArcSessionImpl::SetUserInfo(
    const cryptohome::Identification& cryptohome_id,
    const std::string& hash,
    const std::string& serial_number) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  client_->SetUserInfo(cryptohome_id, hash, serial_number);
}

void ArcSessionImpl::SetDemoModeDelegate(
    ArcClientAdapter::DemoModeDelegate* delegate) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  client_->SetDemoModeDelegate(delegate);
}

void ArcSessionImpl::TrimVmMemory(TrimVmMemoryCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  client_->TrimVmMemory(std::move(callback));
}

void ArcSessionImpl::SetDefaultDeviceScaleFactor(float scale_factor) {
  lcd_density_ = GetLcdDensityForDeviceScaleFactor(scale_factor);
  DCHECK_GT(lcd_density_, 0);
}

void ArcSessionImpl::OnConfigurationSet(bool success,
                                        size_t num_cores_disabled) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, State::WAITING_FOR_NUM_CORES);

  scheduler_configuration_manager_->RemoveObserver(this);
  state_ = State::STARTING_MINI_INSTANCE;

  // Note: On non-x86_64 devices, the configuration request to debugd always
  // fails. It is WAI, and to support that case, don't log anything even when
  // |success| is false. |num_cores_disabled| is always set regardless of
  // where the call is successful.
  DoStartMiniInstance(num_cores_disabled);
}

std::ostream& operator<<(std::ostream& os, ArcSessionImpl::State state) {
#define MAP_STATE(name)             \
  case ArcSessionImpl::State::name: \
    return os << #name

  switch (state) {
    MAP_STATE(NOT_STARTED);
    MAP_STATE(WAITING_FOR_NUM_CORES);
    MAP_STATE(STARTING_MINI_INSTANCE);
    MAP_STATE(RUNNING_MINI_INSTANCE);
    MAP_STATE(STARTING_FULL_INSTANCE);
    MAP_STATE(CONNECTING_MOJO);
    MAP_STATE(RUNNING_FULL_INSTANCE);
    MAP_STATE(STOPPED);
  }
#undef MAP_STATE

  // Some compilers report an error even if all values of an enum-class are
  // covered exhaustively in a switch statement.
  NOTREACHED() << "Invalid value " << static_cast<int>(state);
  return os;
}

}  // namespace arc


text:
layout: post
title: "simple event hooks in Rust"
date: November 3, 2017
categories:
- rust
- code
description: 'how to implement a simple events hook system in Rust using the Observer Pattern'
keywords: rust, pub-sub, events hook, event driven programming
author: Matt
---

## What

The **observer pattern** is a software design pattern in which an object, called the subject, maintains
a list of its dependents, called observers, and notifies them automatically of any state changes,
usually by calling one of their methods. [1][1]

**Event hooks** (or callbacks) are a simple way of implementing the observer pattern where a the
subject notifies the observers when certain events occurs.

## Why

Event hooks can be used to implement event-driven programming, where the flow of the program is
determined by events such as user actions, sensor outputs, or  messages from other programs/threads.[2][2]

## How

We use Rust's [traits][3] feature to define the expected behaviour of our events interface. The
trait will contain the event hooks that the event handlers are supposed to implement.

The use of trait makes our event handlers to be generic (they can be of any type), all that will be
required of them is to have an implementation of the trait.

For illustration, I'll implement an event-driven Logger that records tcp connection events.

Below is a trait that implements an events interface for a tcp socket communication

```rust
#[allow(unused_variables)]
pub trait Events {
    fn on_connect(&self, host: &str, port: i32) {}
    fn on_error(&self, err: &str) {}
    fn on_read(&self, resp: &[u8]) {}
    fn on_shutdown(&self) {}
    fn on_pre_read(&self) {}
    fn on_post_read(&self) {}
}
```

Then, a simple **Logger** struct implements the trait as follows

```rust
struct Logger;

impl Events for Logger {
    fn on_connect(&self, host: &str, port: i32) {
        println!("Connected to {} on port {}", host, port);
    }

    fn on_error(&self, err: &str) {
        println!("error: {}", err);
    }

    fn on_read(&self, resp: &[u8]) {
        print!("{}", str::from_utf8(resp).unwrap());
    }

    fn on_shutdown(&self) {
        println!("Connection closed.");
    }

    fn on_pre_read(&self) {
        println!("Receiving content:\n");
    }

    fn on_post_read(&self) {
        println!("\nFinished receiving content.")
    }
}
```
The **Logger** acts as the Observer that gets notified when events occur.

Next, we have a **HttpClient** struct that does some tcp network calls and notifies its registered hooks
(observers) when the events occurs.

```rust
struct HttpClient {
    host: String,
    port: i32,
    hooks: Vec<Box<Events>>,
}

impl HttpClient {
    pub fn new(host: &str, port: i32) -> Self {
        Self {
            host: host.to_owned(),
            port: port,
            hooks: Vec::new(),
        }
    }

    pub fn add_events_hook<E: Events + 'static>(&mut self, hook: E) {
        self.hooks.push(Box::new(hook));
    }

    pub fn get(&self, endpoint: &str) {
        let cmd = format!("GET {} HTTP/1.1\r\nHost: {}\r\n\r\n", endpoint, self.host).into_bytes();
        let mut socket = self.connect().unwrap();
        socket.write(cmd.as_slice()).unwrap();
        socket.flush().unwrap();
        for hook in &self.hooks {
            hook.on_pre_read();
        }
        loop {
            let mut buf = vec![0; 512usize];
            let cnt = socket.read(&mut buf[..]).unwrap();
            buf.truncate(cnt);
            if !buf.is_empty() {
                for hook in &self.hooks {
                    hook.on_read(buf.as_slice());
                }
            } else {
                for hook in &self.hooks {
                    hook.on_post_read();
                }
                break;
            }
        }
        for hook in &self.hooks {
            hook.on_shutdown();
        }

    }

    pub fn connect(&self) -> io::Result<TcpStream>{
        let addr = format!("{}:{}", self.host, self.port);
        match TcpStream::connect(addr) {
            Ok(stream) => {
                for hook in &self.hooks {
                    hook.on_connect(&self.host, self.port);
                }
                Ok(stream)
            },
            Err(error) => {
                for hook in &self.hooks {
                    hook.on_error(error.description());
                }
                Err(error)
            },
        }

    }
}
```

The **HttpClient** struct implements a **add_events_hook** method that is used to register the events handlers.

To piece all together, we have a **main** function that:
* initializes the **HttpClient** struct.
* registers the **Logger** has an event hooks handler for **HttpClient**
* makes a network call using **HttpClient**. This results in the **Logger** receiving events.

```rust
fn main() {
    let mut  http_stream = HttpClient::new("httpbin.org", 80);
    http_stream.add_events_hook(Logger);
    http_stream.get("/ip");
}
```

The **Logger** will log the events to the terminal:

```
Connected to httpbin.org on port 80
Receiving content:

HTTP/1.1 200 OK
Connection: keep-alive
Server: meinheld/0.6.1
Date: Fri, 03 Nov 2017 09:16:40 GMT
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0.000749111175537
Content-Length: 33
Via: 1.1 vegur

{
  "origin": "212.22.171.150"
}

Finished receiving content.
Connection closed.
```
Voila! That's a simple implementation of event hooks in Rust. The complete code can be found
[here](https://gist.github.com/mattgathu/73712cb7399834d6f8162d641830cbb7)

## Footnotes

There is a lot of event driven work being done using Rust and here are some interesting projects
that you can check out:
* [mio][4] -  a lightweight I/O library for Rust.
* [ws-rs][5] - Lightweight, event-driven WebSockets for Rust.
* [tokio-core][6] - I/O primitives and event loop for async I/O in Rust

## References

1. <https://en.wikipedia.org/wiki/Observer_pattern>
2. <https://en.wikipedia.org/wiki/Event-driven_programming>
3. <https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html>
4. <https://doc.rust-lang.org/book/second-edition/ch19-03-advanced-traits.html>
5. <https://doc.rust-lang.org/std/net/struct.TcpStream.html>
6. <https://github.com/seanmonstar/reqwest/issues/155>

[1]: https://en.wikipedia.org/wiki/Observer_pattern
[2]: https://en.wikipedia.org/wiki/Event-driven_programming
[3]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html
[4]: https://github.com/carllerche/mio
[5]: https://github.com/housleyjk/ws-rs
[6]: https://github.com/tokio-rs/tokio-core

redpajama_set_name: RedPajamaGithub


text:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <math.h>

#include "RayTracer/JSONValue.h"

// Macros to free an array/object
#define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }
#define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter).second; } }

/**
 * Parses a JSON encoded value to a JSONValue object
 *
 * @access protected
 *
 * @param wchar_t** data Pointer to a wchar_t* that contains the data
 *
 * @return JSONValue* Returns a pointer to a JSONValue object on success, NULL on error
 */
JSONValue *JSONValue::Parse(const wchar_t **data)
{
	// Is it a string?
	if (**data == '"')
	{
		std::wstring str;
		if (!JSON::ExtractString(&(++(*data)), str))
			return NULL;
		else
			return new JSONValue(str);
	}

	// Is it a boolean?
	else if ((simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"true", 4) == 0) || (simplejson_wcsnlen(*data, 5) && wcsncasecmp(*data, L"false", 5) == 0))
	{
		bool value = wcsncasecmp(*data, L"true", 4) == 0;
		(*data) += value ? 4 : 5;
		return new JSONValue(value);
	}

	// Is it a null?
	else if (simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"null", 4) == 0)
	{
		(*data) += 4;
		return new JSONValue();
	}

	// Is it a number?
	else if (**data == L'-' || (**data >= L'0' && **data <= L'9'))
	{
		// Negative?
		bool neg = **data == L'-';
		if (neg) (*data)++;

		double number = 0.0;

		// Parse the whole part of the number - only if it wasn't 0
		if (**data == L'0')
			(*data)++;
		else if (**data >= L'1' && **data <= L'9')
			number = JSON::ParseInt(data);
		else
			return NULL;

		// Could be a decimal now...
		if (**data == '.')
		{
			(*data)++;

			// Not get any digits?
			if (!(**data >= L'0' && **data <= L'9'))
				return NULL;

			// Find the decimal and sort the decimal place out
			// Use ParseDecimal as ParseInt won't work with decimals less than 0.1
			// thanks to Javier Abadia for the report & fix
			double decimal = JSON::ParseDecimal(data);

			// Save the number
			number += decimal;
		}

		// Could be an exponent now...
		if (**data == L'E' || **data == L'e')
		{
			(*data)++;

			// Check signage of expo
			bool neg_expo = false;
			if (**data == L'-' || **data == L'+')
			{
				neg_expo = **data == L'-';
				(*data)++;
			}

			// Not get any digits?
			if (!(**data >= L'0' && **data <= L'9'))
				return NULL;

			// Sort the expo out
			double expo = JSON::ParseInt(data);
			for (double i = 0.0; i < expo; i++)
				number = neg_expo ? (number / 10.0) : (number * 10.0);
		}

		// Was it neg?
		if (neg) number *= -1;

		return new JSONValue(number);
	}

	// An object?
	else if (**data == L'{')
	{
		JSONObject object;

		(*data)++;

		while (**data != 0)
		{
			// Whitespace at the start?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// Special case - empty object
			if (object.size() == 0 && **data == L'}')
			{
				(*data)++;
				return new JSONValue(object);
			}

			// We want a string now...
			std::wstring name;
			if (!JSON::ExtractString(&(++(*data)), name))
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// More whitespace?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// Need a : now
			if (*((*data)++) != L':')
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// More whitespace?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// The value is here
			JSONValue *value = Parse(data);
			if (value == NULL)
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// Add the name:value
			if (object.find(name) != object.end())
				delete object[name];
			object[name] = value;

			// More whitespace?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_OBJECT(object);
				return NULL;
			}

			// End of object?
			if (**data == L'}')
			{
				(*data)++;
				return new JSONValue(object);
			}

			// Want a , now
			if (**data != L',')
			{
				FREE_OBJECT(object);
				return NULL;
			}

			(*data)++;
		}

		// Only here if we ran out of data
		FREE_OBJECT(object);
		return NULL;
	}

	// An array?
	else if (**data == L'[')
	{
		JSONArray array;

		(*data)++;

		while (**data != 0)
		{
			// Whitespace at the start?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_ARRAY(array);
				return NULL;
			}

			// Special case - empty array
			if (array.size() == 0 && **data == L']')
			{
				(*data)++;
				return new JSONValue(array);
			}

			// Get the value
			JSONValue *value = Parse(data);
			if (value == NULL)
			{
				FREE_ARRAY(array);
				return NULL;
			}

			// Add the value
			array.push_back(value);

			// More whitespace?
			if (!JSON::SkipWhitespace(data))
			{
				FREE_ARRAY(array);
				return NULL;
			}

			// End of array?
			if (**data == L']')
			{
				(*data)++;
				return new JSONValue(array);
			}

			// Want a , now
			if (**data != L',')
			{
				FREE_ARRAY(array);
				return NULL;
			}

			(*data)++;
		}

		// Only here if we ran out of data
		FREE_ARRAY(array);
		return NULL;
	}

	// Ran out of possibilites, it's bad!
	else
	{
		return NULL;
	}
}

/**
 * Basic constructor for creating a JSON Value of type NULL
 *
 * @access public
 */
JSONValue::JSONValue(/*NULL*/)
{
	type = JSONType_Null;
}

/**
 * Basic constructor for creating a JSON Value of type String
 *
 * @access public
 *
 * @param wchar_t* m_char_value The string to use as the value
 */
JSONValue::JSONValue(const wchar_t *m_char_value)
{
	type = JSONType_String;
	string_value = std::wstring(m_char_value);
}

/**
 * Basic constructor for creating a JSON Value of type String
 *
 * @access public
 *
 * @param std::wstring m_string_value The string to use as the value
 */
JSONValue::JSONValue(const std::wstring &m_string_value)
{
	type = JSONType_String;
	string_value = m_string_value;
}

/**
 * Basic constructor for creating a JSON Value of type Bool
 *
 * @access public
 *
 * @param bool m_bool_value The bool to use as the value
 */
JSONValue::JSONValue(bool m_bool_value)
{
	type = JSONType_Bool;
	bool_value = m_bool_value;
}

/**
 * Basic constructor for creating a JSON Value of type Number
 *
 * @access public
 *
 * @param double m_number_value The number to use as the value
 */
JSONValue::JSONValue(double m_number_value)
{
	type = JSONType_Number;
	number_value = m_number_value;
}

/**
 * Basic constructor for creating a JSON Value of type Array
 *
 * @access public
 *
 * @param JSONArray m_array_value The JSONArray to use as the value
 */
JSONValue::JSONValue(const JSONArray &m_array_value)
{
	type = JSONType_Array;
	array_value = m_array_value;
}

/**
 * Basic constructor for creating a JSON Value of type Object
 *
 * @access public
 *
 * @param JSONObject m_object_value The JSONObject to use as the value
 */
JSONValue::JSONValue(const JSONObject &m_object_value)
{
	type = JSONType_Object;
	object_value = m_object_value;
}

/**
 * The destructor for the JSON Value object
 * Handles deleting the objects in the array or the object value
 *
 * @access public
 */
JSONValue::~JSONValue()
{
	if (type == JSONType_Array)
	{
		JSONArray::iterator iter;
		for (iter = array_value.begin(); iter != array_value.end(); iter++)
			delete *iter;
	}
	else if (type == JSONType_Object)
	{
		JSONObject::iterator iter;
		for (iter = object_value.begin(); iter != object_value.end(); iter++)
		{
			delete (*iter).second;
		}
	}
}

/**
 * Checks if the value is a NULL
 *
 * @access public
 *
 * @return bool Returns true if it is a NULL value, false otherwise
 */
bool JSONValue::IsNull() const
{
	return type == JSONType_Null;
}

/**
 * Checks if the value is a String
 *
 * @access public
 *
 * @return bool Returns true if it is a String value, false otherwise
 */
bool JSONValue::IsString() const
{
	return type == JSONType_String;
}

/**
 * Checks if the value is a Bool
 *
 * @access public
 *
 * @return bool Returns true if it is a Bool value, false otherwise
 */
bool JSONValue::IsBool() const
{
	return type == JSONType_Bool;
}

/**
 * Checks if the value is a Number
 *
 * @access public
 *
 * @return bool Returns true if it is a Number value, false otherwise
 */
bool JSONValue::IsNumber() const
{
	return type == JSONType_Number;
}

/**
 * Checks if the value is an Array
 *
 * @access public
 *
 * @return bool Returns true if it is an Array value, false otherwise
 */
bool JSONValue::IsArray() const
{
	return type == JSONType_Array;
}

/**
 * Checks if the value is an Object
 *
 * @access public
 *
 * @return bool Returns true if it is an Object value, false otherwise
 */
bool JSONValue::IsObject() const
{
	return type == JSONType_Object;
}

/**
 * Retrieves the String value of this JSONValue
 * Use IsString() before using this method.
 *
 * @access public
 *
 * @return std::wstring Returns the string value
 */
const std::wstring &JSONValue::AsString() const
{
	return string_value;
}

/**
 * Retrieves the Bool value of this JSONValue
 * Use IsBool() before using this method.
 *
 * @access public
 *
 * @return bool Returns the bool value
 */
bool JSONValue::AsBool() const
{
	return bool_value;
}

/**
 * Retrieves the Number value of this JSONValue
 * Use IsNumber() before using this method.
 *
 * @access public
 *
 * @return double Returns the number value
 */
double JSONValue::AsNumber() const
{
	return number_value;
}

/**
 * Retrieves the Array value of this JSONValue
 * Use IsArray() before using this method.
 *
 * @access public
 *
 * @return JSONArray Returns the array value
 */
const JSONArray &JSONValue::AsArray() const
{
	return array_value;
}

/**
 * Retrieves the Object value of this JSONValue
 * Use IsObject() before using this method.
 *
 * @access public
 *
 * @return JSONObject Returns the object value
 */
const JSONObject &JSONValue::AsObject() const
{
	return object_value;
}

/**
 * Retrieves the number of children of this JSONValue.
 * This number will be 0 or the actual number of children
 * if IsArray() or IsObject().
 *
 * @access public
 *
 * @return The number of children.
 */
std::size_t JSONValue::CountChildren() const
{
	switch (type)
	{
		case JSONType_Array:
			return array_value.size();
		case JSONType_Object:
			return object_value.size();
		default:
			return 0;
	}
}

/**
 * Checks if this JSONValue has a child at the given index.
 * Use IsArray() before using this method.
 *
 * @access public
 *
 * @return bool Returns true if the array has a value at the given index.
 */
bool JSONValue::HasChild(std::size_t index) const
{
	if (type == JSONType_Array)
	{
		return index < array_value.size();
	}
	else
	{
		return false;
	}
}

/**
 * Retrieves the child of this JSONValue at the given index.
 * Use IsArray() before using this method.
 *
 * @access public
 *
 * @return JSONValue* Returns JSONValue at the given index or NULL
 *                    if it doesn't exist.
 */
JSONValue *JSONValue::Child(std::size_t index)
{
	if (index < array_value.size())
	{
		return array_value[index];
	}
	else
	{
		return NULL;
	}
}

/**
 * Checks if this JSONValue has a child at the given key.
 * Use IsObject() before using this method.
 *
 * @access public
 *
 * @return bool Returns true if the object has a value at the given key.
 */
bool JSONValue::HasChild(const wchar_t* name) const
{
	if (type == JSONType_Object)
	{
		return object_value.find(name) != object_value.end();
	}
	else
	{
		return false;
	}
}

/**
 * Retrieves the child of this JSONValue at the given key.
 * Use IsObject() before using this method.
 *
 * @access public
 *
 * @return JSONValue* Returns JSONValue for the given key in the object
 *                    or NULL if it doesn't exist.
 */
JSONValue* JSONValue::Child(const wchar_t* name)
{
	JSONObject::const_iterator it = object_value.find(name);
	if (it != object_value.end())
	{
		return it->second;
	}
	else
	{
		return NULL;
	}
}

/**
 * Creates a JSON encoded string for the value with all necessary characters escaped
 *
 * @access public
 *
 * @return std::wstring Returns the JSON string
 */
std::wstring JSONValue::Stringify() const
{
	std::wstring ret_string;

	switch (type)
	{
		case JSONType_Null:
			ret_string = L"null";
			break;

		case JSONType_String:
			ret_string = StringifyString(string_value);
			break;

		case JSONType_Bool:
			ret_string = bool_value ? L"true" : L"false";
			break;

		case JSONType_Number:
		{
			if (isinf(number_value) || isnan(number_value))
				ret_string = L"null";
			else
			{
				std::wstringstream ss;
				ss.precision(15);
				ss << number_value;
				ret_string = ss.str();
			}
			break;
		}

		case JSONType_Array:
		{
			ret_string = L"[";
			JSONArray::const_iterator iter = array_value.begin();
			while (iter != array_value.end())
			{
				ret_string += (*iter)->Stringify();

				// Not at the end - add a separator
				if (++iter != array_value.end())
					ret_string += L",";
			}
			ret_string += L"]";
			break;
		}

		case JSONType_Object:
		{
			ret_string = L"{";
			JSONObject::const_iterator iter = object_value.begin();
			while (iter != object_value.end())
			{
				ret_string += StringifyString((*iter).first);
				ret_string += L":";
				ret_string += (*iter).second->Stringify();

				// Not at the end - add a separator
				if (++iter != object_value.end())
					ret_string += L",";
			}
			ret_string += L"}";
			break;
		}
	}

	return ret_string;
}

/**
 * Creates a JSON encoded string with all required fields escaped
 * Works from http://www.ecma-internationl.org/publications/files/ECMA-ST/ECMA-262.pdf
 * Section 15.12.3.
 *
 * @access private
 *
 * @param std::wstring str The string that needs to have the characters escaped
 *
 * @return std::wstring Returns the JSON string
 */
std::wstring JSONValue::StringifyString(const std::wstring &str)
{
	std::wstring str_out = L"\"";

	std::wstring::const_iterator iter = str.begin();
	while (iter != str.end())
	{
		wchar_t chr = *iter;

		if (chr == L'"' || chr == L'\\' || chr == L'/')
		{
			str_out += L'\\';
			str_out += chr;
		}
		else if (chr == L'\b')
		{
			str_out += L"\\b";
		}
		else if (chr == L'\f')
		{
			str_out += L"\\f";
		}
		else if (chr == L'\n')
		{
			str_out += L"\\n";
		}
		else if (chr == L'\r')
		{
			str_out += L"\\r";
		}
		else if (chr == L'\t')
		{
			str_out += L"\\t";
		}
		else if (chr < L' ')
		{
			str_out += L"\\u";
			for (int i = 0; i < 4; i++)
			{
				int value = (chr >> 12) & 0xf;
				if (value >= 0 && value <= 9)
					str_out += (wchar_t)('0' + value);
				else if (value >= 10 && value <= 15)
					str_out += (wchar_t)('A' + (value - 10));
				chr <<= 4;
			}
		}
		else
		{
			str_out += chr;
		}

		iter++;
	}

	str_out += L"\"";
	return str_out;
}


text:
'use strict';

const chai = require('chai');

const expect = chai.expect;
const Support = require('../../support');

const current = Support.sequelize;
const sinon = require('sinon');
const { DataTypes, Sequelize } = require('@sequelize/core');

describe(Support.getTestDialectTeaser('Model'), () => {
  describe('method findByPk', () => {
    beforeEach(function () {
      this.stub = sinon.stub(Sequelize.Model, 'findAll').resolves();
    });
    afterEach(() => {
      sinon.restore();
    });

    it('should call internal findOne() method if findOne() is overridden', async () => {
      const Model = current.define('model', {
        unique1: {
          type: DataTypes.INTEGER,
          unique: 'unique',
        },
        unique2: {
          type: DataTypes.INTEGER,
          unique: 'unique',
        },
      });
      Model.findOne = sinon.stub();
      sinon.spy(Sequelize.Model, 'findOne');

      await Model.findByPk(1);
      Model.findOne.should.not.have.been.called;
      Sequelize.Model.findOne.should.have.been.called;
    });
  });
});


text:
package main

import "math/rand"

const letterBytes = "abcdefghjkmnpqrstuvwxyz"

func randStringBytes(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return string(b)
}


text:
using System;
using System.IO;
using System.Text;
using fastJSON;

namespace CommonSerializer.PowerJSON
{
	// This project can output the Class library as a NuGet Package.
	// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
	public class PowerJsonCommonSerializer : ICommonSerializer
	{
		private readonly SerializationManager _manager;
		private readonly JSONParameters _parameters;

		public PowerJsonCommonSerializer()
			: this(JSON.Manager, JSON.Parameters)
		{
		}

		public PowerJsonCommonSerializer(SerializationManager manager, JSONParameters parameters)
		{
			_manager = manager;
			_parameters = parameters;
		}

		public string Description
		{
			get
			{
				return "PowerJSON, a derivative of fastJSON";
			}
		}

		public string Name
		{
			get
			{
				return "PowerJSON";
			}
		}

		public bool StreamsUtf8
		{
			get
			{
				return true;
			}
		}

		public T DeepClone<T>(T t)
		{
			return JSON.DeepCopy(t, _parameters, _manager);
		}

		public object Deserialize(string str, Type type)
		{
			return JSON.ToObject(str, type, _parameters, _manager);
		}

		public object Deserialize(TextReader reader, Type type)
		{
			return Deserialize(reader.ReadToEnd(), type);
		}

		public object Deserialize(Stream stream, Type type)
		{
			using (var reader = new StreamReader(stream, Encoding.UTF8, true, 2048, true))
				return Deserialize(reader.ReadToEnd(), type);
		}

		public T Deserialize<T>(TextReader reader)
		{
			return Deserialize<T>(reader.ReadToEnd());

		}

		public T Deserialize<T>(string str)
		{
			return JSON.ToObject<T>(str, _parameters, _manager);
		}

		public T Deserialize<T>(Stream stream)
		{
			return (T)Deserialize(stream, typeof(T));
		}

		public string Serialize<T>(T value)
		{
			return JSON.ToJSON(value, _parameters, _manager);
		}

		public string Serialize(object value, Type type)
		{
			return JSON.ToJSON(value, _parameters, _manager);
		}

		public void Serialize<T>(TextWriter writer, T value)
		{
			writer.Write(JSON.ToJSON(value, _parameters, _manager));
		}

		public void Serialize(TextWriter writer, object value, Type type)
		{
			writer.Write(JSON.ToJSON(value, _parameters, _manager));
		}

		public void Serialize<T>(Stream stream, T value)
		{
			Serialize(stream, value, typeof(T));
		}

		public void Serialize(Stream stream, object value, Type type)
		{
			using (var writer = new StreamWriter(stream, Encoding.UTF8, 2048, true))
				writer.Write(JSON.ToJSON(value, _parameters, _manager));
		}

		public void RegisterSubtype<TBase, TInheritor>(int fieldNumber = -1)
		{
			RegisterSubtype<TBase>(typeof(TInheritor), fieldNumber);
		}

		public void RegisterSubtype<TBase>(Type inheritor, int fieldNumber = -1)
		{
			// no way to turn it off that I can see
		}
	}
}


text:
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"syscall"
	"time"
	"unsafe"

	"github.com/linuxkit/virtsock/pkg/vsock"
)

// Listen for connections on an AF_VSOCK address and update the system time
// from the hardware clock when a connection is received.

// From <linux/rtc.h> struct rtc_time
type rtcTime struct {
	tmSec   uint32
	tmMin   uint32
	tmHour  uint32
	tmMday  uint32
	tmMon   uint32
	tmYear  uint32
	tmWday  uint32
	tmYday  uint32
	tmIsdst uint32
}

const (
	// iocREAD and friends are from <linux/asm-generic/ioctl.h>
	iocREAD      = uintptr(2)
	iocNRBITS    = uintptr(8)
	iocNRSHIFT   = uintptr(0)
	iocTYPEBITS  = uintptr(8)
	iocTYPESHIFT = iocNRSHIFT + iocNRBITS
	iocSIZEBITS  = uintptr(14)
	iocSIZESHIFT = iocTYPESHIFT + iocTYPEBITS
	iocDIRSHIFT  = iocSIZESHIFT + iocSIZEBITS
	// rtcRDTIMENR and friends are from <linux/rtc.h>
	rtcRDTIMENR   = uintptr(0x09)
	rtcRDTIMETYPE = uintptr(112)
)

func rtcReadTime() rtcTime {
	f, err := os.Open("/dev/rtc0")
	if err != nil {
		log.Fatalf("Failed to open /dev/rtc0: %v", err)
	}
	defer f.Close()
	result := rtcTime{}
	arg := uintptr(0)
	arg |= (iocREAD << iocDIRSHIFT)
	arg |= (rtcRDTIMETYPE << iocTYPESHIFT)
	arg |= (rtcRDTIMENR << iocNRSHIFT)
	arg |= (unsafe.Sizeof(result) << iocSIZESHIFT)
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), arg, uintptr(unsafe.Pointer(&result)))
	if errno != 0 {
		log.Fatalf("RTC_RD_TIME failed: %v", errno)
	}
	return result
}

func main() {
	// host-timesync-daemon -cid <cid> -port <port>

	cid := flag.Int("cid", 0, "AF_VSOCK CID to listen on")
	port := flag.Int("port", 0, "AF_VSOCK port to listen on")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s: set the time after an AH_VSOCK connection is received.\n\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Example usage:\n")
		fmt.Fprintf(os.Stderr, "%s -port 0xf3a4\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "   -- when a connection is received on port 0xf3a4, query the hardware clock and\n")
		fmt.Fprintf(os.Stderr, "      set the system time. The connection will be closed after the clock has\n")
		fmt.Fprintf(os.Stderr, "      been changed.\n\n")
		fmt.Fprintf(os.Stderr, "Arguments:\n")
		flag.PrintDefaults()
	}

	flag.Parse()
	if *port == 0 {
		log.Fatalf("Please supply a -port argument")
	}
	if *cid == 0 {
		// by default allow connections from anywhere on the local machine
		*cid = vsock.CIDAny
	}

	l, err := vsock.Listen(uint32(*cid), uint32(*port))
	if err != nil {
		log.Fatalf("Failed to bind to vsock port %x:%x: %s", *cid, *port, err)
	}
	log.Printf("Listening on port %x:%x", *cid, *port)

	for {
		conn, err := l.Accept()

		if err != nil {
			log.Fatalf("Error accepting connection: %s", err)
		}
		log.Printf("Connection to: %x:%x from: %s\n", *cid, *port, conn.RemoteAddr())

		t := rtcReadTime()
		// Assume the RTC is set to UTC. This may not be true on a Windows host but in
		// that case we assume the platform is capable of providing a PV clock and
		// we don't use this code anyway.
		d := time.Date(int(t.tmYear+1900), time.Month(t.tmMon+1), int(t.tmMday), int(t.tmHour), int(t.tmMin), int(t.tmSec), 0, time.UTC)
		log.Printf("Setting system clock to %s", d)
		tv := syscall.Timeval{
			Sec:  d.Unix(),
			Usec: 0, // the RTC only has second granularity
		}
		if err = syscall.Settimeofday(&tv); err != nil {
			log.Printf("Unexpected failure from Settimeofday: %v", err)
		}
		// Close after the command terminates. The caller can use this as a notification.
		conn.Close()
	}
}


text:
Raspberry Pi Security Onion Dockerfile
============
# rpi-security-onion
Automated Security Onion for the Raspberry Pi.
(https://github.com/hwegge2/rpi-security-onion)

This repository contains the Dockerfile for setting up a Security Onion on a Raspberry Pi.

## Get Latest

- git clone (https://github.com/hwegge2/rpi-security-onion)
- cd rpi-security-onion

## Features:

- No Defined Authentication
- User Defined Authentication
- Custom Workspace directory via mounting Volume containers
- Automated Build Process

# Base Docker Image
[resin/rpi-raspbian:wheezy] (https://hub.docker.com/r/resin/rpi-raspbian/)

## Installation

Download the automated build from the Docker Hub Registry:

docker pull hwegge2/rpi-security-onion

You can also build an image from the Dockerfile:

docker build -t="$USER/rpi-security-onion" github.com/hwegge2/rpi-security-onion .

## Usage

Start up the container

docker run --name rpi-security-onion --rm -ti hwegge2/rpi-security-onion


text:
let cE = React.createElement

// =====================================================================================================================
// V1 - Raw createElement

// let rootElem =
// cE( 'div', {},
//   cE( 'h1', {}, 'Contacts' ),
//   cE( 'ul', {},
//     cE( 'li', {},
//       cE( 'a', {href: 'mailto:email@gmail.com'}, 'Person 1' )
//     ),
//     cE( 'li', {},
//       cE( 'a', {href: 'mailto:email@email.edu'}, 'Student 2' )
//     )
//   )
// )
// ReactDOM.render( rootElem, document.getElementById( 'root' ) )

// =====================================================================================================================
// V2 - React Components w/ data

class ContactItem extends React.Component {
  render() {
    return(
      // Assign a Key to help React identify the element: https://reactjs.org/docs/lists-and-keys.html#keys
      cE( 'li', {className: 'contact unstyled'},
        cE( 'h2', {className: 'contact-name'}, this.props.name ),
        cE( 'a', {href: `mailto:${this.props.email}`}, this.props.email ),
        cE( 'div', {}, this.props.description )
      )
    )
  }
}
// Configure properties
ContactItem.propTypes = {
  description: PropTypes.string,
  email: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
}
ContactItem.defaultProps = {
  name: 'Default Name',
}

// Display all Contact data
var contacts = [

  {description: 'Unicorn', email: 'doingBigThings@me.co', key: 1, name: 'Colin King'},
  // {description: 'The older one', email: 'me@kyle.co', key: 2, name: 'Kyle King'},
  {description: 'HE HAS NO NAME!', email: 'someone@datOne.co', key: 3},
  {key: 4, name: 'EMPTY INPUT'},
]
var contactItems = contacts
  .filter( ( contact ) => contact.email )
  .map( ( contact ) => cE( ContactItem, contact ) )

// Render Basic Contact List
// WARN: use `cE(Fragment, {}` to encapsulate elements rather than excess div (`import React, {Fragment} from 'react'`)
// FYI: read more about Fragments here: https://reactjs.org/docs/fragments.html (use `<> ... </>` in JSX)
var rootElem = cE( React.Fragment, {},
  cE( 'h1', {}, 'Contact List' ),
  cE( 'ul', {}, contactItems )
)
ReactDOM.render( rootElem, document.getElementById( 'root' ) )

// =====================================================================================================================
// V3 - Add Clock

class Clock extends React.Component {
  constructor( props ) {
    super( props )
    this.state = {date: new Date()}
  }

  componentDidMount() {
    this.timerID = setInterval( () => this.tick(), this.props.updateInterval )
  }
  componentWillUnmount() {
    clearInterval( this.timerID )
  }

  tick() {
    this.setState( {date: new Date()} )
  }

  render() {
    return(
      cE( 'div', {},
        cE( 'h1', {}, `Clock Example (${this.props.updateInterval})` ),
        cE( 'span', {}, this.state.date.toLocaleString() )
      )
    )
  }
}
// Configure properties
Clock.propTypes = {
  updateInterval: PropTypes.number.isRequired,
}

var clockElements = cE( 'div', {},
  cE( Clock, {updateInterval: 1000} ),
  cE( Clock, {updateInterval: 2000} ),
  cE( Clock, {updateInterval: 4000} )
)
ReactDOM.render( clockElements, document.getElementById( 'tick' ) )

// // FYI: Use setState function to use previous state
// this.setState( ( state, props ) => ( {
//   counter: state.counter + props.increment
// } ) )
// // setState will overwrite a shallow copy (replace counter, but leave other keys intact)

// =====================================================================================================================
// V4 - Event Handling

class Toggle extends React.Component {
  // Need Babel to use static keyword
  // static propTypes = {
  //   id: PropTypes.string.isRequired,
  // }

  constructor( props ) {
    super( props )
    this.state = {isToggleOn: true}

    // FYI: This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind( this, `>${this.props.id}<` )
  }

  handleClick( id ) {
    // Demonstrate binding id
    console.log( `Clicked: "${id}"` )
    this.setState( state => ( {
      isToggleOn: !state.isToggleOn,
    } ) )
  }

  render() {
    const label = `${this.props.id}-${this.state.isToggleOn ? 'ON' : 'OFF'}`
    return(
      cE( 'p', {},
        cE( 'button', {onClick: this.handleClick}, label )
      )
    )
  }
}
Toggle.propTypes = {
  id: PropTypes.string.isRequired,
}

var toggleElements = cE( 'div', {},
  cE( 'h1', {}, 'Toggle Buttons' ),
  cE( Toggle, {id: true} ),  // Without Babel, this isn't caught
  cE( Toggle, {id: 'Button_1'} ),
  cE( Toggle, {id: 'Button_2'} ),
  cE( Toggle, {id: 'Button_3'} )
)
ReactDOM.render( toggleElements, document.getElementById( 'toggle-button' ) )

// =====================================================================================================================
// V5 -- Forms (Controlled State) > React Component is only source of "Truth"

class Dropdown extends React.Component {
  constructor( props ) {
    super( props )
    this.handleChange = this.handleChange.bind( this )
  }

  handleChange( e ) {
    this.props.onDropdownChange( e.target.value )  // FYI: lift state
  }

  render() {
    // Make sure to use: `this.PROPS.dropdown` rather than `.state.`
    return(
      cE( 'select', {onChange: this.handleChange, value: this.props.dropdown},
        this.props.dropdownOptions.map( ( opt ) =>
          cE( 'option', {key: opt.toString(), value: opt}, opt )
        )
      )
    )
  }
}
Dropdown.propTypes = {
  dropdownOptions: PropTypes.array.isRequired,
}

class Reservation extends React.Component {
  constructor( props ) {
    super( props )

    const dropdownOptions = ['Lime', 'Coconut', 'Watermelon', 'Lump Crab Meat']
    this.state = {
      dropdown: dropdownOptions[0],
      dropdownOptions,
      isGoing: true,
      numberOfGuests: 2,
      textarea: 'Please write an essay about your favorite DOM element.',
      username: 'bRIAn',  // WARN: will not be transformed to CAPS until edited
    }

    // Create reference
    this.fileInput = React.createRef()

    // Must bind this to each handler
    this.handleInputChange = this.handleInputChange.bind( this )
    this.handleDropdownChange = this.handleDropdownChange.bind( this )
    this.handleSubmit = this.handleSubmit.bind( this )
    this.handleTextareaChange = this.handleTextareaChange.bind( this )
  }

  handleInputChange( e ) {
    // Example parsing and enforcing formatting
    let value = null
    if ( e.target.type === 'checkbox' )
      value = e.target.checked
    else {
      value = e.target.value
      if ( e.target.name === 'username' ) {
        value = value.toUpperCase()
        // FYI: Test changing dropdown options using lifted state
        this.state.dropdownOptions[4] = value
      }
    }

    // With the ES6 computed property name syntax, update the state
    this.setState( {
      [e.target.name]: value,
    } )
  }

  handleDropdownChange( dropdown ) {
    this.setState( {dropdown} )
  }

  handleSubmit( e ) {
    e.preventDefault()

    console.info( `Currently selected Dropdown item: ${this.state.dropdown}` )
    Object.values(this.fileInput.current.files).map( ( file, idx ) =>
      console.log( `[${idx}] File name: '${file.name}' (${file.type})` )
    )

    const name = this.state.username
    const numGs = this.state.numberOfGuests
    alert( `${name}'s ${numGs} guest${numGs > 1 ? 's are' : ' is'} ${this.state.isGoing ? '' : 'not '}going.` )
  }

  handleTextareaChange( e ) {
    this.setState( {textarea: e.target.value} )
  }

  render() {
    return (
      cE( 'div', {},
        cE( 'h1', {}, 'Controlled Component Examples' ),
        cE( 'form', {onSubmit: this.handleSubmit},
          cE( 'h2', {}, 'Form:' ),
          cE( 'label', {},
            cE( 'span', {}, 'Username:' ),
            cE( 'input', {
              name: 'username',
              onChange: this.handleInputChange,
              type: 'text',
              value: this.state.username,
            } )
          ),
          cE( 'br' ),
          cE( 'label', {},
            cE( 'span', {}, 'Is going:' ),
            cE( 'input', {
              checked: this.state.isGoing,
              name: 'isGoing',
              onChange: this.handleInputChange,
              type: 'checkbox',
            } )
          ),
          cE( 'br' ),
          cE( 'label', {},
            cE( 'span', {}, 'Number of Guests:' ),
            cE( 'input', {
              name: 'numberOfGuests',
              onChange: this.handleInputChange,
              type: 'number',
              value: this.state.numberOfGuests,
            } )
          ),
          cE( 'br' ),
          // Test using components (select) within a form
          cE( Dropdown, {
            dropdownOptions: this.state.dropdownOptions,
            onDropdownChange: this.handleDropdownChange,
          } ),
          cE( 'br' ),
          // FYI: Example use ref (input type:file is always an uncontrolled component)
          cE( 'input', {multiple: true, ref: this.fileInput, type: 'file'} ),
          cE( 'br' ),
          cE( 'input', {type: 'submit', value: 'Submit'} )
        ),
        cE( 'h2', {}, 'Text Area:' ),
        cE( 'textarea', {
          onChange: this.handleTextareaChange,
          value: this.state.textarea,
        }  )
      )
    )
  }
}

const mountNode = document.getElementById( 'reservation' )

ReactDOM.render( cE( Reservation ), mountNode )

// // Example - The input is locked at first but becomes editable after a short delay.
// ReactDOM.render( cE( 'input', {value: 'hi'} ), mountNode )
// setTimeout( () => {
//   ReactDOM.render( cE( 'input', {value: 'NULL!'} ), mountNode )
//   ReactDOM.render( cE( 'input', {value: null} ), mountNode )
// }, 2500 )

// When building forms, see https://jaredpalmer.com/formik

// =====================================================================================================================
// V6 - Lifting State

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit',
}

function BoilingVerdict( props ) {
  return cE( 'p', {}, `The water would${props.celsius >= 100 ? '' : ' not'} boil.` )
}

function toCelsius( fahrenheit ) {
  return ( fahrenheit - 32 ) * 5 / 9
}

function toFahrenheit( celsius ) {
  return ( celsius * 9 / 5 ) + 32
}

function tryConvert( temperature, convert ) {
  const input = parseFloat( temperature )
  if ( Number.isNaN( input ) )
    return ''

  const output = convert( input )
  const rounded = Math.round( output * 1000 ) / 1000
  return rounded.toString()
}

// F|C Temperature Input Element
class TemperatureInput extends React.Component {
  constructor( props ) {
    super( props )
    this.handleChange = this.handleChange.bind( this )
  }

  handleChange( e ) {
    this.props.onTemperatureChange( e.target.value )
  }

  render() {
    return (
      cE( 'fieldset', {},
        cE( 'legend', {}, `Enter temperature in ${scaleNames[this.props.scale]}:` ),
        cE( 'input', {onChange: this.handleChange, value: this.props.temperature} )
      )
    )
  }
}

// Combined F & C Temperature Inputs. Determines if temperature would boil water
class Calculator extends React.Component {
  constructor( props ) {
    super( props )
    this.handleCelsiusChange = this.handleCelsiusChange.bind( this )
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind( this )
    this.state = {scale: 'c', temperature: ''}
  }

  handleCelsiusChange( temperature ) {
    // FYI: When state changes, the render() method is called, so C and F are recalculated
    this.setState( {scale: 'c', temperature} )
  }

  handleFahrenheitChange( temperature ) {
    this.setState( {scale: 'f', temperature} )
  }

  render() {
    const scale = this.state.scale
    const temperature = this.state.temperature
    // Handle case where input is not a number with tryConvert
    const celsius = scale === 'f' ? tryConvert( temperature, toCelsius ) : temperature
    const fahrenheit = scale === 'c' ? tryConvert( temperature, toFahrenheit ) : temperature

    return (
      cE( 'div', {},
        cE( 'h1', {}, 'Linked Calculator Inputs' ),
        cE( TemperatureInput, {
          onTemperatureChange: this.handleCelsiusChange,
          scale: 'c',
          temperature: celsius,
        } ),
        cE( TemperatureInput, {
          onTemperatureChange: this.handleFahrenheitChange,
          scale: 'f',
          temperature: fahrenheit,
        } ),
        cE( BoilingVerdict, {celsius: parseFloat( celsius )} )
      )
    )
  }
}

ReactDOM.render( cE( Calculator ), document.getElementById( 'calculator' ) )

// =====================================================================================================================
// V7 - Don't do Inheritance

// Containment example
function FancyBorder( props ) {
  return (
    cE( 'div', {className: `FancyBorder FancyBorder-${props.color}`}, props.children )
  )
}
// This lets other components pass arbitrary children to them by nesting the JSX:
function WelcomeDialog( props ) {
  return (
    cE( FancyBorder, {color: props.color},
      cE( 'h1', {className: 'dialog-title'}, 'Welcome' ),
      cE( 'p', {className: 'dialog-message'}, 'Thank you for visiting our spacecraft!' )
    )
  )
}
ReactDOM.render( cE( WelcomeDialog, {color: 'blue'} ), document.getElementById( 'containment-basic' ) )

// Example with specified children
function SplitPane( props ) {
  return (
    cE( 'div', {className: 'row'},
      cE( 'div', {className: 'col-6'}, props.left ),
      cE( 'div', {className: 'col-6'}, props.right )
    )
  )
}
ReactDOM.render(
  cE( SplitPane, {
    left: cE( WelcomeDialog, {color: 'red'} ),
    right: cE( WelcomeDialog, {color: 'blue'} ),
  } ), document.getElementById( 'containment-splitPane' ) )

// Specialization Example
function Dialog( props ) {
  return (
    cE( FancyBorder, {color: 'blue'},
      cE( 'h1', {className: 'dialog-title'}, props.title ),
      cE( 'p', {className: 'dialog-message'}, props.message ),
      props.children
    )
  )
}

class SignUpDialog extends React.Component {
  constructor( props ) {
    super( props )
    this.handleChange = this.handleChange.bind( this )
    this.handleSignUp = this.handleSignUp.bind( this )
    this.state = {login: ''}
  }

  render() {
    return (
      cE( 'div', {},
        cE( Dialog, {message: 'How should we refer to you?', title: 'Mars Exploration Program'},
          cE( 'input', {onChange: this.handleChange, value: this.state.login} ),
          cE( 'button', {onClick: this.handleSignUp}, 'Sign me up!' )
        ),
        cE( Dialog, {},
          cE( 'p', {}, 'Only children, no message or title example' )
        )
      )
    )
  }

  handleChange( e ) {
    this.setState( {login: e.target.value} )
  }

  handleSignUp() {
    alert( `Welcome aboard, ${this.state.login}!` )
  }
}
ReactDOM.render( cE( SignUpDialog ), document.getElementById( 'specialization' ) )

// =====================================================================================================================
// V8 - Thinking in React

// The easiest way is to build a version that takes your data model and renders the UI but has no interactivity.
// It's best to decouple these processes because building a static version requires a lot of typing and no thinking,
//   and adding interactivity requires a lot of thinking and not a lot of typing.


text:
namespace xwalk {

namespace application {
class ApplicationService;
}

class XWalkPermissionManager : public content::PermissionManager {
 public:
  XWalkPermissionManager(
      application::ApplicationService* application_service);
  ~XWalkPermissionManager() override;

  // PermissionManager implementation.
  int RequestPermission(
      content::PermissionType permission,
      content::RenderFrameHost* render_frame_host,
      const GURL& requesting_origin,
      const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
      override;
  int RequestPermissions(
      const std::vector<content::PermissionType>& permissions,
      content::RenderFrameHost* render_frame_host,
      const GURL& requesting_origin,
      const base::Callback<void(
          const std::vector<blink::mojom::PermissionStatus>&)>& callback)
          override;
  void CancelPermissionRequest(int request_id) override;
  void ResetPermission(content::PermissionType permission,
                       const GURL& requesting_origin,
                       const GURL& embedding_origin) override;
  blink::mojom::PermissionStatus GetPermissionStatus(
      content::PermissionType permission,
      const GURL& requesting_origin,
      const GURL& embedding_origin) override;
  void RegisterPermissionUsage(content::PermissionType permission,
                               const GURL& requesting_origin,
                               const GURL& embedding_origin) override;
  int SubscribePermissionStatusChange(
      content::PermissionType permission,
      const GURL& requesting_origin,
      const GURL& embedding_origin,
      const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
      override;
  void UnsubscribePermissionStatusChange(int subscription_id) override;

 private:
  struct PendingRequest;
  using PendingRequestsMap = IDMap<PendingRequest, IDMapOwnPointer>;

  void GetApplicationName(
      content::RenderFrameHost* render_frame_host,
      std::string* name);
  static void OnRequestResponse(
      const base::WeakPtr<XWalkPermissionManager>& manager,
      int request_id,
      const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
      bool allowed);

  PendingRequestsMap pending_requests_;
  scoped_refptr<RuntimeGeolocationPermissionContext>
      geolocation_permission_context_;
  scoped_refptr<RuntimeNotificationPermissionContext>
      notification_permission_context_;
  application::ApplicationService* application_service_;
  base::WeakPtrFactory<XWalkPermissionManager> weak_ptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(XWalkPermissionManager);
};

}  // namespace xwalk

#endif  // XWALK_RUNTIME_BROWSER_XWALK_PERMISSION_MANAGER_H_


text:
package smoke;

import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.awaitility.Awaitility;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import static org.assertj.core.api.BDDAssertions.then;
import static org.awaitility.Awaitility.await;

/**
 * @author Marcin Grzejszczak
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = IntegrationTests.class,
		webEnvironment = SpringBootTest.WebEnvironment.NONE)
@EnableAutoConfiguration
public class IntegrationTests {

	private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());

	@Value("${stubrunner.url}") String stubRunnerUrl;
	@Value("${application.url}") String applicationUrl;
	@Value("${test.timeout:60}") Long timeout;

	RestTemplate restTemplate = new RestTemplate();

	@Test
	public void shouldStoreAMessageWhenGithubDataWasReceivedViaMessaging() {
		Awaitility.await().atMost(this.timeout, TimeUnit.SECONDS).untilAsserted(() -> {
			final Integer countOfEntries = countGithubData();
			log.info("Initial count is [" + countOfEntries + "]");

			ResponseEntity<Map> response = triggerMessage();
			then(response.getStatusCode().is2xxSuccessful()).isTrue();
			log.info("Triggered additional message");

			log.info("Awaiting proper count of github data");
			await().until(() -> countGithubData() > countOfEntries);
		});
	}

	private ResponseEntity<Map> triggerMessage() {
		return this.restTemplate.postForEntity("http://" +
				this.stubRunnerUrl + "/triggers/issue_created_v2", "", Map.class);
	}

	private Integer countGithubData() {
		Integer response = this.restTemplate
				.getForObject("http://" + this.applicationUrl + "/issues/count", Integer.class);
		log.info("Received response [" + response + "]");
		return response;
	}
}


text:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using XCode.RuningCode.Entity.Base;

namespace XCode.RuningCode.Entity.Blog
{
    public class Tag : BaseEntity
    {
        public string Name { get; set; }

        public string Description { get; set; }

        public virtual ICollection<Article> Articles { get; set; }=new Collection<Article>();
    }
}


text:
package com.google.security.zynamics.binnavi.REIL.mono.apiwrappers;

import com.google.common.base.Preconditions;
import com.google.security.zynamics.binnavi.API.reil.mono.ILatticeElement;
import com.google.security.zynamics.reil.algorithms.mono.interfaces.IInfluencingState;

/**
 * Wraps API state objects to internal state objects.
 *
 * @param <ApiLatticeElement> Type of the API lattice elements.
 * @param <ObjectType> Type of the additional object of a state.
 */
public final class StateWrapper<ApiLatticeElement extends ILatticeElement<ApiLatticeElement>, ObjectType> implements com.google.security.zynamics.binnavi.API.reil.mono.IInfluencingState<ApiLatticeElement, ObjectType>
{
	/**
	 * Wrapped API lattice element.
	 */
	private final ApiLatticeElement element;

	/**
	 * Wrapped additional object.
	 */
	private final ObjectType object;

	/**
	 * Creates a new wrapper object.
	 *
	 * @param wrappedState The wrapped API state.
	 */
	public StateWrapper(final IInfluencingState<ApiLatticeElement, ObjectType> wrappedState)
	{
		Preconditions.checkNotNull(wrappedState, "IE02086: Wrapped state argument can not be null");

		element = wrappedState.getElement();
		object = wrappedState.getObject();
	}

	@Override
	public ApiLatticeElement getElement()
	{
		return element;
	}

	@Override
	public ObjectType getObject()
	{
		return object;
	}
}


text:
/**
 * Class that represents an Address.
 * @author Marco Moschettini
 * @version 0.0.1
 */
export default class Address
{
    private _address: string;
    private _port: number;
    private _family: string;

    /**
     * The constructor
     * @param address {string} The ip address
     * @param port {number} The port
     * @param family
     */
    constructor(address: string, port: number, family = 'ipv4')
    {
        this._address = address;
        this._port = port;
        this._family = family;
    }

    /**
     * Method used to deserialize a previously serialized address and to return a new Address instance
     * @param address {_address: string, _port: number, _family; string}: The serialized address to be deserialized
     * @returns {Address}
     */
    public static refresh(address: {_address: string, _port: number, _family; string})
    {
        if(address._address && address._port)
            return new Address(address._address, address._port, address._family);
    }

    // region getters
    public get address(): string
    {
        return this._address;
    }

    public get port(): number
    {
        return this._port;
    }
    // endregion
}


text:
import "mocha";
import puppeteer from "puppeteer";
import { expect } from "chai";
import { Screenshot, createFolder, setupCredentials, enterCredentials, storagePoller, ONE_SECOND_IN_MS } from "../../../../../e2eTestUtils/TestUtils";
import { BrowserCacheUtils } from "../../../../../e2eTestUtils/BrowserCacheTestUtils";
import { LabApiQueryParams } from "../../../../../e2eTestUtils/LabApiQueryParams";
import { AzureEnvironments, AppTypes } from "../../../../../e2eTestUtils/Constants";
import { LabClient } from "../../../../../e2eTestUtils/LabClient";
import { JWK, JWT } from "jose";

const SCREENSHOT_BASE_FOLDER_NAME = `${__dirname}/screenshots`;
const SAMPLE_HOME_URL = "http://localhost:30662/";
let username = "";
let accountPwd = "";

describe("Browser tests", function () {
    this.timeout(0);
    this.retries(1);

    let browser: puppeteer.Browser;
    before(async () => {
        createFolder(SCREENSHOT_BASE_FOLDER_NAME);
        const labApiParams: LabApiQueryParams = {
            azureEnvironment: AzureEnvironments.PPE,
            appType: AppTypes.CLOUD
        };

        const labClient = new LabClient();
        const envResponse = await labClient.getVarsByCloudEnvironment(labApiParams);
        [username, accountPwd] = await setupCredentials(envResponse[0], labClient);

        browser = await puppeteer.launch({
            headless: true,
            ignoreDefaultArgs: ["--no-sandbox", "–disable-setuid-sandbox"]
        });
    });

    let context: puppeteer.BrowserContext;
    let page: puppeteer.Page;
    let BrowserCache: BrowserCacheUtils;
    beforeEach(async () => {
        context = await browser.createIncognitoBrowserContext();
        page = await context.newPage();
        page.setDefaultTimeout(ONE_SECOND_IN_MS*5);
        BrowserCache = new BrowserCacheUtils(page, "sessionStorage");
        await page.goto(SAMPLE_HOME_URL);
    });

    afterEach(async () => {
        await page.close();
    });

    after(async () => {
        await context.close();
        await browser.close();
    });

    it("Performs loginRedirect, acquires and validates CAE token", async () => {
        const testName = "redirectBaseCase";
        const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`);

        // Home Page
        await page.waitForSelector("#SignIn");
        await screenshot.takeScreenshot(page, "samplePageInit");

        // Click Sign In
        await page.click("#SignIn");
        await page.waitForSelector("#redirect");
        await screenshot.takeScreenshot(page, "signInClicked");

        // Click Sign In With Redirect
        await page.click("#redirect");

        // Enter credentials
        await enterCredentials(page, screenshot, username, accountPwd);

        // Fetch profile
        await page.waitForSelector("#seeProfile", { visible: true });
        await screenshot.takeScreenshot(page, "samplePageLoggedIn");
        await page.click("#seeProfile");
        await page.waitForSelector("#profile-div");
        await screenshot.takeScreenshot(page, "caeTokenClicked");

        // Check token
        const tokenStore = await BrowserCache.getTokens();
        expect(tokenStore.idTokens).to.be.length(1);
        expect(tokenStore.accessTokens).to.be.length(1);
        expect(tokenStore.refreshTokens).to.be.length(1);
        const cachedAccount = await BrowserCache.getAccountFromCache(tokenStore.idTokens[0]);
        const defaultCachedToken = await BrowserCache.accessTokenForScopesExists(tokenStore.accessTokens, ["openid", "profile", "user.read"]);
        expect(cachedAccount).to.not.be.null;
        expect(defaultCachedToken).to.be.true;

        // Check cae token
        const accessToken = JSON.parse((await BrowserCache.getWindowStorage())[(tokenStore.accessTokens[0])]).secret;
        const decodedToken: any = JWT.decode(accessToken);
        expect(decodedToken.xms_cc).to.deep.equal([ "CP1" ]);
    });

    it("Performs loginRedirect, acquires and validates CAE PoP token", async () => {
        const testName = "redirectBaseCase";
        const screenshot = new Screenshot(`${SCREENSHOT_BASE_FOLDER_NAME}/${testName}`);

        // Home Page
        await page.waitForSelector("#SignIn");
        await screenshot.takeScreenshot(page, "samplePageInitPop");

        // Click Sign In
        await page.click("#SignIn");
        await page.waitForSelector("#redirect");
        await screenshot.takeScreenshot(page, "signInClickedPop");

        // Click Sign In With Redirect
        await page.click("#redirect");

        // Enter credentials
        await enterCredentials(page, screenshot, username, accountPwd);

        // Click to get cae pop token
        await page.waitForSelector("#seeProfilePop", { visible: true });
        await screenshot.takeScreenshot(page, "samplePageLoggedInPop");
        await page.click("#seeProfilePop");

        // Click to get cae bearer token
        await page.click("#seeProfile");
        await page.waitForSelector("#profile-div p");
        await screenshot.takeScreenshot(page, "caePopTokenClicked");

        // Check for both tokens in cache
        await storagePoller(async () => {
            const tokenStore = await BrowserCache.getTokens();
            expect(tokenStore.accessTokens).to.be.length(2);
        }, ONE_SECOND_IN_MS*5);

        const tokenStore = await BrowserCache.getTokens();
        const cachedBearerToken = await BrowserCache.accessTokenForScopesExists(tokenStore.accessTokens, ["openid", "profile", "user.read"]);
        expect(cachedBearerToken).to.be.true;

        const cachedPopToken = await BrowserCache.popAccessTokenForScopesExists(tokenStore.accessTokens, ["openid", "profile", "user.read"]);
        expect(cachedPopToken).to.be.true;

        const storage = await BrowserCache.getWindowStorage();
        const caePopTokenKey = tokenStore.accessTokens.find(key => key.includes("accesstoken_with_authscheme"));
        const accessToken = JSON.parse(storage[caePopTokenKey]).secret;

        // Check cae pop token
        const decodedToken: any = JWT.decode(accessToken);
        expect(decodedToken.xms_cc).to.deep.equal([ "CP1" ]);
        expect(decodedToken.cnf.kid).to.be.string;
        expect(decodedToken.cnf.xms_ksl).to.be.string;
    });
});


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>C-Index</title>
<meta name="date" content="2014-04-30">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes

B C G I M O R S

C

close() - Method in class ModuleLoader

Calls Superclass close(), sets instance isConnected field to false on success.

closeModule(String) - Static method in class BulkLoader

Close an individual Module by name.

connect() - Method in class ModuleLoader

Used to reconnect to module if connection has been closed.

connectModule(String) - Static method in class BulkLoader

Reestablish connection on Module previously closed.

B C G I M O R S

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes


text:
package com.amazon.ask.dispatcher.request.handler.impl;

import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.events.skillevents.PermissionAcceptedRequest;
import com.amazon.ask.model.Response;

import java.util.Optional;

/**
 * Request handler for PermissionAcceptedRequest requests.
 */
public interface PermissionAcceptedRequestHandler extends RequestHandler {

    /**
     * Returns true if the handler can dispatch the current request
     *
     * @param input input to the request handler
     * @param permissionAcceptedRequest PermissionAcceptedRequest request
     * @return true if the handler is capable of handling the current request and/or state
     */
    boolean canHandle(HandlerInput input, PermissionAcceptedRequest permissionAcceptedRequest);

    /**
     * Handles the request.
     *
     * @param input input to the request handler
     * @param permissionAcceptedRequest PermissionAcceptedRequest request
     * @return output from the handler.
     */
    Optional<Response> handle(HandlerInput input, PermissionAcceptedRequest permissionAcceptedRequest);

    @Override
    default boolean canHandle(HandlerInput handlerInput) {
        if (handlerInput.getRequest() instanceof PermissionAcceptedRequest) {
            return canHandle(handlerInput, (PermissionAcceptedRequest)handlerInput.getRequest());
        }
        return false;
    }

    @Override
    default Optional<Response> handle(HandlerInput handlerInput) {
        return handle(handlerInput, (PermissionAcceptedRequest)handlerInput.getRequest());
    }

}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace F23Bag.Tests.AutomaticUITestElements
{
    public class ObjectForTreeLayout
    {
        public IEnumerable<int> Children { get; } = new List<int> { 1, 2, 3 };
    }
}