pax_global_header00006660000000000000000000000064127703344120014515gustar00rootroot0000000000000052 comment=86fb2bb84223c7134ef81a1e4cd42ccdc5c96820 pluginlib-1.10.4/000077500000000000000000000000001277033441200135655ustar00rootroot00000000000000pluginlib-1.10.4/.gitignore000066400000000000000000000000401277033441200155470ustar00rootroot00000000000000build devel CMakeLists.txt.user pluginlib-1.10.4/CHANGELOG.rst000066400000000000000000000260111277033441200156060ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package pluginlib ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.10.4 (2016-09-20) ------------------- * Merge pull request `#42 `_ from delftrobotics-forks/unique-ptr Add std::unique_ptr API * Add unit test for unique_ptr API. * Simplify unit tests with ASSERT_THROW. * Add ClassLoader::createUniqueInstance. * Wrap long comment on createInstance and friend. * Throw exception if plugin.xml is broken (`#41 `_) * added test case for broken xml files with missing attributes of class tag * added checks if all needed attributes of the class tag are existing * removed comment and empty line * Contributors: Maarten de Vries, Mikael Arguedas, cwecht 1.10.3 (2016-06-22) ------------------- * Merge pull request `#40 `_ from ros/fix_warnings fix deprecated warnings in unit tests * fix deprecated warnings in unit tests * removed merge messages and redundant commits * Contributors: Mikael Arguedas 1.10.2 (2016-03-14) ------------------- * Remove Boost Software License from license tag `#35 `_ * Throw an exception if ClassLoader can't be instantiated due to an invalid package name `#34 `_ * Add ":" to split function within getName. `#33 `_ * Contributors: Esteve Fernandez, Jochen Sprickerhof, Mikael Arguedas, Mike O'Driscoll 1.10.1 (2014-12-23) ------------------- * Remove GTEST_FOUND from CMakeLists.txt * Check that GTest is installed before running tests. * Moved plugin_macro_update script to scripts directory. Made plugin_macro_update rosrunnable and removed it from global PATH `#29 `_ * Contributors: Esteve Fernandez 1.10.0 (2014-05-08 14:56) ------------------------- 1.9.25 (2014-05-08 20:37) ------------------------- * Use cmake_modules to find TinyXML `#26 `_ * Check for release libraries in debug builds `#25 `_ * update refreshDeclaredClasses to force recrawl (fix `#23 `_) * Contributors: Dirk Thomas, Esteve Fernandez 1.9.24 (2014-03-11) ------------------- * Remove invalid exception when no plugins are found `#22 `_ * Update maintainer field * Contributors: Dirk Thomas, Esteve Fernandez 1.9.23 (2013-10-04) ------------------- * expose plugin paths in ClassLoader `#21 `_ * Contributors: Dirk Thomas, Mirza Shah 1.9.22 (2013-08-21) ------------------- * Fixed use of __FILE_\_ macro in deprecation warning * Added libdl to plugin_tool link args...temporary fix * Contributors: Mirza Shah 1.9.21 (2013-07-14) ------------------- * Added file hint for deprecated warnings. `#16 `_ * check for CATKIN_ENABLE_TESTING * remove mainpage.dox * Contributors: Dane Powell, Dirk Thomas, Mirza Shah 1.9.20 (2013-04-18) ------------------- * Added another unit test for managed instance case. * Fixed a regression that broke unload call. Added a unit test for this case. * Contributors: Mirza Shah 1.9.19 (2013-03-23) ------------------- * Converted ROS_DEBUG and ROS_WARN calls to ROS_DEBUG_NAMED and ROS_WARN_NAMED calls `#13 `_ * Contributors: Dave Coleman, Mirza Shah 1.9.18 (2013-01-28) ------------------- * Support for boost filesystem v2 `#11 `_ * Added more debug information * Contributors: Mario Prats, Mirza Shah 1.9.17 (2012-12-27) ------------------- * More useful debug messages * Fixed incorrect debug message in plugin description XML parsing * Contributors: Mirza Shah 1.9.16 (2012-12-21) ------------------- * Removed old file * Annotated deprecation warning with more info * Made python script global installable * Added a script to recursively update deprecated pluginlib macro * added missing license header * modified dep type of catkin * Contributors: Aaron Blasdel, Dirk Thomas, Mirza Shah 1.9.15 (2012-12-13 17:22) ------------------------- * Updated registration macros to be easier and deprecated older ones. Also cleaned up code violating standard * Added wg copyright notice * Contributors: Mirza Shah 1.9.14 (2012-12-13 15:20) ------------------------- * lookup name (i.e. magic name) is now optional. Further cleanup...alphabetized methods, broke up some. * Contributors: Mirza Shah 1.9.13 (2012-12-11) ------------------- * Made robust to plugin package having different name from the folder it came from. ```#6 `_ * Contributors: Mirza Shah 1.9.2 (2012-10-25) ------------------ * fixed deps for downstream packages * Contributors: Dirk Thomas 1.9.1 (2012-10-24 22:02) ------------------------ * fix missing and redundant deps for downstream projects * Contributors: Dirk Thomas 1.9.0 (2012-10-24 18:31) ------------------------ * renamed test target * remove obsolete files * Fixed dependency in package.xml and minor touchups * Broke up code into further files * Catkinized pluginlib and completed integration more or less with class_loader. Heavy mods to pluginlib::ClassLoader to handle constraints of Catkin as well as delegate housekeeping to class_loader::ClassLoader * Updated to utilize newly renamed class_loader (formerly plugins) library with new file names, functions, identifiers, etc * Removed explicit dependency that should have been automatically imported from dependent package in CMakeLists.txt * Fixed unhandled exception to make all unit tests pass * Removed mention of console bridge in CMakeLists.txt, plugins now probably exports * Finished mods to utilize lower level plugins library. One test still failing, will get to that soon, but basics seem to be ok * Modding pluginlib to use new plugins library. Not done, but just doing it tosync with my laptop * Removed Poco and updated CMake and manifest files to depend on lower level plugins library * Contributors: Dirk Thomas, Mirza Shah, mirzashah 1.8.6 (2012-10-09) ------------------ * added missing boost include dirs and runtime dependency * updated cmake min version to 2.8.3 * Contributors: Dirk Thomas, Vincent Rabaud 1.8.5 (2012-10-01) ------------------ * add missing roslib dependency that happens in class_loader_imp.h * Contributors: Vincent Rabaud 1.8.4 (2012-09-30) ------------------ * updated to latest catkin * Contributors: Dirk Thomas 1.8.3 (2012-09-07) ------------------ * added tinyxml to project depends * Contributors: Dirk Thomas 1.8.2 (2012-09-06) ------------------ * updated pkg-config in manifest.xml * updated catkin variables * Contributors: Dirk Thomas 1.8.1 (2012-09-04) ------------------ * Missing LIBRARIES and DEPENDS specifiers from CMakeLists.txt, now added. * catkin-ized * updated api doc for load/create/unload methods * renamed new methods using shorter name for encouraged method * added cmake macro for hiding plugin symbols and respective rosbuild export * updated class loader according to updated REP 121 * add auto-unload for libraries using boost shared pointer * pluginlib: added a pure-virtual base class for ClassLoader called ClassLoaderBase, which is not templated. Only one function of ClassLoader is actually templated. This allows client code to not be templated where it doesn't need to be. * patch 4 for `#4887 `_ * ignore bin * accepting patch from ticket `#4887 `_ REP 116 implementation * add explicit link against tinyxml, because users of our libraries will need to link against it * link poco_lite with tinyxml * remove namespace to be compatible with tinyxml sysdep * removing back depend on common * removing rosdep.yaml, rule is in ros/rosdep.yaml * fixed tinyxml * converting to unary stack (separated from common) * applied patch from 4923, to support boost 1.46 * patch from Nick Butko osx compatability * adding unittest melonee forgot to commit * adding pluginlib tests * patch for osx linking `#4094 `_ * Fixed exception comments * Added Ubuntu platform tags to manifest * Fixing bug where the incorrect library path was passed to dlopen from pluginlib... oops. * fix in latest for `#4013 `_ to isolate boost filesystem calls into a library * patch from Wim `#3346 `_ reviewed by Eitan and I * Adding getName and isClassAvailable function calls to the class loader * inlining to avoid multiple definitions * macro deprecation * adding warning about deprecated macro PLUGINLIB_REGISTER_CLASS * pluginlib now takes pkg/type arguments, new macro PLUGINLIB_DECLARE_CLASS * pluginlib now robust to malformed manifests * Adding more descriptive error messages when libaries fail to load * Remove use of deprecated rosbuild macros * doc review completed http://www.ros.org/wiki/pluginlib/Reviews/2009-10-06_Doc_Review * fixing documentation link * fixing `#2894 `_ * Removing ROS_ERRORS in favor of adding information to the exceptions thrown * migration part 1 * Contributors: Dave Hershberger, Dirk Thomas, Ken Conley, Mirza Shah, Tully Foote, eitan, gerkey, kwc, mwise, rusu, tfoote, vpradeep, wheeler pluginlib-1.10.4/CMakeLists.txt000066400000000000000000000040321277033441200163240ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.3) project(pluginlib) find_package(catkin REQUIRED COMPONENTS class_loader rosconsole roslib cmake_modules) find_package(Boost REQUIRED COMPONENTS filesystem system) find_package(TinyXML REQUIRED) catkin_python_setup() catkin_package( INCLUDE_DIRS include CATKIN_DEPENDS class_loader rosconsole roslib DEPENDS Boost TinyXML ) include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${TinyXML_INCLUDE_DIRS}) add_executable(plugin_tool src/plugin_tool.cpp) target_link_libraries(plugin_tool ${Boost_LIBRARIES} ${catkin_LIBRARIES} ${TinyXML_LIBRARIES}) install(TARGETS plugin_tool RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}) install(DIRECTORY include/pluginlib/ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}) install(FILES share/pluginlib/typed_class_loader_template.cpp DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) install(PROGRAMS scripts/plugin_macro_update DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) if(CATKIN_ENABLE_TESTING) add_library(test_plugins EXCLUDE_FROM_ALL SHARED test/test_plugins.cpp) catkin_add_gtest(${PROJECT_NAME}_utest test/utest.cpp) if(TARGET ${PROJECT_NAME}_utest) target_link_libraries(${PROJECT_NAME}_utest ${TinyXML_LIBRARIES} ${catkin_LIBRARIES} ${Boost_LIBRARIES}) add_dependencies(${PROJECT_NAME}_utest test_plugins) endif() include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) if(COMPILER_SUPPORTS_CXX11) catkin_add_gtest(${PROJECT_NAME}_unique_ptr_test test/unique_ptr_test.cpp) if(TARGET ${PROJECT_NAME}_unique_ptr_test) target_link_libraries(${PROJECT_NAME}_unique_ptr_test ${TinyXML_LIBRARIES} ${catkin_LIBRARIES} ${Boost_LIBRARIES}) set_target_properties(${PROJECT_NAME}_unique_ptr_test PROPERTIES COMPILE_FLAGS -std=c++11 LINK_FLAGS -std=c++11) add_dependencies(${PROJECT_NAME}_unique_ptr_test test_plugins) endif() endif() endif() pluginlib-1.10.4/include/000077500000000000000000000000001277033441200152105ustar00rootroot00000000000000pluginlib-1.10.4/include/pluginlib/000077500000000000000000000000001277033441200171755ustar00rootroot00000000000000pluginlib-1.10.4/include/pluginlib/class_desc.h000066400000000000000000000066111277033441200214550ustar00rootroot00000000000000/********************************************************************* * * Software License Agreement (BSD License) * * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *********************************************************************/ #ifndef PLUGINLIB_CLASS_DESC_H_ #define PLUGINLIB_CLASS_DESC_H_ namespace pluginlib { /** * @class ClassDesc * @brief Storage for information about a given class */ class ClassDesc { public: /** * @brief Constructor for a ClassDesc * @param lookup_name The lookup name of the class * @param derived_class The type of the derived class of the class * @param base_class The type of the class, corresponds to the type of the base class * @param package The package the class lives in * @param description A description for the class * @param library_name The name of the containing library for the class (not a full path!) * @param plugin_manifest_path The path to the plugin manifest file */ ClassDesc(const std::string& lookup_name, const std::string& derived_class, const std::string& base_class, const std::string& package, const std::string& description, const std::string& library_name, const std::string& plugin_manifest_path): lookup_name_(lookup_name), derived_class_(derived_class), base_class_(base_class), package_(package), description_(description), library_name_(library_name), resolved_library_path_("UNRESOLVED"), plugin_manifest_path_(plugin_manifest_path){} std::string lookup_name_; std::string derived_class_; std::string base_class_; std::string package_; std::string description_; std::string library_name_; std::string resolved_library_path_; //This is set by pluginlib::ClassLoader at load time std::string plugin_manifest_path_; }; }; #endif pluginlib-1.10.4/include/pluginlib/class_list_macros.h000066400000000000000000000101631277033441200230530ustar00rootroot00000000000000/********************************************************************* * * Software License Agreement (BSD License) * * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *********************************************************************/ #ifndef PLUGINLIB_CLASS_LIST_MACROS_H_ #define PLUGINLIB_CLASS_LIST_MACROS_H_ #include /** * @macro This version was deprecated in favor of PLUGINLIB_DECLARE_CLASS * @param - class_name - An alias for the class (no special characters allowed) (IGNORED AS OF PLUGINLIB 1.9) * @param - class_type - The real class name with namespace qualifier (e.g. Animals::Lion) * @param - base_class_type - The real base class type from which class_type inherits */ #define PLUGINLIB_REGISTER_CLASS(class_name, class_type, base_class_type) \ CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(class_type, base_class_type, "In file " __FILE__ " pluginlib WARNING: PLUGINLIB_REGISTER_CLASS is deprecated, please use PLUGINLIB_EXPORT_CLASS instead. You can run the script 'plugin_macro_update' provided with pluginlib in your package source folder to automatically and recursively update legacy macros. Base = base_class_type, Derived = derived_class_type") /** * @macro This version is the most in use and requires package name in addition to fields in PLUGINLIB_REGISTER_CLASS * @param - pkg - The package that exports the plugin (IGNORED AS OF PLUGINLIB 1.9) * @param - class_name - An alias for the class (no special characters allowed) (IGNORED AS OF PLUGINLIB 1.9) * @param - class_type - The real class name with namespace qualifier (e.g. Animals::Lion) * @param - base_class_type - The real base class type from which class_type inherits */ #define PLUGINLIB_DECLARE_CLASS(pkg, class_name, class_type, base_class_type) \ CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(class_type, base_class_type, "pluginlib WARNING: In file " __FILE__ " PLUGINLIB_DECLARE_CLASS is deprecated, please use PLUGINLIB_EXPORT_CLASS instead. You can run the script 'plugin_macro_update' provided with pluginlib in your package source folder to automatically and recursively update legacy macros. Base = base_class_type, Derived = derived_class_type") /** * @macro This version was only made possible with pluginlib 1.9 series. It's the easiest to use and now the official way of exporting classes. * @param - class_type - The real class name with namespace qualifier (e.g. Animals::Lion) * @param - base_class_type - The real base class type from which class_type inherits */ #define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type) \ CLASS_LOADER_REGISTER_CLASS(class_type, base_class_type); #endif pluginlib-1.10.4/include/pluginlib/class_loader.h000066400000000000000000000363031277033441200220060ustar00rootroot00000000000000/* * Copyright (c) 2009, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLUGINLIB_CLASS_LOADER_H #define PLUGINLIB_CLASS_LOADER_H #include "boost/algorithm/string.hpp" #include "class_loader/multi_library_class_loader.h" #include #include "pluginlib/class_desc.h" #include "pluginlib/class_loader_base.h" #include "pluginlib/pluginlib_exceptions.h" #include "ros/console.h" #include "ros/package.h" #include "tinyxml.h" //Note: pluginlib has traditionally utilized a "lookup name" for classes that does not match its real C++ name. This was //done due to limitations of how pluginlib was implemented. As of version 1.9, a lookup name is no longer necessary and //an attempt to the merge two concepts is underway namespace pluginlib { #if __cplusplus >= 201103L template using UniquePtr = class_loader::ClassLoader::UniquePtr; #endif /** * @class ClassLoader * @brief A class to help manage and load classes */ template class ClassLoader: public ClassLoaderBase { public: typedef typename std::map::iterator ClassMapIterator; public: /** * @brief Constructor for a ClassLoader * @param package The package containing the base class * @param base_class The type of the base class for classes to be loaded * @param attrib_name The attribute to search for in manifext.xml files, defaults to "plugin" * @param plugin_xml_paths The list of paths of plugin.xml files, defaults to be crawled via ros::package::getPlugins() * @exception pluginlib::ClassLoaderException Thrown if package manifest cannot be found */ ClassLoader(std::string package, std::string base_class, std::string attrib_name = std::string("plugin"), std::vector plugin_xml_paths = std::vector()); /** * @brief Destructor for ClassLoader */ ~ClassLoader(); /** * @brief Creates an instance of a desired class, optionally loading the associated library automatically if necessary * @param lookup_name The name of the class to load * @param auto_load Specifies whether or not to automatically load the library containing the class, set to true by default * @exception pluginlib::LibraryLoadException Thrown when the library associated with the class cannot be loaded * @exception pluginlib::CreateClassException Thrown when the class cannot be instantiated * @return An instance of the class * @deprecated use either createInstance() or createUnmanagedInstance(). */ __attribute__((deprecated)) T* createClassInstance(const std::string& lookup_name, bool auto_load = true); /** * @brief Creates an instance of a desired class (which implicitly calls loadLibraryForClass() to increment the library counter). * Deleting the instance and calling unloadLibraryForClass() is automatically handled by the shared pointer. * @param lookup_name The name of the class to load * @exception pluginlib::LibraryLoadException Thrown when the library associated with the class cannot be loaded * @exception pluginlib::CreateClassException Thrown when the class cannot be instantiated * @return An instance of the class */ boost::shared_ptr createInstance(const std::string& lookup_name); #if __cplusplus >= 201103L /** * @brief Creates an instance of a desired class (which implicitly calls loadLibraryForClass() to increment the library counter). * Deleting the instance and calling unloadLibraryForClass() is automatically handled by the unique pointer. * * If you release the wrapped pointer you must manually call the original deleter when you want to destroy the released pointer. * * @param lookup_name The name of the class to load * @exception pluginlib::LibraryLoadException Thrown when the library associated with the class cannot be loaded * @exception pluginlib::CreateClassException Thrown when the class cannot be instantiated * @return An instance of the class */ UniquePtr createUniqueInstance(const std::string& lookup_name); #endif /** * @brief Creates an instance of a desired class (which implicitly calls loadLibraryForClass() to increment the library counter). * @attention The ownership is transfered to the caller, which is responsible for deleting the instance and calling unloadLibraryForClass() * (in order to decrement the associated library counter and unloading it if it is no more used). * @param lookup_name The name of the class to load * @exception pluginlib::LibraryLoadException Thrown when the library associated with the class cannot be loaded * @exception pluginlib::CreateClassException Thrown when the class cannot be instantiated * @return An instance of the class */ T* createUnmanagedInstance(const std::string& lookup_name); /** * @brief Returns a list of all available plugin manifest paths for this ClassLoader's base class type * @return A vector of strings corresponding to the paths of all available plugin manifests */ std::vector getPluginXmlPaths(); /** * @brief Returns a list of all available classes for this ClassLoader's base class type * @return A vector of strings corresponding to the names of all available classes */ std::vector getDeclaredClasses(); /** * @brief Strips the package name off of a lookup name * @param lookup_name The name of the plugin * @return The name of the plugin stripped of the package name */ virtual std::string getName(const std::string& lookup_name); /** * @brief Given the lookup name of a class, returns the type of the associated base class * @return The type of the associated base class */ virtual std::string getBaseClassType() const; /** * @brief Given the lookup name of a class, returns the type of the derived class associated with it * @param lookup_name The name of the class * @return The name of the associated derived class */ virtual std::string getClassType(const std::string& lookup_name); /** * @brief Given the lookup name of a class, returns its description * @param lookup_name The lookup name of the class * @return The description of the class */ virtual std::string getClassDescription(const std::string& lookup_name); /** * @brief Given the name of a class, returns the path to its associated library * @param lookup_name The name of the class * @return The path to the associated library */ virtual std::string getClassLibraryPath(const std::string& lookup_name); /** * @brief Given the name of a class, returns name of the containing package * @param lookup_name The name of the class * @return The name of the containing package */ virtual std::string getClassPackage(const std::string& lookup_name); /** * @brief Given the name of a class, returns the path of the associated plugin manifest * @param lookup_name The name of the class * @return The path of the associated plugin manifest */ virtual std::string getPluginManifestPath(const std::string& lookup_name); /** * @brief Returns the libraries that are registered and can be loaded * @return A vector of strings corresponding to the names of registered libraries */ virtual std::vector getRegisteredLibraries(); /** * @brief Checks if the library for a given class is currently loaded * @param lookup_name The lookup name of the class to query * @return True if the class is loaded, false otherwise */ bool isClassLoaded(const std::string& lookup_name); /** * @brief Checks if the class associated with a plugin name is available to be loaded * @param lookup_name The name of the plugin * @return True if the plugin is available, false otherwise */ virtual bool isClassAvailable(const std::string& lookup_name); /** * @brief Attempts to load the library containing a class with a given name and increments a counter for the library * @param lookup_name The lookup name of the class to load * @exception pluginlib::LibraryLoadException Thrown if the library for the class cannot be loaded */ virtual void loadLibraryForClass(const std::string & lookup_name); /** * @brief Refreshs the list of all available classes for this ClassLoader's base class type * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found */ virtual void refreshDeclaredClasses(); /** * @brief Decrements the counter for the library containing a class with a given name and attempts to unload it if the counter reaches zero * @param lookup_name The lookup name of the class to unload * @exception pluginlib::LibraryUnloadException Thrown if the library for the class cannot be unloaded * @return The number of pending unloads until the library is removed from memory */ virtual int unloadLibraryForClass(const std::string& lookup_name); private: /** * Calls a program from command line and returns output to stdout as a string */ std::string callCommandLine(const char* cmd); /** * Returns the paths to plugin.xml files. * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found * @return A vector of paths */ std::vector getPluginXmlPaths(const std::string& package, const std::string& attrib_name, bool force_recrawl=false); /** * @brief Returns the available classes * @param plugin_xml_paths The vector of paths of plugin.xml files * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found * @return A map of class names and the corresponding descriptions */ std::map determineAvailableClasses(const std::vector& plugin_xml_paths); /** * Opens a package.xml file and extracts the package name (i.e. contents of tag) */ std::string extractPackageNameFromPackageXML(const std::string& package_xml_path); /** * Gets a list of paths to try to find a library. As we transition from rosbuild to Catkin build systems, plugins can be found in the old rosbuild place (pkg_name/lib usually) or somewhere in the Catkin build space */ std::vector getAllLibraryPathsToTry(const std::string& library_name, const std::string& exporting_package_name); /** * Returns the paths where libraries are installed according to the Catkin build system. */ std::vector getCatkinLibraryPaths(); /** * @brief Returns an error message for an unknown class * @param lookup_name The name of the class * @return The error message */ std::string getErrorStringForUnknownClass(const std::string& lookup_name); /** * Gets the standard path separator for the native OS (e.g. "/" on *nix, "\" on windows) */ std::string getPathSeparator(); /** * Gets the path where rosbuild build system thinks plugins are installed */ std::string getROSBuildLibraryPath(const std::string& exporting_package_name); /** * Gets the package name from a path to a plugin XML file */ std::string getPackageFromPluginXMLFilePath(const std::string & path); /** * Joins two filesystem paths together utilzing appropriate path separator */ std::string joinPaths(const std::string& path1, const std::string& path2); /** *Parses a string delimited by newlines into a vector of strings */ std::vector parseToStringVector(std::string newline_delimited_str); /** * Parses a plugin XML file and inserts the appropriate ClassDesc entries into the passes classes_available map */ void processSingleXMLPluginFile(const std::string& xml_file, std::map& class_available); /** * Strips all but the filename from an explicit file path. */ std::string stripAllButFileFromPath(const std::string& path); /** * @brief Helper function for unloading a shared library * @param library_path The exact path to the library to unload * @return The number of pending unloads until the library is removed from memory */ int unloadClassLibraryInternal(const std::string& library_path); private: std::vector plugin_xml_paths_; std::map classes_available_; //Map from library to class's descriptions described in XML std::string package_; std::string base_class_; std::string attrib_name_; class_loader::MultiLibraryClassLoader lowlevel_class_loader_; //The underlying classloader }; }; #include "class_loader_imp.h" //Note: The implementation of the methods is in a separate file for clarity #endif //PLUGINLIB_CLASS_LOADER_H pluginlib-1.10.4/include/pluginlib/class_loader_base.h000066400000000000000000000147431277033441200230040ustar00rootroot00000000000000 /* * Copyright (c) 2012, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLUGINLIB_CLASS_LOADER_BASE_H #define PLUGINLIB_CLASS_LOADER_BASE_H #include #include namespace pluginlib { /** * Pure virtual base class of pluginlib::ClassLoader which is not * templated. This allows the writing of non-templated manager code * which can call all the administrative functions of ClassLoaders - * everything except createClassInstance(), createInstance() * and createUnmanagedInstance(). */ class ClassLoaderBase { public: /** * @brief Empty virtual destructor */ virtual ~ClassLoaderBase() {} /** * @brief Returns a list of all available plugin manifest paths for this ClassLoader's base class type * @return A vector of strings corresponding to the paths of all available plugin manifests */ virtual std::vector getPluginXmlPaths() = 0; /** * @brief Returns a list of all available classes for this ClassLoader's base class type * @return A vector of strings corresponding to the names of all available classes */ virtual std::vector getDeclaredClasses() = 0; /** * @brief Refreshs the list of all available classes for this ClassLoader's base class type * @exception pluginlib::LibraryLoadException Thrown if package manifest cannot be found */ virtual void refreshDeclaredClasses() = 0; /** * @brief Strips the package name off of a lookup name * @param lookup_name The name of the plugin * @return The name of the plugin stripped of the package name */ virtual std::string getName(const std::string& lookup_name) = 0; /** * @brief Checks if the class associated with a plugin name is available to be loaded * @param lookup_name The name of the plugin * @return True if the plugin is available, false otherwise */ virtual bool isClassAvailable(const std::string& lookup_name) = 0; /** * @brief Given the lookup name of a class, returns the type of the derived class associated with it * @param lookup_name The name of the class * @return The name of the associated derived class */ virtual std::string getClassType(const std::string& lookup_name) = 0; /** * @brief Given the lookup name of a class, returns its description * @param lookup_name The lookup name of the class * @return The description of the class */ virtual std::string getClassDescription(const std::string& lookup_name) = 0; /** * @brief Given the lookup name of a class, returns the type of the associated base class * @return The type of the associated base class */ virtual std::string getBaseClassType() const = 0; /** * @brief Given the name of a class, returns name of the containing package * @param lookup_name The name of the class * @return The name of the containing package */ virtual std::string getClassPackage(const std::string& lookup_name) = 0; /** * @brief Given the name of a class, returns the path of the associated plugin manifest * @param lookup_name The name of the class * @return The path of the associated plugin manifest */ virtual std::string getPluginManifestPath(const std::string& lookup_name) = 0; /** * @brief Checks if a given class is currently loaded * @param lookup_name The lookup name of the class to query * @return True if the class is loaded, false otherwise */ virtual bool isClassLoaded(const std::string& lookup_name) = 0; /** * @brief Attempts to load a class with a given name * @param lookup_name The lookup name of the class to load * @exception pluginlib::LibraryLoadException Thrown if the library for the class cannot be loaded */ virtual void loadLibraryForClass(const std::string & lookup_name) = 0; /** * @brief Attempts to unload a class with a given name * @param lookup_name The lookup name of the class to unload * @exception pluginlib::LibraryUnloadException Thrown if the library for the class cannot be unloaded * @return The number of pending unloads until the library is removed from memory */ virtual int unloadLibraryForClass(const std::string& lookup_name) = 0; /** * @brief Returns the libraries that are registered and can be loaded * @return A vector of strings corresponding to the names of registered libraries */ virtual std::vector getRegisteredLibraries() = 0; /** * @brief Given the name of a class, returns the path to its associated library * @param lookup_name The name of the class * @return The path to the associated library */ virtual std::string getClassLibraryPath(const std::string& lookup_name) = 0; }; } #endif pluginlib-1.10.4/include/pluginlib/class_loader_imp.h000066400000000000000000000742401277033441200226550ustar00rootroot00000000000000/********************************************************************* * * Software License Agreement (BSD License) * * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *********************************************************************/ //NOTE: this should really never be included on its own, but just in case someone is bad we'll guard #ifndef PLUGINLIB_CLASS_LOADER_IMP_H_ #define PLUGINLIB_CLASS_LOADER_IMP_H_ #include "boost/bind.hpp" #include "boost/filesystem.hpp" #include #include #include "ros/package.h" #include #include namespace pluginlib { template ClassLoader::ClassLoader(std::string package, std::string base_class, std::string attrib_name, std::vector plugin_xml_paths) : plugin_xml_paths_(plugin_xml_paths), package_(package), base_class_(base_class), attrib_name_(attrib_name), lowlevel_class_loader_(false) //NOTE: The parameter to the class loader enables/disables on-demand class loading/unloading. Leaving it off for now...libraries will be loaded immediately and won't be unloaded until class loader is destroyed or force unload. /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Creating ClassLoader, base = %s, address = %p", base_class.c_str(), this); if (ros::package::getPath(package_).empty()) { throw pluginlib::ClassLoaderException("Unable to find package: " + package_); } if (plugin_xml_paths_.size() == 0) { plugin_xml_paths_ = getPluginXmlPaths(package_, attrib_name_); } classes_available_ = determineAvailableClasses(plugin_xml_paths_); ROS_DEBUG_NAMED("pluginlib.ClassLoader","Finished constructring ClassLoader, base = %s, address = %p", base_class.c_str(), this); } template ClassLoader::~ClassLoader() /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Destroying ClassLoader, base = %s, address = %p", getBaseClassType().c_str(), this); } template std::string ClassLoader::callCommandLine(const char* cmd) /***************************************************************************/ { FILE* pipe = popen(cmd, "r"); if (!pipe) return "ERROR"; char buffer[128]; std::string result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) result += buffer; } pclose(pipe); return result; } template T* ClassLoader::createClassInstance(const std::string& lookup_name, bool auto_load) /***************************************************************************/ { //Note: This method is deprecated ROS_DEBUG_NAMED("pluginlib.ClassLoader","In deprecated call createClassInstance(), lookup_name = %s, auto_load = %i.", (lookup_name.c_str()), auto_load); if (auto_load && !isClassLoaded(lookup_name)) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Autoloading class library before attempting to create instance."); loadLibraryForClass(lookup_name); } try { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to create instance through low-level MultiLibraryClassLoader..."); T* obj = lowlevel_class_loader_.createUnmanagedInstance(getClassType(lookup_name)); ROS_DEBUG_NAMED("pluginlib.ClassLoader","Instance created with object pointer = %p", obj); return obj; } catch (const class_loader::CreateClassException& ex) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","CreateClassException about to be raised for class %s", lookup_name.c_str()); throw pluginlib::CreateClassException(ex.what()); } } template boost::shared_ptr ClassLoader::createInstance(const std::string& lookup_name) /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to create managed instance for class %s.", lookup_name.c_str()); if (!isClassLoaded(lookup_name)) loadLibraryForClass(lookup_name); try { std::string class_type = getClassType(lookup_name); ROS_DEBUG_NAMED("pluginlib.ClassLoader","%s maps to real class type %s", lookup_name.c_str(), class_type.c_str()); boost::shared_ptr obj = lowlevel_class_loader_.createInstance(class_type); ROS_DEBUG_NAMED("pluginlib.ClassLoader","boost::shared_ptr to object of real type %s created.", class_type.c_str()); return obj; } catch (const class_loader::CreateClassException& ex) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Exception raised by low-level multi-library class loader when attempting to create instance of class %s.", lookup_name.c_str()); throw pluginlib::CreateClassException(ex.what()); } } #if __cplusplus >= 201103L template UniquePtr ClassLoader::createUniqueInstance(const std::string& lookup_name) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to create managed (unique) instance for class %s.", lookup_name.c_str()); if (!isClassLoaded(lookup_name)) loadLibraryForClass(lookup_name); try { std::string class_type = getClassType(lookup_name); ROS_DEBUG_NAMED("pluginlib.ClassLoader","%s maps to real class type %s", lookup_name.c_str(), class_type.c_str()); UniquePtr obj = lowlevel_class_loader_.createUniqueInstance(class_type); ROS_DEBUG_NAMED("pluginlib.ClassLoader","std::unique_ptr to object of real type %s created.", class_type.c_str()); return obj; } catch (const class_loader::CreateClassException& ex) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Exception raised by low-level multi-library class loader when attempting to create instance of class %s.", lookup_name.c_str()); throw pluginlib::CreateClassException(ex.what()); } } #endif template T* ClassLoader::createUnmanagedInstance(const std::string& lookup_name) /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to create UNMANAGED instance for class %s.", lookup_name.c_str()); if (!isClassLoaded(lookup_name)) loadLibraryForClass(lookup_name); T* instance = 0; try { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to create instance through low level multi-library class loader."); std::string class_type = getClassType(lookup_name); ROS_DEBUG_NAMED("pluginlib.ClassLoader","%s maps to real class type %s", lookup_name.c_str(), class_type.c_str()); instance = lowlevel_class_loader_.createUnmanagedInstance(class_type); ROS_DEBUG_NAMED("pluginlib.ClassLoader","Instance of type %s created.", class_type.c_str()); } catch (const class_loader::CreateClassException& ex) //mas - change exception type here (DONE) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Exception raised by low-level multi-library class loader when attempting to create UNMANAGED instance of class %s.", lookup_name.c_str()); throw pluginlib::CreateClassException(ex.what()); } return instance; } template std::vector ClassLoader::getPluginXmlPaths(const std::string& package, const std::string& attrib_name, bool force_recrawl) /***************************************************************************/ { //Pull possible files from manifests of packages which depend on this package and export class std::vector paths; ros::package::getPlugins(package, attrib_name, paths, force_recrawl); return paths; } template std::map ClassLoader::determineAvailableClasses(const std::vector& plugin_xml_paths) /***************************************************************************/ { //mas - This method requires major refactoring...not only is it really long and confusing but a lot of the comments do not seem to be correct. With time I keep correcting small things, but a good rewrite is needed. ROS_DEBUG_NAMED("pluginlib.ClassLoader","Entering determineAvailableClasses()..."); std::map classes_available; //Walk the list of all plugin XML files (variable "paths") that are exported by the build system for (std::vector::const_iterator it = plugin_xml_paths.begin(); it != plugin_xml_paths.end(); ++it) { processSingleXMLPluginFile(*it, classes_available); } ROS_DEBUG_NAMED("pluginlib.ClassLoader","Exiting determineAvailableClasses()..."); return classes_available; } template std::string ClassLoader::extractPackageNameFromPackageXML(const std::string& package_xml_path) /***************************************************************************/ { TiXmlDocument document; document.LoadFile(package_xml_path); TiXmlElement* doc_root_node = document.FirstChildElement("package"); if (doc_root_node == NULL) { ROS_ERROR_NAMED("pluginlib.ClassLoader","Could not find a root element for package manifest at %s.", package_xml_path.c_str()); return ""; } assert(doc_root_node == document.RootElement()); TiXmlElement* package_name_node = doc_root_node->FirstChildElement("name"); if(package_name_node == NULL) { ROS_ERROR_NAMED("pluginlib.ClassLoader","package.xml at %s does not have a tag! Cannot determine package which exports plugin.", package_xml_path.c_str()); return ""; } return(package_name_node->GetText()); } template std::vector ClassLoader::getCatkinLibraryPaths() /***************************************************************************/ { //TODO: This needs to be replaced with an api call return(parseToStringVector(callCommandLine("catkin_find --lib"))); } template std::vector ClassLoader::getAllLibraryPathsToTry(const std::string& library_name, const std::string& exporting_package_name) /***************************************************************************/ { //Catkin-rosbuild Backwards Compatability Rules - Note library_name may be prefixed with relative path (e.g. "/lib/libFoo") //1. Try catkin library paths (catkin_find --libs) + library_name + extension //2. Try catkin library paths (catkin_find -- libs) + stripAllButFileFromPath(library_name) + extension //3. Try export_pkg/library_name + extension std::vector all_paths; std::vector all_paths_without_extension = getCatkinLibraryPaths(); all_paths_without_extension.push_back(getROSBuildLibraryPath(exporting_package_name)); bool debug_library_suffix = (class_loader::systemLibrarySuffix().compare(0, 1, "d") == 0); std::string non_debug_suffix; if(debug_library_suffix) { non_debug_suffix = class_loader::systemLibrarySuffix().substr(1); } else { non_debug_suffix = class_loader::systemLibrarySuffix(); } std::string library_name_with_extension = library_name + non_debug_suffix; std::string stripped_library_name = stripAllButFileFromPath(library_name); std::string stripped_library_name_with_extension = stripped_library_name + non_debug_suffix; const std::string path_separator = getPathSeparator(); for(unsigned int c = 0; c < all_paths_without_extension.size(); c++) { std::string current_path = all_paths_without_extension.at(c); all_paths.push_back(current_path + path_separator + library_name_with_extension); all_paths.push_back(current_path + path_separator + stripped_library_name_with_extension); // We're in debug mode, try debug libraries as well if(debug_library_suffix) { all_paths.push_back(current_path + path_separator + library_name + class_loader::systemLibrarySuffix()); all_paths.push_back(current_path + path_separator + stripped_library_name + class_loader::systemLibrarySuffix()); } } return(all_paths); } template bool ClassLoader::isClassLoaded(const std::string& lookup_name) /***************************************************************************/ { return lowlevel_class_loader_.isClassAvailable(getClassType(lookup_name)); //mas - (DONE) } template std::string ClassLoader::getBaseClassType() const /***************************************************************************/ { return base_class_; } template std::string ClassLoader::getClassDescription(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it != classes_available_.end()) return it->second.description_; return ""; } template std::string ClassLoader::getClassType(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it != classes_available_.end()) return it->second.derived_class_; return ""; } template std::string ClassLoader::getClassLibraryPath(const std::string& lookup_name) /***************************************************************************/ { if (classes_available_.find(lookup_name) == classes_available_.end()) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Class %s has no mapping in classes_available_.", lookup_name.c_str()); return ""; } ClassMapIterator it = classes_available_.find(lookup_name); std::string library_name = it->second.library_name_; ROS_DEBUG_NAMED("pluginlib.ClassLoader","Class %s maps to library %s in classes_available_.", lookup_name.c_str(), library_name.c_str()); std::vector paths_to_try = getAllLibraryPathsToTry(library_name, it->second.package_); ROS_DEBUG_NAMED("pluginlib.ClassLoader","Iterating through all possible paths where %s could be located...", library_name.c_str()); for(std::vector::const_iterator it = paths_to_try.begin(); it != paths_to_try.end(); it++) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Checking path %s ", it->c_str()); if (boost::filesystem::exists(*it)) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Library %s found at explicit path %s.", library_name.c_str(), it->c_str()); return *it; } } return ""; } template std::string ClassLoader::getClassPackage(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it != classes_available_.end()) return it->second.package_; return ""; } template std::vector ClassLoader::getPluginXmlPaths() /***************************************************************************/ { return plugin_xml_paths_; } template std::vector ClassLoader::getDeclaredClasses() /***************************************************************************/ { std::vector lookup_names; for (ClassMapIterator it = classes_available_.begin(); it != classes_available_.end(); ++it) lookup_names.push_back(it->first); return lookup_names; } template std::string ClassLoader::getErrorStringForUnknownClass(const std::string& lookup_name) /***************************************************************************/ { std::string declared_types; std::vector types = getDeclaredClasses(); for ( unsigned int i = 0; i < types.size(); i ++) { declared_types = declared_types + std::string(" ") + types[i]; } return "According to the loaded plugin descriptions the class " + lookup_name + " with base class type " + base_class_ + " does not exist. Declared types are " + declared_types; } template std::string ClassLoader::getName(const std::string& lookup_name) /***************************************************************************/ { //remove the package name to get the raw plugin name std::vector split; boost::split(split, lookup_name, boost::is_any_of("/:")); return split.back(); } template std::string ClassLoader::getPackageFromPluginXMLFilePath(const std::string & plugin_xml_file_path) /***************************************************************************/ { //Note: This method takes an input a path to a plugin xml file and must determine which //package the XML file came from. This is not necessariliy the same thing as the member //variable "package_". The plugin xml file can be located anywhere in the source tree for a //package //rosbuild: //1. Find nearest encasing manifest.xml //2. Once found, the name of the folder containg the manifest should be the package name we are looking for //3. Confirm package is findable with rospack //catkin: //1. Find nearest encasing package.xml //2. Extract name of package from package.xml std::string package_name; boost::filesystem::path p(plugin_xml_file_path); boost::filesystem::path parent = p.parent_path(); //Figure out exactly which package the passed XML file is exported by. while (true) { if(boost::filesystem::exists(parent / "package.xml")) { std::string package_file_path = (boost::filesystem::path(parent / "package.xml")).string(); return(extractPackageNameFromPackageXML(package_file_path)); } else if (boost::filesystem::exists(parent / "manifest.xml")) { #if BOOST_FILESYSTEM_VERSION >= 3 std::string package = parent.filename().string(); #else std::string package = parent.filename(); #endif std::string package_path = ros::package::getPath(package); if (plugin_xml_file_path.find(package_path) == 0) //package_path is a substr of passed plugin xml path { package_name = package; break; } } //Recursive case - hop one folder up parent = parent.parent_path().string(); //Base case - reached root and cannot find what we're looking for if (parent.string().empty()) return ""; } return package_name; } template std::string ClassLoader::getPathSeparator() /***************************************************************************/ { #if BOOST_FILESYSTEM_VERSION >= 3 return(boost::filesystem::path("/").native()); #else return(boost::filesystem::path("/").external_file_string()); #endif } template std::string ClassLoader::getPluginManifestPath(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it != classes_available_.end()) return it->second.plugin_manifest_path_; return ""; } template std::vector ClassLoader::getRegisteredLibraries() /***************************************************************************/ { return(lowlevel_class_loader_.getRegisteredLibraries()); } template std::string ClassLoader::getROSBuildLibraryPath(const std::string& exporting_package_name) /***************************************************************************/ { return(ros::package::getPath(exporting_package_name)); } template bool ClassLoader::isClassAvailable(const std::string& lookup_name) /***************************************************************************/ { return classes_available_.find(lookup_name) != classes_available_.end(); } template std::string ClassLoader::joinPaths(const std::string& path1, const std::string& path2) /***************************************************************************/ { boost::filesystem::path p1(path1); return (p1 / path2).string(); } template void ClassLoader::loadLibraryForClass(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it == classes_available_.end()) { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Class %s has no mapping in classes_available_.", lookup_name.c_str()); throw pluginlib::LibraryLoadException(getErrorStringForUnknownClass(lookup_name)); } std::string library_path = getClassLibraryPath(lookup_name); if (library_path == "") { ROS_DEBUG_NAMED("pluginlib.ClassLoader","No path could be found to the library containing %s.", lookup_name.c_str()); std::ostringstream error_msg; error_msg << "Could not find library corresponding to plugin " << lookup_name << ". Make sure the plugin description XML file has the correct name of the library and that the library actually exists."; throw pluginlib::LibraryLoadException(error_msg.str()); } try { lowlevel_class_loader_.loadLibrary(library_path); it->second.resolved_library_path_ = library_path; } catch(const class_loader::LibraryLoadException& ex) { std::string error_string = "Failed to load library " + library_path + ". Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: " + ex.what(); throw pluginlib::LibraryLoadException(error_string); } } template std::vector ClassLoader::parseToStringVector(std::string newline_delimited_str) /***************************************************************************/ { std::string next; std::vector parse_result; for(unsigned int c = 0; c < newline_delimited_str.size(); c++) { char ch = newline_delimited_str.at(c); if(ch == '\n') { parse_result.push_back(next); next = ""; } else next.push_back(ch); } return(parse_result); } template void ClassLoader::processSingleXMLPluginFile(const std::string& xml_file, std::map& classes_available) /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Processing xml file %s...", xml_file.c_str()); TiXmlDocument document; document.LoadFile(xml_file); TiXmlElement * config = document.RootElement(); if (config == NULL) { ROS_ERROR_NAMED("pluginlib.ClassLoader","Skipping XML Document \"%s\" which had no Root Element. This likely means the XML is malformed or missing.", xml_file.c_str()); return; } if (config->ValueStr() != "library" && config->ValueStr() != "class_libraries") { ROS_ERROR_NAMED("pluginlib.ClassLoader","The XML document \"%s\" given to add must have either \"library\" or \ \"class_libraries\" as the root tag", xml_file.c_str()); return; } //Step into the filter list if necessary if (config->ValueStr() == "class_libraries") { config = config->FirstChildElement("library"); } TiXmlElement* library = config; while ( library != NULL) { std::string library_path = library->Attribute("path"); if (library_path.size() == 0) { ROS_ERROR_NAMED("pluginlib.ClassLoader","Failed to find Path Attirbute in library element in %s", xml_file.c_str()); continue; } std::string package_name = getPackageFromPluginXMLFilePath(xml_file); if (package_name == "") ROS_ERROR_NAMED("pluginlib.ClassLoader","Could not find package manifest (neither package.xml or deprecated manifest.xml) at same directory level as the plugin XML file %s. Plugins will likely not be exported properly.\n)", xml_file.c_str()); TiXmlElement* class_element = library->FirstChildElement("class"); while (class_element) { std::string derived_class; if (class_element->Attribute("type") != NULL) { derived_class = std::string(class_element->Attribute("type")); } else { throw pluginlib::ClassLoaderException("Class could not be loaded. Attribute 'type' in class tag is missing."); } std::string base_class_type; if (class_element->Attribute("base_class_type") != NULL) { base_class_type = std::string(class_element->Attribute("base_class_type")); } else { throw pluginlib::ClassLoaderException("Class could not be loaded. Attribute 'base_class_type' in class tag is missing."); } std::string lookup_name; if(class_element->Attribute("name") != NULL) { lookup_name = class_element->Attribute("name"); ROS_DEBUG_NAMED("pluginlib.ClassLoader","XML file specifies lookup name (i.e. magic name) = %s.", lookup_name.c_str()); } else { ROS_DEBUG_NAMED("pluginlib.ClassLoader","XML file has no lookup name (i.e. magic name) for class %s, assuming lookup_name == real class name.", derived_class.c_str()); lookup_name = derived_class; } //make sure that this class is of the right type before registering it if(base_class_type == base_class_){ // register class here TiXmlElement* description = class_element->FirstChildElement("description"); std::string description_str; if (description) description_str = description->GetText() ? description->GetText() : ""; else description_str = "No 'description' tag for this plugin in plugin description file."; classes_available.insert(std::pair(lookup_name, ClassDesc(lookup_name, derived_class, base_class_type, package_name, description_str, library_path, xml_file))); } //step to next class_element class_element = class_element->NextSiblingElement( "class" ); } library = library->NextSiblingElement( "library" ); } } template void ClassLoader::refreshDeclaredClasses() /***************************************************************************/ { ROS_DEBUG_NAMED("pluginlib.ClassLoader","Refreshing declared classes."); // determine classes not currently loaded for removal std::list remove_classes; for (std::map::const_iterator it = classes_available_.begin(); it != classes_available_.end(); it++) { std::string resolved_library_path = it->second.resolved_library_path_; std::vector open_libs = lowlevel_class_loader_.getRegisteredLibraries(); if(std::find(open_libs.begin(), open_libs.end(), resolved_library_path) != open_libs.end()) remove_classes.push_back(it->first); } while (!remove_classes.empty()) { classes_available_.erase(remove_classes.front()); remove_classes.pop_front(); } // add new classes plugin_xml_paths_ = getPluginXmlPaths(package_, attrib_name_, true); std::map updated_classes = determineAvailableClasses(plugin_xml_paths_); for (std::map::const_iterator it = updated_classes.begin(); it != updated_classes.end(); it++) { if (classes_available_.find(it->first) == classes_available_.end()) classes_available_.insert(std::pair(it->first, it->second)); } } template std::string ClassLoader::stripAllButFileFromPath(const std::string& path) /***************************************************************************/ { std::string only_file; size_t c = path.find_last_of(getPathSeparator()); if(c == std::string::npos) return(path); else return(path.substr(c, path.size())); } template int ClassLoader::unloadLibraryForClass(const std::string& lookup_name) /***************************************************************************/ { ClassMapIterator it = classes_available_.find(lookup_name); if (it != classes_available_.end() && it->second.resolved_library_path_ != "UNRESOLVED") { std::string library_path = it->second.resolved_library_path_; ROS_DEBUG_NAMED("pluginlib.ClassLoader","Attempting to unload library %s for class %s", library_path.c_str(), lookup_name.c_str()); return unloadClassLibraryInternal(library_path); } else { throw pluginlib::LibraryUnloadException(getErrorStringForUnknownClass(lookup_name)); } } template int ClassLoader::unloadClassLibraryInternal(const std::string& library_path) /***************************************************************************/ { return(lowlevel_class_loader_.unloadLibrary(library_path)); } } #endif pluginlib-1.10.4/include/pluginlib/pluginlib_exceptions.h000066400000000000000000000063101277033441200235740ustar00rootroot00000000000000 /* * Copyright (c) 2012, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLUGINLIB_EXCEPTIONS_H_DEFINED #define PLUGINLIB_EXCEPTIONS_H_DEFINED #include namespace pluginlib { /** * @class PluginlibException * @brief A base class for all pluginlib exceptions that inherits from std::runtime_exception */ class PluginlibException: public std::runtime_error { public: PluginlibException(const std::string error_desc) : std::runtime_error(error_desc) {} }; /** * @class LibraryLoadException * @brief An exception class thrown when pluginlib is unable to load the library associated with a given plugin */ class LibraryLoadException: public PluginlibException { public: LibraryLoadException(const std::string error_desc) : PluginlibException(error_desc) {} }; /** * @class ClassLoaderException * @brief An exception class thrown when pluginlib is unable to instantiate a class loader */ class ClassLoaderException: public PluginlibException { public: ClassLoaderException(const std::string error_desc) : PluginlibException(error_desc) {} }; /** * @class LibraryUnloadException * @brief An exception class thrown when pluginlib is unable to unload the library associated with a given plugin */ class LibraryUnloadException: public PluginlibException { public: LibraryUnloadException(const std::string error_desc) : PluginlibException(error_desc) {} }; /** * @class CreateClassException * @brief An exception class thrown when pluginlib is unable to create the class associated with a given plugin */ class CreateClassException: public PluginlibException { public: CreateClassException(const std::string error_desc) : PluginlibException(error_desc) {} }; } #endif pluginlib-1.10.4/package.xml000066400000000000000000000026471277033441200157130ustar00rootroot00000000000000 pluginlib 1.10.4 The pluginlib package provides tools for writing and dynamically loading plugins using the ROS build infrastructure. To work, these tools require plugin providers to register their plugins in the package.xml of their package. Mikael Arguedas BSD http://www.ros.org/wiki/pluginlib https://github.com/ros/pluginlib/issues https://github.com/ros/pluginlib Eitan Marder-Eppstein Tully Foote Dirk Thomas Mirza Shah catkin boost cmake_modules class_loader rosconsole roslib tinyxml boost class_loader rosconsole roslib tinyxml pluginlib-1.10.4/scripts/000077500000000000000000000000001277033441200152545ustar00rootroot00000000000000pluginlib-1.10.4/scripts/plugin_macro_update000077500000000000000000000044211277033441200212240ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of the Willow Garage nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Run this script to update legacy pluginlib macros to utilize new # simplified PLUGINLIB_EXPORT_CLASS macro. import subprocess cmd = "find . -type f ! -name '*.svn-base' -a ! -name '*.hg' -a ! -name '*.git' -a \( -name '*.c*' -o -name '*.h*' \) -exec sed -i '%(rule)s' {} \;" rules = ['s/PLUGINLIB_DECLARE_CLASS(.*,.*,\(.*\),\(.*\))/PLUGINLIB_EXPORT_CLASS(\\1,\\2)/g', 's/PLUGINLIB_REGISTER_CLASS(.*,\(.*\),\(.*\))/PLUGINLIB_EXPORT_CLASS(\\1,\\2)/g', ] for rule in rules: full_cmd = cmd%locals() print ("Running %s"%full_cmd) ret_code = subprocess.call(full_cmd, shell=True) if ret_code == 0: print ("success") else: print ("failure") pluginlib-1.10.4/setup.py000066400000000000000000000002411277033441200152740ustar00rootroot00000000000000#!/usr/bin/env python from distutils.core import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup() setup(**d) pluginlib-1.10.4/share/000077500000000000000000000000001277033441200146675ustar00rootroot00000000000000pluginlib-1.10.4/share/pluginlib/000077500000000000000000000000001277033441200166545ustar00rootroot00000000000000pluginlib-1.10.4/share/pluginlib/typed_class_loader_template.cpp000066400000000000000000000050261277033441200251160ustar00rootroot00000000000000/* * Copyright (c) 2012, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include @ extern "C" { std::vector availablePlugins(const std::string& package_name) { pluginlib::ClassLoader<$> class_loader(package_name, "$"); return(class_loader.getDeclaredClasses()); } bool loadPlugin(const std::string& package_name, const std::string& class_name) { pluginlib::ClassLoader<$> class_loader(package_name, "$"); try { class_loader.createInstance(class_name); return true; } catch(...) { return false; } } std::string whereIsPluginLocated(const std::string& package_name, const std::string& class_name) { pluginlib::ClassLoader<$> class_loader(package_name, "$"); try { return class_loader.getClassLibraryPath(class_name); } catch(...) { return ("Could not find location of plugin " + class_name); } } } pluginlib-1.10.4/src/000077500000000000000000000000001277033441200143545ustar00rootroot00000000000000pluginlib-1.10.4/src/plugin_tool.cpp000066400000000000000000000303021277033441200174110ustar00rootroot00000000000000 /* * Copyright (c) 2012, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include using std::cout; using std::endl; using std::vector; using std::string; vector g_cli_arguments; void* g_class_loader_library_handle = NULL; //Handle CLI request void processUserCommand(); void handleFindPluginRequest(); void handleListPluginsRequest(); void handleLoadPluginRequest(); //Command line arguments vector getCLIArguments(); void setCLIArguments(int argc, char* argv[]); bool verifyCLIArguments(); string baseClass(){return(getCLIArguments().at(1));} string baseClassHeader(){return(getCLIArguments().at(2));} string packageName(){return(getCLIArguments().at(3));} string commandVerb(){return(getCLIArguments().at(4));} string pluginName(){return(getCLIArguments().at(5));} //Typed Class Loader Interface (shared object) string callCommandLine(const char* cmd); string determineIncludePathsForBaseClassHeaderDependencies(); void generateAndLoadTypedPluginInterface(); void generateFile(string filename, string contents); string generatedSharedLibrary(){return "libTypedPluginInterface.so";} string generatedObjFile(){return "typedPluginInterface.o";} string generatedCppFile(){return "typedPluginInterface.cpp";} string getPluginlibSharedFolder(); string getTypedClassLoaderTemplate(); string getTypedClassLoaderTemplateWithBaseSet(); vector parseToStringVector(std::string newline_delimited_str); string stripNewlineCharacters(const std::string& s); string templateCppFileWithoutExtension(){return "typedPluginInterface";} string templateCppFile(){return templateCppFileWithoutExtension() + ".cpp";} string templateCppFileAbsolutePath(){return getPluginlibSharedFolder() + "/" + templateCppFile();} int main(int argc, char* argv[]) /*****************************************************************************/ { cout << "plugin_tool - A command line tool for pluginlib testing" << endl; cout << "-------------------------------------------------------" << endl; setCLIArguments(argc, argv); if(!verifyCLIArguments()) { cout << "Error: Invalid arguments passed to plugin_tool." << endl; exit(-1); } cout << "Base class = " << baseClass() << endl; cout << "Package name = " << packageName() << endl << endl; generateAndLoadTypedPluginInterface(); processUserCommand(); return 0; } std::string callCommandLine(const char* cmd) /***************************************************************************/ { FILE* pipe = popen(cmd, "r"); if (!pipe) return "ERROR"; char buffer[128]; std::string result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) result += buffer; } pclose(pipe); return result; } string determineIncludePathsForBaseClassHeaderDependencies() /*****************************************************************************/ { string cmd = "rospack cflags-only-I " + packageName(); return(stripNewlineCharacters(callCommandLine(cmd.c_str()))); } void generateAndLoadTypedPluginInterface() /*****************************************************************************/ { cout << "Generating typed plugin interface cpp..." << endl; string code = getTypedClassLoaderTemplateWithBaseSet(); cout << "***************************************************" << endl; cout << code << endl; cout << "***************************************************" << endl; cout << "Outputting to file " << templateCppFile() << "..." << endl; generateFile(generatedCppFile(), code); cout << "Building interface shared object..." << endl; string cmd1 = "g++ -fPIC -I" + determineIncludePathsForBaseClassHeaderDependencies() + " -c " + generatedCppFile(); string cmd2 = "g++ -shared -o " + generatedSharedLibrary() + " " + generatedObjFile(); cout << "Command 1 = " << cmd1 << endl; cout << "Command 2 = " << cmd2 << endl; if(-1 == system(cmd1.c_str())) { cout << "Error: Failed to compile interface." << endl; exit(-1); } else { cout << "Interface compiled to an object file, attempting to build..." << endl; if(-1 == system(cmd2.c_str())) { cout << "Error: Failed to build shared object." << endl; exit(-1); } else cout << "Build of shared object succeeded." << endl; } cout << "Loading shared object into memory." << endl; g_class_loader_library_handle = dlopen("libTypedPluginInterface.so", RTLD_LAZY); if(g_class_loader_library_handle) cout << "Shared object successfully loaded into memory." << endl; else { cout << "Error: Failed to load shared object into memory." << endl; exit(-1); } } template T getPluginFunction(const std::string& function_name) /*****************************************************************************/ { void* ptr = dlsym(g_class_loader_library_handle, function_name.c_str()); return((T)(ptr)); } vector getCLIArguments() /*****************************************************************************/ { return(g_cli_arguments); } void generateFile(string filename, string contents) /*****************************************************************************/ { std::ofstream file; file.open(filename.c_str()); file << contents; file.close(); } std::string getPluginlibSharedFolder() /***************************************************************************/ { vector allVals = parseToStringVector(callCommandLine("catkin_find pluginlib --share")); assert(allVals.size() > 0); return(allVals.at(0)); } string getTypedClassLoaderTemplate() /*****************************************************************************/ { std::ifstream file; string path = getPluginlibSharedFolder() + "/typed_class_loader_template.cpp"; file.open(path.c_str()); if(!file) { cout << "Error: Cannot find file " + path + " to generate class loader"; exit(-1); } string contents; while(!file.eof()) { char c; file.get(c); contents.push_back(c); cout << c; } return contents; } string getTypedClassLoaderTemplateWithBaseSet() /*****************************************************************************/ { string class_template = getTypedClassLoaderTemplate(); string class_with_type_set; for(unsigned int c = 0; c < class_template.size(); c++) { if(class_template.at(c) == '$') class_with_type_set += baseClass(); else if(class_template.at(c) == '@') class_with_type_set += "#include \"" + baseClassHeader() + "\""; else class_with_type_set.push_back(class_template.at(c)); } return(class_with_type_set); } void handleFindPluginRequest() /*****************************************************************************/ { //string whereIsPluginLocated(const string& package_name, const string& class_name) typedef std::string (*WhereIsFunc)(const string&, const string&); WhereIsFunc f = getPluginFunction("whereIsPluginLocated"); cout << "Attempting to find plugin " << pluginName() << " exported from package " << packageName() << "..." << endl; if(f) cout << "Plugin " << pluginName() << " is located in library " << f(packageName(), pluginName()) << endl; else { cout << "Error: Could not find function 'whereIsPluginLocated' in shared object." << endl; exit(-1); } } void handleListPluginsRequest() /*****************************************************************************/ { // std::vector availablePlugins(const string& package_name) typedef std::vector (*ListFunc)(const string&); ListFunc f = getPluginFunction("availablePlugins"); cout << "The following plugins are available in package " << packageName() << ":" << endl; if(f) { std::vector plugins = f(packageName()); for(unsigned int c = 0; c < plugins.size(); c++) cout << plugins.at(c) << endl; } else { cout << "Error: Could not find function 'availablePlugins' in shared object." << endl; exit(-1); } } void handleLoadPluginRequest() /*****************************************************************************/ { // bool loadPlugin(const string& package_name, const string& class_name) typedef bool (*LoadPluginFunc)(const string&, const string&); LoadPluginFunc f = getPluginFunction("loadPlugin"); string plugin_name = getCLIArguments().at(4); cout << "Attempting to find plugin " << plugin_name << "..." << endl; if(f) { if(f(packageName(), plugin_name)) cout << "Opened plugin successfully :)" << endl; else { cout << "Error: Plugin did not open :(" << endl; exit(-1); } } else { cout << "Error: Could not find function 'loadPlugin' in shared object." << endl; exit(-1); } } vector parseToStringVector(std::string newline_delimited_str) /***************************************************************************/ { string next; vector parse_result; for(unsigned int c = 0; c < newline_delimited_str.size(); c++) { char ch = newline_delimited_str.at(c); if(ch == '\n') { parse_result.push_back(next); next = ""; } else next.push_back(ch); } return(parse_result); } void processUserCommand() /*****************************************************************************/ { string verb = commandVerb(); if (verb == "find") handleFindPluginRequest(); else if (verb == "list") handleListPluginsRequest(); else if(verb == "load") handleLoadPluginRequest(); else cout << "Error: Unknown verb for plugin_tool, available verbs are 'load', 'list', and 'find'." << endl; } void setCLIArguments(int argc, char* argv[]) /*****************************************************************************/ { g_cli_arguments = vector(argc); for(int c = 0; c < argc; c++) g_cli_arguments.at(c) = string(argv[c]); } string stripNewlineCharacters(const std::string& s) /*****************************************************************************/ { string stripped; for(unsigned int c = 0; c < s.size(); c++) { if(s.at(c) != '\n') stripped.push_back(s.at(c)); } return stripped; } bool verifyCLIArguments() /*****************************************************************************/ { vector args = getCLIArguments(); if(args.size() < 5) { cout << "Not enough arguments. Usage: plugin_tool "; return false; } for(int c = 0; c < args.size(); c++) cout << "Arg " << c << ": " << args.at(c) << endl; return(true); } pluginlib-1.10.4/test/000077500000000000000000000000001277033441200145445ustar00rootroot00000000000000pluginlib-1.10.4/test/test_base.h000066400000000000000000000004011277033441200166610ustar00rootroot00000000000000#ifndef PLUGINLIB_TEST_BASE_H_ #define PLUGINLIB_TEST_BASE_H_ namespace test_base { class Fubar { public: virtual void initialize(double foo) = 0; virtual double result() = 0; virtual ~Fubar(){} protected: Fubar(){} }; }; #endif pluginlib-1.10.4/test/test_plugins.cpp000066400000000000000000000003651277033441200177740ustar00rootroot00000000000000#include #include "test_base.h" #include "test_plugins.h" PLUGINLIB_DECLARE_CLASS(pluginlib, foo, test_plugins::Foo, test_base::Fubar) PLUGINLIB_DECLARE_CLASS(pluginlib, bar, test_plugins::Bar, test_base::Fubar) pluginlib-1.10.4/test/test_plugins.h000066400000000000000000000011571277033441200174410ustar00rootroot00000000000000#ifndef PLUGINLIB_TEST_PLUGINS_H_ #define PLUGINLIB_TEST_PLUGINS_H_ #include "test_base.h" #include namespace test_plugins { class Bar : public test_base::Fubar { public: Bar(){} void initialize(double foo) { foo_ = foo; } double result() { return 0.5 * foo_ * getBar(); } double getBar() { return sqrt((foo_ * foo_) - ((foo_ / 2) * (foo_ / 2))); } private: double foo_; }; class Foo : public test_base::Fubar { public: Foo(){} void initialize(double foo) { foo_ = foo; } double result() { return foo_ * foo_; } private: double foo_; }; }; #endif pluginlib-1.10.4/test/test_plugins.xml000066400000000000000000000010131277033441200200010ustar00rootroot00000000000000 This is a foo plugin. This is a bar plugin. This is a broken none plugin. pluginlib-1.10.4/test/test_plugins_broken.xml000066400000000000000000000003131277033441200213430ustar00rootroot00000000000000 This is a foo plugin. pluginlib-1.10.4/test/unique_ptr_test.cpp000066400000000000000000000043571277033441200205130ustar00rootroot00000000000000#include #include "test_base.h" #include TEST(PluginlibUniquePtrTest, unknownPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); ASSERT_THROW(test_loader.createUniqueInstance("pluginlib/foobar"), pluginlib::LibraryLoadException); } TEST(PluginlibUniquePtrTest, misspelledPlugin) { pluginlib::ClassLoader bad_test_loader("pluginlib", "test_base::Fuba"); ASSERT_THROW(bad_test_loader.createUniqueInstance("pluginlib/foo"), pluginlib::LibraryLoadException); } TEST(PluginlibTest, brokenPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); ASSERT_THROW(test_loader.createUniqueInstance("pluginlib/none"), pluginlib::PluginlibException); } TEST(PluginlibUniquePtrTest, workingPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); try { pluginlib::UniquePtr foo = test_loader.createUniqueInstance("pluginlib/foo"); foo->initialize(10.0); EXPECT_EQ(foo->result(),100.0); } catch(pluginlib::PluginlibException& ex) { FAIL() << "Throwing exception: " << ex.what(); return; } catch(...) { FAIL() << "Uncaught exception"; } } TEST(PluginlibUniquePtrTest, createUniqueInstanceAndUnloadLibrary) { ROS_INFO( "Making the ClassLoader..." ); pluginlib::ClassLoader pl("pluginlib", "test_base::Fubar"); ROS_INFO( "Instantiating plugin..." ); { pluginlib::UniquePtr inst = pl.createUniqueInstance("pluginlib/foo"); } ROS_INFO( "Checking if plugin is loaded with isClassLoaded..." ); if( pl.isClassLoaded( "pluginlib/foo" ) ) ROS_INFO( "Class is loaded" ); else { FAIL() << "Library containing class should be loaded but isn't."; } ROS_INFO( "Trying to unload class with unloadLibraryForClass..." ); try { pl.unloadLibraryForClass("pluginlib/foo"); } catch(pluginlib::PluginlibException& e) { FAIL() << "Could not unload library when I should be able to."; } ROS_INFO( "Done." ); } // Run all the tests that were declared with TEST() int main(int argc, char **argv){ testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } pluginlib-1.10.4/test/utest.cpp000066400000000000000000000067241277033441200164250ustar00rootroot00000000000000#include #include "test_base.h" #include TEST(PluginlibTest, unknownPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); ASSERT_THROW(test_loader.createInstance("pluginlib/foobar"), pluginlib::LibraryLoadException); } TEST(PluginlibTest, misspelledPlugin) { pluginlib::ClassLoader bad_test_loader("pluginlib", "test_base::Fuba"); ASSERT_THROW(bad_test_loader.createInstance("pluginlib/foo"), pluginlib::LibraryLoadException); } TEST(PluginlibTest, invalidPackage) { ASSERT_THROW(pluginlib::ClassLoader("pluginlib_bad", "test_base::Fubar"), pluginlib::ClassLoaderException); } TEST(PluginlibTest, brokenPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); ASSERT_THROW(test_loader.createInstance("pluginlib/none"), pluginlib::PluginlibException); } TEST(PluginlibTest, workingPlugin) { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar"); try { boost::shared_ptr foo = test_loader.createInstance("pluginlib/foo"); foo->initialize(10.0); EXPECT_EQ(foo->result(),100.0); } catch(pluginlib::PluginlibException& ex) { FAIL() << "Throwing exception: " << ex.what(); return; } catch(...) { FAIL() << "Uncaught exception"; } } TEST(PluginlibTest, createUnmanagedInstanceAndUnloadLibrary) { ROS_INFO( "Making the ClassLoader..." ); pluginlib::ClassLoader pl("pluginlib", "test_base::Fubar"); ROS_INFO( "Instantiating plugin..." ); test_base::Fubar *inst = pl.createUnmanagedInstance("pluginlib/foo"); ROS_INFO( "Deleting plugin..." ); delete inst; ROS_INFO( "Checking if plugin is loaded with isClassLoaded..." ); if( pl.isClassLoaded( "pluginlib/foo" ) ) ROS_INFO( "Class is loaded" ); else { FAIL() << "Library containing class should be loaded but isn't."; } ROS_INFO( "Trying to unload class with unloadLibraryForClass..." ); try { pl.unloadLibraryForClass("pluginlib/foo"); } catch(pluginlib::PluginlibException& e) { FAIL() << "Could not unload library when I should be able to."; } ROS_INFO( "Done." ); } TEST(PluginlibTest, createManagedInstanceAndUnloadLibrary) { ROS_INFO( "Making the ClassLoader..." ); pluginlib::ClassLoader pl("pluginlib", "test_base::Fubar"); ROS_INFO( "Instantiating plugin..." ); { boost::shared_ptr inst = pl.createInstance("pluginlib/foo"); } ROS_INFO( "Checking if plugin is loaded with isClassLoaded..." ); if( pl.isClassLoaded( "pluginlib/foo" ) ) ROS_INFO( "Class is loaded" ); else { FAIL() << "Library containing class should be loaded but isn't."; } ROS_INFO( "Trying to unload class with unloadLibraryForClass..." ); try { pl.unloadLibraryForClass("pluginlib/foo"); } catch(pluginlib::PluginlibException& e) { FAIL() << "Could not unload library when I should be able to."; } ROS_INFO( "Done." ); } TEST(PluginlibTest, brokenXML) { try { pluginlib::ClassLoader test_loader("pluginlib", "test_base::Fubar", "plugin_test"); } catch(pluginlib::ClassLoaderException& ex) { SUCCEED(); return; } ADD_FAILURE() << "Didn't throw exception as expected"; } // Run all the tests that were declared with TEST() int main(int argc, char **argv){ testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }