From c4a6034d69ba326f91d8956c4df58e9865ee2c95 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 3 Jan 2018 17:09:44 +0100
Subject: [PATCH] introduce load cli command to load library

---
 alib2cli/makefile.conf                |  2 +-
 alib2cli/src/command/LoadCommand.h    | 26 ++++++++++
 alib2cli/src/common/LibraryLoader.cpp | 23 +++++++++
 alib2cli/src/common/LibraryLoader.h   | 72 +++++++++++++++++++++++++++
 alib2cli/src/parser/Parser.cpp        |  7 +++
 alib2cli/src/parser/Parser.h          |  2 +-
 6 files changed, 130 insertions(+), 2 deletions(-)
 create mode 100644 alib2cli/src/command/LoadCommand.h
 create mode 100644 alib2cli/src/common/LibraryLoader.cpp
 create mode 100644 alib2cli/src/common/LibraryLoader.h

diff --git a/alib2cli/makefile.conf b/alib2cli/makefile.conf
index 5f6fbb956f..f6fc9bd373 100644
--- a/alib2cli/makefile.conf
+++ b/alib2cli/makefile.conf
@@ -1,5 +1,5 @@
 LIBRARY:=alib2cli
 TESTBIN:=alib2test
 LINK_PATHS=../alib2xml/ ../alib2common/ ../alib2abstraction/ ../alib2measure/ ../alib2std/
-LINK_LIBRARIES=alib2xml alib2common alib2abstraction alib2measure alib2std xml2
+LINK_LIBRARIES=alib2xml alib2common alib2abstraction alib2measure alib2std xml2 stdc++fs
 INCLUDE_PATHS=\$$(SOURCES_BASE_DIR)/../../alib2xml/src/ \$$(SOURCES_BASE_DIR)/../../alib2common/src/ \$$(SOURCES_BASE_DIR)/../../alib2abstraction/src/ \$$(SOURCES_BASE_DIR)/../../alib2measure/src/ \$$(SOURCES_BASE_DIR)/../../alib2std/src/ /usr/include/libxml2/
diff --git a/alib2cli/src/command/LoadCommand.h b/alib2cli/src/command/LoadCommand.h
new file mode 100644
index 0000000000..db42419791
--- /dev/null
+++ b/alib2cli/src/command/LoadCommand.h
@@ -0,0 +1,26 @@
+#ifndef _CLI_LOAD_COMMAND_H_
+#define _CLI_LOAD_COMMAND_H_
+
+#include <command/Command.h>
+#include <environment/Environment.h>
+
+#include <common/LibraryLoader.h>
+
+namespace cli {
+
+class LoadCommand : public Command {
+	std::string m_libraryName;
+
+public:
+	LoadCommand ( std::string libraryName ) : m_libraryName ( std::move ( libraryName ) ) {
+	}
+
+	virtual Command::Result run ( Environment & ) const override {
+		cli::LibraryLoader::load ( m_libraryName );
+		return Command::Result::OK;
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_LOAD_COMMAND_H_ */
diff --git a/alib2cli/src/common/LibraryLoader.cpp b/alib2cli/src/common/LibraryLoader.cpp
new file mode 100644
index 0000000000..0b0ba38f81
--- /dev/null
+++ b/alib2cli/src/common/LibraryLoader.cpp
@@ -0,0 +1,23 @@
+#include "LibraryLoader.h"
+
+namespace cli {
+
+std::list < LibraryLoader::Library >::iterator LibraryLoader::find ( const std::string name ) {
+	for ( std::list < LibraryLoader::Library >::iterator iter = libraries.begin ( ); iter != libraries.end ( ); ++ iter ) {
+		if ( iter->path ( ) == name )
+			return iter;
+	}
+
+	return libraries.end ( );
+}
+
+std::list < LibraryLoader::Library > LibraryLoader::libraries;
+
+void LibraryLoader::load ( const std::string & name ) {
+	std::list < LibraryLoader::Library >::iterator iter = find ( name );
+	if ( iter == libraries.end ( ) )
+		iter = libraries.emplace ( libraries.end ( ), std::move ( name ) );
+	iter->load ( );
+}
+
+} /* namespace cli */
diff --git a/alib2cli/src/common/LibraryLoader.h b/alib2cli/src/common/LibraryLoader.h
new file mode 100644
index 0000000000..fbcfded963
--- /dev/null
+++ b/alib2cli/src/common/LibraryLoader.h
@@ -0,0 +1,72 @@
+#ifndef _CLI_LIBRARY_LOADER_H_
+#define _CLI_LIBRARY_LOADER_H_
+
+#include <command/Command.h>
+#include <environment/Environment.h>
+
+#include <dlfcn.h>
+
+#include <experimental/filesystem>
+#include <alib/list>
+
+#include <exception/CommonException.h>
+
+namespace cli {
+
+class LibraryLoader {
+	class Library {
+		std::string m_path;
+		void * m_handle;
+
+	public:
+		Library ( const std::string & path ) : m_path ( path ), m_handle ( NULL ) {
+		}
+
+		Library ( const Library & ) = delete;
+
+		Library ( Library && other ) : m_path ( std::move ( other.m_path ) ), m_handle ( other.m_handle ) {
+			other.m_handle = NULL;
+		}
+
+		Library & operator = ( const Library & ) = delete;
+		Library & operator = ( Library && other ) = delete;
+
+		~Library ( ) {
+			unload ( );
+		}
+
+		void load ( ) {
+			if ( ! loaded ( ) )
+				m_handle = dlopen ( m_path.c_str ( ), RTLD_NOW );
+			if ( ! loaded ( ) )
+				throw exception::CommonException ( std::string ( dlerror ( ) ) );
+		}
+
+		void unload ( ) {
+			if ( loaded ( ) ) {
+				dlclose ( m_handle );
+				m_handle = NULL;
+			}
+		}
+
+		const std::string & path ( ) const {
+			return m_path;
+		}
+
+		bool loaded ( ) const {
+			return m_handle != NULL;
+		}
+
+	};
+
+	static std::list < Library >::iterator find ( const std::string name );
+
+	static std::list < Library > libraries;
+
+public:
+	static void load ( const std::string & name );
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_LIBRARY_LOADER_H_ */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 10cbcd4866..3d5fec731b 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -30,6 +30,7 @@
 #include <command/DataTypesIntrospectionCommand.h>
 #include <command/CastsIntrospectionCommand.h>
 #include <command/SetCommand.h>
+#include <command/LoadCommand.h>
 
 #include <primitive/Integer.h>
 #include <primitive/String.h>
@@ -358,6 +359,12 @@ std::unique_ptr < Command > Parser::parse ( ) {
 		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING );
 		match ( cli::Lexer::TokenType::END );
 		return std::make_unique < SetCommand > ( std::move ( param ), std::move ( value ) );
+	} else if ( check_nonreserved_kw ( "load" ) ) {
+		match_nonreserved_kw ( "load" );
+		std::string libraryName = getTokenValue ( );
+		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING );
+		match ( cli::Lexer::TokenType::END );
+		return std::make_unique < LoadCommand > ( std::move ( libraryName ) );
 	} else {
 		throw exception::CommonException ( "Mismatched set while expanding parse rule." );
 	}
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index 64d3268898..1db21e5e5c 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -95,7 +95,7 @@ public:
 	std::unique_ptr < Param > in_redirect_param ( );
 
 	std::unique_ptr < Param > param ( );
-	
+
 	std::unique_ptr < Arg > template_param ( );
 
 	std::unique_ptr < Param > move_param ( );
-- 
GitLab