Skip to content

Commit

Permalink
add extensible hook for RStudio session initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcphers committed Jun 18, 2014
1 parent 8b01e0c commit fc86699
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/cpp/session/CMakeLists.txt
Expand Up @@ -87,6 +87,7 @@ set (SESSION_SOURCE_FILES
modules/SessionPath.cpp
modules/SessionPlots.cpp
modules/SessionProfiler.cpp
modules/SessionRHooks.cpp
modules/SessionRPubs.cpp
modules/SessionShinyApps.cpp
modules/SessionShinyViewer.cpp
Expand Down
5 changes: 5 additions & 0 deletions src/cpp/session/SessionMain.cpp
Expand Up @@ -116,6 +116,7 @@ extern "C" const char *locale2charset(const char *);
#include "modules/SessionPackrat.hpp"
#include "modules/SessionProfiler.hpp"
#include "modules/SessionRPubs.hpp"
#include "modules/SessionRHooks.hpp"
#include "modules/SessionShinyApps.hpp"
#include "modules/SessionShinyViewer.hpp"
#include "modules/SessionSpelling.hpp"
Expand Down Expand Up @@ -1627,6 +1628,7 @@ Error rInit(const r::session::RInitInfo& rInitInfo)
(modules::shiny_viewer::initialize)
(modules::shiny_apps::initialize)
(modules::packrat::initialize)
(modules::rhooks::initialize)

// workers
(workers::web_request::initialize)
Expand Down Expand Up @@ -1725,6 +1727,9 @@ void rDeferredInit(bool newSession)
{
module_context::events().onDeferredInit(newSession);

// allow any packages listening to complete initialization
modules::rhooks::invokeHook(kSessionInitHook, newSession);

// fire an event to the client
ClientEvent event(client_events::kDeferredInitCompleted);
module_context::enqueClientEvent(event);
Expand Down
32 changes: 32 additions & 0 deletions src/cpp/session/modules/SessionRHooks.R
@@ -0,0 +1,32 @@
#
# SessionRHooks.R
#
# Copyright (C) 2009-14 by RStudio, Inc.
#
# Unless you have received this program directly from RStudio pursuant
# to the terms of a commercial license agreement with RStudio, then
# this program is licensed to you under the terms of version 3 of the
# GNU Affero General Public License. This program is distributed WITHOUT
# ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
# AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
#
#

.rs.addFunction("invokeHook", function(hookName, ...) {
# ensure that the list of hooks can be iterated over as a list
hooks <- getHook(hookName)
if (!is.list(hooks))
hooks <- list(hooks)

# execute each attached hook with the given parameters
for (fun in hooks) {
if (is.character(fun))
fun <- get(fun)
tryCatch(fun(...),
error = function(e) {
# ignore errors occurring during hook execution
})
}
})

46 changes: 46 additions & 0 deletions src/cpp/session/modules/SessionRHooks.cpp
@@ -0,0 +1,46 @@
/*
* SessionRHooks.cpp
*
* Copyright (C) 2009-14 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/

#include <core/Exec.hpp>

#include <r/RSexp.hpp>
#include <r/RExec.hpp>

#include <session/SessionModuleContext.hpp>

#include <boost/bind.hpp>

#include "SessionRHooks.hpp"

namespace session {
namespace modules {
namespace rhooks {

using namespace core;

Error initialize()
{
using boost::bind;
using namespace module_context;
ExecBlock initBlock;
initBlock.addFunctions()
(bind(sourceModuleRFile, "SessionRHooks.R"));
return initBlock.execute();
}

} // namespace rhooks
} // namespace modules
} // namespace session

43 changes: 43 additions & 0 deletions src/cpp/session/modules/SessionRHooks.hpp
@@ -0,0 +1,43 @@
/*
* SessionRHooks.hpp
*
* Copyright (C) 2009-14 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/

#ifndef SESSION_RHOOKS_HPP
#define SESSION_RHOOKS_HPP

#define kSessionInitHook "rstudio.sessionInit"

namespace core {
class Error;
}

namespace session {
namespace modules {
namespace rhooks {

core::Error initialize();

// thin wrapper around hook invocation
template<typename ParamType>
core::Error invokeHook(const std::string& hookName, const ParamType& param)
{
return r::exec::RFunction(".rs.invokeHook", hookName, param).call();
}

} // namespace packrat
} // namespace modules
} // namespace rhooks

#endif // SESSION_RHOOKS_HPP

0 comments on commit fc86699

Please sign in to comment.