diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2009-08-13 17:22:20 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2009-08-13 17:22:20 +0000 |
commit | d2c1ccadb685877479d7a2091e9aca5a5b333652 (patch) | |
tree | 0118dca796b67ccfbcb8ebe51be7e6b2298580cc /modules/CIAO/DAnCE/RepositoryManager | |
parent | 1bf8bb0ad2f1244f827b9cf7426946f0a14050db (diff) | |
download | ATCD-d2c1ccadb685877479d7a2091e9aca5a5b333652.tar.gz |
branching/tagging
Diffstat (limited to 'modules/CIAO/DAnCE/RepositoryManager')
24 files changed, 4881 insertions, 0 deletions
diff --git a/modules/CIAO/DAnCE/RepositoryManager/DAnCE_RepositoryManager_Module_Export.h b/modules/CIAO/DAnCE/RepositoryManager/DAnCE_RepositoryManager_Module_Export.h new file mode 100644 index 00000000000..b94621bd39b --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/DAnCE_RepositoryManager_Module_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl DAnCE_RepositoryManager_Module +// ------------------------------ +#ifndef DANCE_REPOSITORYMANAGER_MODULE_EXPORT_H +#define DANCE_REPOSITORYMANAGER_MODULE_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL) +# define DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL */ + +#if !defined (DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL) +# define DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL 1 +#endif /* ! DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL */ + +#if defined (DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL) && (DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL == 1) +# if defined (DANCE_REPOSITORYMANAGER_MODULE_BUILD_DLL) +# define DAnCE_RepositoryManager_Module_Export ACE_Proper_Export_Flag +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* DANCE_REPOSITORYMANAGER_MODULE_BUILD_DLL */ +# define DAnCE_RepositoryManager_Module_Export ACE_Proper_Import_Flag +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* DANCE_REPOSITORYMANAGER_MODULE_BUILD_DLL */ +#else /* DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL == 1 */ +# define DAnCE_RepositoryManager_Module_Export +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARATION(T) +# define DANCE_REPOSITORYMANAGER_MODULE_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* DANCE_REPOSITORYMANAGER_MODULE_HAS_DLL == 1 */ + +// Set DANCE_REPOSITORYMANAGER_MODULE_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (DANCE_REPOSITORYMANAGER_MODULE_NTRACE) +# if (ACE_NTRACE == 1) +# define DANCE_REPOSITORYMANAGER_MODULE_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define DANCE_REPOSITORYMANAGER_MODULE_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !DANCE_REPOSITORYMANAGER_MODULE_NTRACE */ + +#if (DANCE_REPOSITORYMANAGER_MODULE_NTRACE == 1) +# define DANCE_REPOSITORYMANAGER_MODULE_TRACE(X) +#else /* (DANCE_REPOSITORYMANAGER_MODULE_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define DANCE_REPOSITORYMANAGER_MODULE_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (DANCE_REPOSITORYMANAGER_MODULE_NTRACE == 1) */ + +#endif /* DANCE_REPOSITORYMANAGER_MODULE_EXPORT_H */ + +// End of auto generated file. diff --git a/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.cpp b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.cpp new file mode 100644 index 00000000000..1acd3d8c4b9 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.cpp @@ -0,0 +1,256 @@ +// $Id$ + +#include "ace/Log_Msg.h" +#include "DAnCE/Deployment/Deployment_DataC.h" +#include "PC_Updater.h" +#include "PC_Updater_T.h" +#include "ace/Containers_T.h" //for ACE_Double_Linked_List + +namespace +{ + const size_t TEMP_LEN = 1024; +} + +using namespace PC_Updater_T; + + + //PATH of glory/gory to update the locations of the IADs + // + //PackageConfiguration something; + //ComponentPackageDescriptions basePackage; + //PackagedComponentImplementations implementation; + //ComponentImplementationDescription referencedImplementation; + // + //MONOLITHIC Component: + //MonolithicImplementationDescriptions monolithicImpl; + //NamedImplementationArtifacts primaryArtifact; + //ImplementationArtifactDescription referencedArtifact; + //::CORBA::StringSeq location; + // + //ASSEMBLY-BASED Component + //ComponentAssemblyDescriptions assemblyImpl; + //SubcomponentInstantiationDescriptions instance; + //ComponentPackageDescriptions package; + //... + + + /* + * PC_Updater Constructors + */ + +PC_Updater::PC_Updater (const char* server_path, const char* package) +: server_path_ (server_path), + file_list_ (), + package_ (package), + success_ (true) +{ +} + + +PC_Updater::PC_Updater (ACE_CString& server_path, ACE_CString& package) +: server_path_ (server_path), + file_list_ (), + package_ (package), + success_ (true) +{ +} + + /* + * PC_Updater - Destructor + */ + +PC_Updater::~PC_Updater () +{ + this->clear_list (); +} + + +void PC_Updater::clear_list () +{ + while (!this->file_list_.is_empty ()) + { + ZIP_File_Info* inf = this->file_list_.delete_head (); + + //deallocate the head of the filename list + delete inf; + } +} + + + /* + * PC_Updater - Object update methods + */ + + + // PackageConfiguration + + bool PC_Updater::update (::Deployment::PackageConfiguration &pc) + { + //get the list of files in the package and figure out the names of all necessary files + if (!ZIP_Wrapper::file_list_info (const_cast <char*> (this->package_.c_str ()), this->file_list_)) + return false; + + update_sequence (pc.basePackage, this); + + return this->success_; + } + + + // ComponentInterfaceDescription + + void PC_Updater::update (::Deployment::ComponentInterfaceDescription &) + { + } + + // Requirement + + void PC_Updater::update (::Deployment::Requirement &) + { + } + + + // ComponentExternalPortEndpoint + + void PC_Updater::update (::Deployment::ComponentExternalPortEndpoint &) + { + } + + + + // ImplementationDependency + + void PC_Updater::update (Deployment::ImplementationDependency &) + { + } + + // ComponentPackageReference + + void PC_Updater::update (::Deployment::ComponentPackageReference &) + { + } + + // SubcomponentInstantiationDescription + + void PC_Updater::update (::Deployment::SubcomponentInstantiationDescription &sid) + { + update_sequence (sid.basePackage, this); + } + + // SubcomponentPortEndpoint + + void PC_Updater::update (::Deployment::SubcomponentPortEndpoint& ) + { + } + + // AssemblyConnectionDescription + + void PC_Updater::update (::Deployment::AssemblyConnectionDescription &) + { + } + + + // AssemblyPropertyMapping + + void + PC_Updater::update (::Deployment::AssemblyPropertyMapping &) + { + } + + // ComponentAssemblyDescription + + void PC_Updater::update (::Deployment::ComponentAssemblyDescription& cad) + { + update_sequence (cad.instance, this); + } + + // ImplementationArtifactDescription + + void PC_Updater::update (::Deployment::ImplementationArtifactDescription &iad) + { + const char* location = CORBA::string_dup (iad.location[0]); + + //create an iterator + ACE_Double_Linked_List_Iterator<ZIP_File_Info> iter (this->file_list_); + + //find the correct path and return + while (!iter.done ()) + { + const char* full_path = iter.next ()->name_.c_str (); + //weird. Need to call next to get current ?!?! + + //is it an implementation artifact? + const char* name = ACE_OS::strstr (full_path, "implementations/"); + if (name) + { + //now check if the name matches + name = ACE_OS::strstr (full_path, iad.location[0]); + + if (name) + { + ACE_CString loc (this->server_path_); + loc += "/implementations/"; + loc += location; + + iad.location[0] = CORBA::string_dup (loc.c_str ()); + + //cout << "Location after update: " << iad.location[0] << endl << endl; + return; + } + } + iter++; + } + + ACE_ERROR ((LM_ERROR, + "[PC_Updater::update] Unable to update: %s!\n", + location)); + + this->success_ = false; + } + + // NamedImplementationArtifact + + void PC_Updater::update (::Deployment::NamedImplementationArtifact &nia) + { + update (nia.referencedArtifact); + } + + // ImplementationRequirement + void PC_Updater::update (::Deployment::ImplementationRequirement &) + { + } + + // MonolithicImplementationDescription + void PC_Updater::update (::Deployment::MonolithicImplementationDescription &mid) + { + update_sequence (mid.primaryArtifact, this); + } + + // Capability + void PC_Updater::update (::Deployment::Capability &) + { + } + + // ComponentImplementationDescription + void PC_Updater::update (::Deployment::ComponentImplementationDescription &cid) + { + update_sequence (cid.assemblyImpl, this); + update_sequence (cid.monolithicImpl, this); + } + + // PackagedComponentImplementation + void PC_Updater::update (::Deployment::PackagedComponentImplementation &pci) + { + PC_Updater::update (pci.referencedImplementation); + } + + // ComponentPackageDescription + void PC_Updater::update (::Deployment::ComponentPackageDescription &comppkgdesc) + { + update_sequence (comppkgdesc.implementation, this); + } + + + // Property + void PC_Updater::update (Deployment::Property& ) + { + } diff --git a/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.h b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.h new file mode 100644 index 00000000000..fd5b41db555 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater.h @@ -0,0 +1,114 @@ + +/* -*- C++ -*- */ + +//======================================================================== +/** + * file PC_Updater.h + * + * $Id$ + * + * This class is used to update the location field of the implementation + * artifacts in the PackageConfiguration, so that they point to the + * physical libraries on the collocated HTTP server + * + * author Stoyan Paunov <spaunov@isis.vanderbilt.edu> + */ +//======================================================================== + +#ifndef PC_UPDATER_H +#define PC_UPDATER_H +#include /**/ "ace/pre.h" + +#include "DAnCE/Deployment/DeploymentC.h" +#include "DAnCE/Deployment/Deployment_Packaging_DataC.h" +#include "ace/SString.h" //for the ACE_CString + +#include "ZIP_Wrapper.h" //Wrapper around zzip +#include "ace/Containers_T.h" //for ACE_Double_Linked_List +#include "ace/Malloc_Allocator.h" //for ACE_New_Allocator needed by the doubly link list + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class PC_Updater + * + * This class defines a set of overloaded methods used to update + * the contents of a PackageConfiguration. More specifically the class + * goes through the PackageConfiguration and updates the locations of the + * artifacts, wrt to their location on the HTTP server. + */ +class PC_Updater +{ +public: + + /// Constructors + + PC_Updater (const char* server_path, const char* package); + PC_Updater (ACE_CString& server_path, ACE_CString& package); + + ~PC_Updater (); + + /// A whole slew of overloaded routines for different IDL + /// data types part of the PackageConfiguration. + + bool update (::Deployment::PackageConfiguration &pc); + + void update (::Deployment::Property &property); + + void update (::Deployment::AssemblyConnectionDescription &acd); + + void update (::Deployment::AssemblyPropertyMapping &apm); + + void update (::Deployment::ComponentPackageDescription &comppkgdesc); + + void update (::Deployment::MonolithicImplementationDescription &mid); + + void update (::Deployment::PackagedComponentImplementation &pci); + + void update (::Deployment::SubcomponentPortEndpoint &spe); + + void update (::Deployment::Requirement &requirement); + + void update (::Deployment::ComponentExternalPortEndpoint &cepe); + + void update (::Deployment::ComponentPackageReference &cpr); + + void update (::Deployment::ComponentImplementationDescription &cid); + + void update (::Deployment::SubcomponentInstantiationDescription &sid); + + void update (::Deployment::NamedImplementationArtifact &named_implementation); + + void update (::Deployment::ComponentInterfaceDescription &cid); + + void update (::Deployment::Capability &capability); + + void update (::Deployment::ImplementationArtifactDescription &iad); + + void update (::Deployment::ImplementationRequirement &ir); + + void update (::Deployment::ImplementationDependency &id); + + void update (::Deployment::ComponentAssemblyDescription& cad); + +protected: + + void clear_list (); + +private: + + ACE_CString server_path_; + + /// create a doubly link list + //ACE_New_Allocator allocator_; + ACE_Double_Linked_List<ZIP_File_Info> file_list_; + + ACE_CString package_; + bool success_; +}; + +#include /**/ "ace/post.h" + +#endif /* PC_UPDATER_H */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.cpp b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.cpp new file mode 100644 index 00000000000..a5f5ec5fb2e --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.cpp @@ -0,0 +1,20 @@ +// $Id$ +#ifndef PC_UPDATER_T_C +#define PC_UPDATER_T_C +#include "PC_Updater.h" +#include "PC_Updater_T.h" + +namespace PC_Updater_T +{ + /// Dumps a sequence + template <typename SEQUENCE> + void update_sequence (SEQUENCE &seq, PC_Updater* updater) + { + CORBA::ULong const size = seq.length (); + + for (CORBA::ULong i = 0; i < size; ++i) + updater->update (seq[i]); + } +} + +#endif /* PC_Updater_C */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.h b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.h new file mode 100644 index 00000000000..0696c685e2b --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/PC_Updater_T.h @@ -0,0 +1,40 @@ + +/* -*- C++ -*- */ + +//================================================================== +/** + * file PC_Updater_T.h + * + * $Id$ + * + * author Stoyan Paunov <spaunov@isis.vanderbilt.edu> + */ +//===================================================================== + +#ifndef CIAO_CONFIG_HANDLERS_PC_UPDATER_T_H +#define CIAO_CONFIG_HANDLERS_PC_UPDATER_T_H +#include /**/ "ace/pre.h" + +#include "ace/config-lite.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace PC_Updater_T +{ + template <typename SEQUENCE> + static void update_sequence (SEQUENCE &seq); +} + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "PC_Updater_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("PC_Updater_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + + +#include /**/ "ace/post.h" +#endif /*CIAO_CONFIG_HANDLERS_PC_Updater_T_H*/ diff --git a/modules/CIAO/DAnCE/RepositoryManager/README b/modules/CIAO/DAnCE/RepositoryManager/README new file mode 100644 index 00000000000..322b00098ac --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/README @@ -0,0 +1,46 @@ +This is the README file for the Repository Manager (RM). + +Building RM: +In order to be able to compile the RM you need to have ZLIB lib because the RM +uses it to read the contents of CCM packages. In order to compile the RM +successfully you will need to do the following: +1.Download the binary version of ZLIB or build it yourself +3.Create an "include" and a "lib" subdirectory. Then copy the libraries files into + the "lib" subdirectory and copy zlib.h into the "include" subdirectory. +4.Set $ZLIB_ROOT to point to the directories where you placed the libraries and + the include files. +5.Turn on zzip and zlib in default.features for MPC. +6.MPC will handle the rest. + +If you want to get the component package through http server: +1.Be sure to set JAWS_DOCUMENT_ROOT to the installation path of the RepoMan, i.e., $CIAO_ROOT/DAnCE/RepositoryManager. +2.Start JAWS: $ACE_ROOT/apps/JAWS/server/main + +Start RM: +1.Using ior file: + RepositoryManagerDaemon -o +2.Using Naming Service: + RepositoryManagerDaemon -v [NameofRM] + +Using RMadmin: +1.Install component package: (use BasicSP for example) + Be sure you have BasicSP.cpk in the $CIAO_ROOT/DAnCE/RepositoryManager/packages + > RMadmin -o -n BasicSP -i -l packages/BasicSP.cpk + or + > RMadmin -o -n BasicSP -i -l http://127.0.0.1:5432/packages/BasicSP.cpk (If the JAWS is started) + This will create the BasicSP directory, BasicSP.cpk file and BasicSP.epc file in the + $CIAO_ROOT/DAnCE/RepositoryManager/RepositoryManager/ +2.Delete component package: (use BasicSP for example) + > RMadmin -o -n BasicSP -d +3.Find component package by its name: (use BasicSP for example) + > RMadmin -o -n BasicSP -f +4.Stop RM: + > RMadmin -o -s + This will create the RM_record file in the $CIAO_ROOT/DAnCE/RepositoryManager/RepositoryManager/ which record the + names and UUIDs of the installed component packages. + + + + + + diff --git a/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.cpp b/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.cpp new file mode 100644 index 00000000000..cd4b92669d0 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.cpp @@ -0,0 +1,265 @@ +// $Id$ + +#include "RM_Helper.h" +#include "ace/Auto_Ptr.h" //for Auto_Ptr +#include "ace/OS_NS_fcntl.h" //for open +#include "ace/OS_NS_unistd.h" //for close +#include "ace/OS_NS_sys_stat.h" //for filesize and mkdir +#include "ace/OS_NS_string.h" + + +void +RM_Helper::pc_to_cdr (const Deployment::PackageConfiguration& pc, TAO_OutputCDR& cdr) +{ + cdr << pc; +} + + +void +RM_Helper::cdr_to_pc (Deployment::PackageConfiguration& pc, TAO_InputCDR& cdr) +{ + cdr >> pc; +} + + +bool +RM_Helper::externalize (const Deployment::PackageConfiguration& pc, const char* path) +{ + size_t bufsiz = 0; + TAO_OutputCDR out (bufsiz); + + RM_Helper::pc_to_cdr (pc, out); + + const ACE_Message_Block* mb = out.begin (); + + return write_pc_to_disk (path, *(const_cast<ACE_Message_Block*> (mb))); +} + + +bool +RM_Helper::reincarnate (Deployment::PackageConfiguration& pc, const char* path) +{ + size_t length = 0; + ACE_Auto_Ptr<ACE_Message_Block> mb (read_pc_from_disk (path, length)); + + if (!mb.get ()) + return false; + + TAO_InputCDR in (mb.get ()); + + RM_Helper::cdr_to_pc (pc, in); + + return true; +} + + +/// This function attempts to copy the file from a specified location +/// to another specified location on the hard disk. +bool +RM_Helper::copy_from_disk_to_disk (const char* from_path, const char* to_path) +{ + if (ACE_OS::strcmp (from_path, to_path) == 0) + return true; + + // Open the files + ACE_HANDLE from_handle = ACE_OS::open (from_path, O_RDONLY); + if (from_handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::copy_from_disk_to_disk] file open error")), + 0); + + ACE_stat file_info; + ACE_OS::fstat (from_handle, &file_info); + ACE_UINT64 file_length = file_info.st_size; + + ACE_HANDLE to_handle = ACE_OS::open (to_path, O_CREAT | O_TRUNC | O_WRONLY); + if (to_handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::copy_from_disk_to_disk] file creation error")), + 0); + + + // Read the contents of the file into the buffer and write the data to another file + ACE_Message_Block *mb = 0; + size_t length; + size_t number = 0; + bool last = false; + + while (true) + { + if ((file_length - BUFSIZ*number) > BUFSIZ) + length = BUFSIZ; + else + { + length = static_cast<size_t> (file_length - BUFSIZ*number); + last = true; + } + + mb = new ACE_Message_Block (length); + + if (ACE_OS::read_n (from_handle, mb->wr_ptr (), length) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::copy_from_disk_to_disk] file read error")), + 0); + + ++number; + + mb->length (length); + + for (ACE_Message_Block *curr = mb; curr != 0; curr = curr->cont ()) + if (ACE_OS::write_n (to_handle, curr->rd_ptr (), curr->length ()) == -1) + { + mb->release (); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::copy_from_disk_to_disk] file write error")), + 0); + } + + mb->release (); + + if (last) + break; + } + + // Close the files + ACE_OS::close (from_handle); + ACE_OS::close (to_handle); + + return true; +} + + +/// This function attempts to write a sequence of bytes from an +/// ACE_Message_Block to a specified location. A 0 is returned +/// in the case of an error and a 1 upon success +bool RM_Helper::write_to_disk ( + const char* full_path, + ACE_Message_Block& mb, + bool replace + ) +{ + ACE_stat stat; + + if (ACE_OS::stat(full_path, &stat) != -1 && !replace) + return false; + + // Open a file handle to the local filesystem + ACE_HANDLE handle = ACE_OS::open (full_path, O_CREAT | O_TRUNC | O_WRONLY); + if (handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::write_to_disk] file creation error")), + false); + + // Write the data to the file + for (ACE_Message_Block * curr = &mb; curr != 0; curr = curr->cont ()) + if (ACE_OS::write_n (handle, curr->rd_ptr(), curr->length()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("write error")), + false); + + // Close the file handle + ACE_OS::close (handle); + + return true; +} + + +/// This function attempts to write a sequence of bytes from an +/// ACE_Message_Block to a specified location. A 0 is returned +/// in the case of an error and a 1 upon success +/// +/// @note This function write the contents in a way that preserves the +/// structure of the ACE_Message_Block. It is relevant for +/// PackageConfigurations ONLY +bool RM_Helper::write_pc_to_disk ( + const char* full_path, + ACE_Message_Block& mb, + bool replace + ) +{ + ACE_stat stat; + + if (ACE_OS::stat(full_path, &stat) != -1 && !replace) + return false; + + // Open a file handle to the local filesystem + ACE_HANDLE const handle = ACE_OS::open (full_path, O_CREAT | O_TRUNC | O_WRONLY); + if (handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::write_to_disk] file creation error")), + false); + + // write the data to the file + for (ACE_Message_Block * curr = &mb; curr != 0; curr = curr->cont ()) + if (ACE_OS::write_n (handle, curr->rd_ptr(), curr->length()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("write error")), + 0); + + // Close the file handle + ACE_OS::close (handle); + + return true; +} + + +/// Function to read the contents of a file from disk into an ACE_Message_Block +/// returns a pointer to an ACE_Message_Block and updates the lenght on success +/// 0 on failure +ACE_Message_Block* +RM_Helper::read_pc_from_disk ( + const char* full_path, + size_t &length + ) +{ + length = 0; + + // Open the file + ACE_HANDLE const handle = ACE_OS::open (full_path, O_RDONLY); + if (handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::read_mb_from_disk] file open error")), + 0); + + ACE_stat file_info; + ACE_OS::fstat (handle, &file_info); + + // Get and check the length of the file + length = static_cast<size_t> (file_info.st_size); + + ACE_INT64 check = length; + if (check != file_info.st_size) + { + length = 0; + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::read_mb_from_disk] file length error")), + 0); + } + + // Read the contents of the file into the buffer + ACE_Message_Block* mb = 0; + ACE_NEW_RETURN (mb, ACE_Message_Block (length + 1), 0); + + if (ACE_OS::read_n (handle, mb->wr_ptr (), length) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[RM::read_mb_from_disk] file read error")), + 0); + + mb->length (length); + + // Close the file handle + ACE_OS::close (handle); + + return mb; +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.h b/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.h new file mode 100644 index 00000000000..47e46d35a6f --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RM_Helper.h @@ -0,0 +1,81 @@ + +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file RM_Helper.h + * + * $Id$ + * + * This class aggregates a number of helper functions used by the + * CIAO RepositoryManager + * + * + * @author Stoyan Paunov + */ +//============================================================================= + +#ifndef RM_HELPER_H_ +#define RM_HELPER_H_ + + +#include "DAnCE/Deployment/Deployment_Packaging_DataC.h" +#include "tao/CDR.h" +#include "ace/Message_Block.h" + + +class RM_Helper +{ +public: + + static void pc_to_cdr (const Deployment::PackageConfiguration& pc, TAO_OutputCDR& cdr); + + static void cdr_to_pc (Deployment::PackageConfiguration& pc, TAO_InputCDR& cdr); + + static bool externalize (const Deployment::PackageConfiguration& pc, const char* path); + + static bool reincarnate (Deployment::PackageConfiguration& pc, const char* path); + + /** + * Function that copies the file from a specified location to another + * specified location on the hard disk. + * @retval true on success + * @retval false on error + */ + static bool copy_from_disk_to_disk (const char* from_path, const char* to_path); + + /** + * Function that writes out a file to a specified location on the hard disk + * @retval true on success + * @retval false on already exists and replace == false + * @retval false on error + */ + static bool write_to_disk (const char* full_path, + ACE_Message_Block& mb, + bool replace = true + ); + + /** + * Function that writes out a file to a specified location on the hard disk + * @retval true on success + * @retval false on already exists and replace == false + * @retval 0 on error + * @note This function is relevant for PackageConfigurations ONLY + */ + static bool write_pc_to_disk (const char* full_path, + ACE_Message_Block& mb, + bool replace = true); + + /** + * Function to read the contents of a file from disk into an + * ACE_Message_Block returns a pointer to an ACE_Message_Block and updates + * the lenght on success + * @retval 0 on failure + */ + + static ACE_Message_Block* read_pc_from_disk (const char* full_path, + size_t &length); + +}; + +#endif diff --git a/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.cpp b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.cpp new file mode 100644 index 00000000000..3d8f07fa153 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.cpp @@ -0,0 +1,281 @@ + +/* -*- C++ -*- */ + +//====================================================================== +/** + * @file RepositoryManager.cpp + * + * $Id$ + * + * Description: + * Main driver program for the CIAO RepositoryManager + * Please run as follows: + * RepositoryManagerDaemon [int:nthreads] + * + * @author Stoyan Paunov + */ +//====================================================================== + +#include "RepositoryManager_Impl.h" +#include "ace/OS_NS_stdio.h" +#include "ace/streams.h" +#include "ace/Auto_Ptr.h" +#include "ace/Task.h" +#include "ace/Get_Opt.h" +#include "ace/SString.h" + +#include "orbsvcs/CosNamingC.h" + +namespace CIAO +{ + namespace RepositoryManager + { + /// Name of the file holding the IOR of the RM + const char * RMior = "RepositoryManagerDaemon.ior"; + + // Name of RepoMan + const char * repoman_name_ = "RepositoryManager"; + + //Name service of the RM + const char * RMname_service = "RepositoryManager"; + + /// Default number of worker threads to run in the multi-threaded RM + static unsigned int nthreads = 3; + static ACE_CString HTTPserver = "127.0.0.1:5432"; + + static bool register_with_ns_ = false; + static bool write_to_ior_ = true; + } +} + +// Forward declaration +bool parse_args (int argc, ACE_TCHAR *argv[]); + +/** + * @class Worker + * + * Class that implements the service routine of the worker threads + * of the repository manager + */ +class Worker : public ACE_Task_Base +{ +public: + /// ctor + Worker (CORBA::ORB_ptr orb); + + /// The thread entry point. + virtual int svc (void); + +private: + /// The orb + CORBA::ORB_var orb_; +}; + +bool +write_ior_file (CORBA::ORB_ptr orb, + CIAO::RepositoryManagerDaemon_ptr obj) +{ + CORBA::String_var ior = + orb->object_to_string (obj); + + FILE* RMior_file = + ACE_OS::fopen (CIAO::RepositoryManager::RMior, "w"); + + if (RMior_file) + { + ACE_OS::fprintf (RMior_file, + "%s", + ior.in ()); + ACE_OS::fclose (RMior_file); + } + else + { + return false; + } + + return true; +} + +bool +register_with_ns (CORBA::ORB_ptr orb, + CIAO::RepositoryManagerDaemon_ptr obj) +{ + if (ACE_OS::strlen (CIAO::RepositoryManager::repoman_name_) > 0) + { + CIAO::RepositoryManager::RMname_service = + CIAO::RepositoryManager::repoman_name_; + } + + // Naming Service related operations + CORBA::Object_var naming_context_object = + orb->resolve_initial_references ("NameService"); + + CosNaming::NamingContext_var naming_context = + CosNaming::NamingContext::_narrow (naming_context_object.in ()); + + // Initialize the Naming Sequence + CosNaming::Name name (1); + name.length (1); + + // String dup required for MSVC6 + name[0].id = CORBA::string_dup (CIAO::RepositoryManager::RMname_service); + + // Register the servant with the Naming Service + naming_context->rebind (name, obj); + + return true; +} + +///Main function + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + try + { + //init the ORB + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); + + if (!parse_args (argc, argv)) + return -1; + + // Get the root POA object + CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA"); + + // Downcast to POA type + PortableServer::POA_var root_poa = PortableServer::POA::_narrow (obj.in ()); + + //activate the POA manager + PortableServer::POAManager_var mgr = root_poa->the_POAManager (); + mgr->activate (); + + // Create a servant + CIAO_RepositoryManagerDaemon_i* repo = 0; + ACE_NEW_RETURN (repo, + CIAO_RepositoryManagerDaemon_i ( + orb.in (), + CIAO::RepositoryManager::HTTPserver.c_str (), + CIAO::RepositoryManager::repoman_name_), + 1); + + //transfer ownership to the POA + PortableServer::ServantBase_var owner_transfer(repo); + + //register and implicitly activate servant + CIAO::RepositoryManagerDaemon_var RepositoryManagerDaemon = repo->_this (); + + bool retval = false; + + if (CIAO::RepositoryManager::write_to_ior_) + { + retval = + write_ior_file (orb.in (), + RepositoryManagerDaemon.in ()); + } + else if (CIAO::RepositoryManager::register_with_ns_) + { + retval = + register_with_ns (orb.in (), + RepositoryManagerDaemon.in ()); + } + + if (!retval) + return -1; + + + Worker worker (orb.in ()); + if (worker.activate (THR_NEW_LWP | THR_JOINABLE, + CIAO::RepositoryManager::nthreads) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot activate worker threads\n"), + 1); + + worker.thr_mgr ()->wait (); + + ACE_DEBUG ((LM_DEBUG, "event loop finished\n")); + + // done + return 0; + + // todo shutdown orb + } + catch (CORBA::Exception &ex) { + cerr << "CORBA Exception: " << ex << endl; + + return 1; + } + + + return 0; +} + + +// **************************************************************** + +///Code to parse the arguments + + bool + parse_args (int argc, ACE_TCHAR *argv[]) + { + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("ov:s:n:")); + int c; + while ((c = get_opts ()) != -1) + switch (c) + { + case 'o': + CIAO::RepositoryManager::write_to_ior_ = true; + CIAO::RepositoryManager::register_with_ns_ = false; + break; + case 'v': + CIAO::RepositoryManager::write_to_ior_ = false; + CIAO::RepositoryManager::register_with_ns_ = true; + CIAO::RepositoryManager::repoman_name_ = get_opts.opt_arg (); + break; + case 's': + CIAO::RepositoryManager::HTTPserver = get_opts.opt_arg (); + break; + case 'n': + CIAO::RepositoryManager::nthreads = ACE_OS::atoi (get_opts.opt_arg ()); + break; + case '?': // display help for use of the server. + ACE_DEBUG ((LM_INFO, + "usage: %s\n" + "-o <using ior file>\n" + "-v <name of naming service>\n" + "-s <IP:PORT for HTTP server>\n" + "-n <number of threads>\n", + argv [0])); + return false; + break; + default: + ; + } + + return true; + } + + + +// **************************************************************** + +///Constuctor for the worker class +Worker::Worker (CORBA::ORB_ptr orb) + : orb_ (CORBA::ORB::_duplicate (orb)) +{ +} + +///implementation of the service routine inherited from ACE::Task_Base + +int Worker::svc (void) +{ + try + { + this->orb_->run (); + } + catch (const CORBA::Exception&) + { + } + return 0; +} + + diff --git a/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.mpc b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.mpc new file mode 100644 index 00000000000..204f52fe8ae --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager.mpc @@ -0,0 +1,68 @@ +// -*- MPC -*- +// $Id$ + +project (DAnCE_RepositoryManagerDaemon_IDL) : ciaoidldefaults { + custom_only = 1 + IDL_Files { + RepositoryManagerDaemon.idl + } +} + +project (DAnCE_RepositoryManager) : dance_repositorymanager_skel, ciao_config_handlers, ccm_stub, dance_repositorymanagerbase, naming, iortable, utils, minizip, zlib, dance_lib { + requires += zlib + libs += Package_Config_Handlers + after += DAnCE_RepositoryManagerDaemon_IDL + dynamicflags = DANCE_REPOSITORYMANAGER_MODULE_BUILD_DLL + IDL_Files { + } + + Source_Files { + RepositoryManagerDaemonC.cpp + RepositoryManagerDaemonS.cpp + ZIP_Wrapper.cpp + RepositoryManager_Impl.cpp + RM_Helper.cpp + URL_Parser.cpp + PC_Updater_T.cpp + PC_Updater.cpp + Repository_Manager_Module.cpp + } +} + +project (DAnCE_RepositoryManager_Exec) : dance_repositorymanager, dance_exe { + exename = dance_repository_manager + + Source_Files { + Repository_Manager_Exec.cpp + } + IDL_Files { + } +} + + +project (DAnCE_RepositoryManager_Admin) : dance_repositorymanager_stub, ciao_config_handlers, naming, dance_lib { + dynamicflags = DANCE_REPOSITORYMANAGER_ADMIN_BUILD_DLL + after += DAnCE_RepositoryManagerDaemon_IDL + + IDL_Files { + } + + Source_Files { + repository_manager_admin.cpp + RepositoryManagerDaemonC.cpp + } +} + +project (DAnCE_RepositoryManager_Admin_Exec) : dance_repositorymanager, ciao_config_handlers, naming, dance_exe, dance_logger { + exename = dance_rm_admin + + libs += DAnCE_RepositoryManager_Admin + after += DAnCE_RepositoryManager_Admin + + IDL_Files { + } + + Source_Files { + repository_manager_admin_exec.cpp + } +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/RepositoryManagerDaemon.idl b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManagerDaemon.idl new file mode 100644 index 00000000000..9deac4abd0e --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManagerDaemon.idl @@ -0,0 +1,13 @@ +// $Id$ + +#include "DAnCE/Deployment/Deployment_RepositoryManager.idl" + +module CIAO +{ + interface RepositoryManagerDaemon : Deployment::RepositoryManager + { + // Shutdown the daemon process. + oneway void shutdown (); + }; +}; + diff --git a/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.cpp b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.cpp new file mode 100644 index 00000000000..96dead11bb0 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.cpp @@ -0,0 +1,1256 @@ +// $Id$ + +//==================================================================== +/** + * @file RepositoryManager_Impl.cpp + * + * $Id$ + * + * Description: Actial implementation of the RepoMan + * + * @author Stoyan Paunov + * Shanshan Jiang <shanshan.jiang@vanderbilt.edu> + */ +//==================================================================== + +#include "RepositoryManager_Impl.h" + +#include "ace/OS_NS_fcntl.h" //for open +#include "ace/OS_NS_unistd.h" //for close +#include "ace/OS_NS_sys_stat.h" //for filesize and fstat and mkdir +#include "ace/OS_NS_string.h" //for ACE_CString +#include "ace/OS_Memory.h" //for ACE_NEW* macros + + +//to remove a file or dir from the local filesystem need remove () from stdio.h +// ---> need to include ace/OS_NS_stdio.h which would include the correct file for any OS! +#include "ace/OS_NS_stdio.h" + +#include "ZIP_Wrapper.h" //Wrapper around zzip +#include "ace/Containers_T.h" //for ACE_Double_Linked_List +#include "ace/Malloc_Allocator.h" //for ACE_New_Allocator + +//for the PackageConfiguration parsing +#include "DAnCE/Deployment/Deployment_DataC.h" +#include "DAnCE/Deployment/Deployment_Packaging_DataC.h" +#include "DAnCE/Logger/Log_Macros.h" + +#include "Package_Handlers/PCD_Handler.h" +#include "XML_Typedefs.h" + +#include "RM_Helper.h" //to be able to externalize/internalize a PackageConfiguration +#include "ace/Message_Block.h" //for ACE_Message_Block + +#include "ace/Thread.h" //for obtaining the ID of the current thread +#include "ace/OS_NS_stdlib.h" //for itoa () +#include "ace/Dirent.h" + +#include "URL_Parser.h" //for parsing the URL +#include "tao/HTTP_Client.h" //the HTTP client class to downloading packages + +#include "PC_Updater.h" //A visitor class to walk through the elements of the PC + +#include "ace/Configuration_Import_Export.h" + +namespace +{ + static const char* PC_EXTENSION = ".epc"; + + static const ACE_TCHAR *RM_RECORD_FILE = ACE_TEXT("RM_record"); + static const ACE_TCHAR *RM_RECORD_NAME_SECTION = ACE_TEXT("Names"); + static const ACE_TCHAR *RM_RECORD_UUID_SECTION = ACE_TEXT("UUIDs"); +} + +namespace DAnCE +{ + + //----------------------------------------------------------------- + //Constructor + // + //----------------------------------------------------------------- + + RepositoryManagerDaemon_i::RepositoryManagerDaemon_i + (CORBA::ORB_ptr the_orb, const ACE_TCHAR* server, const ACE_TCHAR* install_dir) + : the_orb_ (CORBA::ORB::_duplicate (the_orb)), + install_root_ (""), + HTTP_server_ ("http://"), + install_path (install_dir) + { + //form the path + this->HTTP_server_ += server; + this->HTTP_server_ += "/"; + this->HTTP_server_ += install_path; + this->HTTP_server_ += "/"; + + //create directory in which the packages will be stored + ACE_OS::mkdir(install_path.c_str ()); + //if dir already exists a -1 is returned + //we ignore this, just need to make sure the directory exists + + ACE_OS::getcwd (this->cwd_, TEMP_LEN); + + this->install_root_ = this->cwd_; + this->install_root_ += "/"; + this->install_root_ += install_path; + + // Install the configuration files to get the names, UUIDs, & types info. + ACE_Configuration_Heap cfg; + cfg.open (); + ACE_Configuration_Section_Key root = cfg.root_section (); + + ACE_Registry_ImpExp config_importer (cfg); + ACE_OS::chdir (install_path.c_str ()); + config_importer.import_config (RM_RECORD_FILE); + ACE_OS::chdir (this->cwd_); + + ACE_CString name; + ACE_Configuration::VALUETYPE type; + ACE_CString path; + + ACE_Configuration_Section_Key NameSection; + cfg.open_section (root, RM_RECORD_NAME_SECTION, 1, NameSection); + u_int index = 0; + while (!cfg.enumerate_values (NameSection, index, name, type)) + { + cfg.get_string_value (NameSection, name.c_str (), path); + this->names_.bind (name, path); + + ++index; + } + + ACE_Configuration_Section_Key UUIDSection; + cfg.open_section (root, RM_RECORD_UUID_SECTION, 1, UUIDSection); + index = 0; + while (!cfg.enumerate_values (UUIDSection, index, name, type)) + { + cfg.get_string_value (UUIDSection, name.c_str (), path); + this->uuids_.bind (name, path); + + ++index; + } + + // Add types + index = 0; + for (PCMap_Iterator iter = this->names_.begin (); + iter != this->names_.end (); + ++iter, ++index) + { + PCEntry& element = *iter; + + ::Deployment::PackageConfiguration_var pc = this->findPackageByName (element.ext_id_.c_str ()); + + if(!this->add_type (pc, element.ext_id_.c_str ())) + ACE_ERROR ((LM_ERROR, "Failed to add the type\n")); + } + + CIAO::Config_Handlers::XML_Helper::_path_resolver.add_path (ACE_TEXT ("CIAO_ROOT"), + ACE_TEXT ("/docs/schema/")); + + } + + //----------------------------------------------------------------- + //Destructor + // + //----------------------------------------------------------------- + + RepositoryManagerDaemon_i::~RepositoryManagerDaemon_i (void) + { + this->names_.unbind_all (); + this->uuids_.unbind_all (); + this->types_.unbind_all (); + } + + //----------------------------------------------------------------- + //shutdown + // + //----------------------------------------------------------------- + + void RepositoryManagerDaemon_i::shutdown () + + { + // Release resource. + this->names_.unbind_all (); + this->uuids_.unbind_all (); + this->types_.unbind_all (); + + this->the_orb_->shutdown (0); + } + + + //----------------------------------------------------------------- + //installPackage + // + //----------------------------------------------------------------- + + void RepositoryManagerDaemon_i::installPackage (const char * installationName, + const char * location, + ::CORBA::Boolean replace) + { + + PCEntry *entry = 0; + if (this->names_.find (ACE_CString (installationName), entry) == 0) + { + DANCE_DEBUG ((LM_INFO, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Found package %s already installed.\n")); + if (!replace) + throw Deployment::NameExists (); + else + deletePackage (installationName); + } + + //Now lets form the path for the local file + //NOTE: I need the absolute path because I will change to a subdirectory + //when I am parsing the descriptors + + ACE_CString path (this->install_root_); + path += "/"; + path += installationName; + + ACE_CString package_path (path); + package_path += ".cpk"; //package extension + + ACE_CString pc_path (path); + pc_path += PC_EXTENSION; //external PackageConfiguration extension + + + ACE_CString descriptor_dir (path); + descriptor_dir += "/descriptors/"; //location of the descriptor directory + + DANCE_DEBUG ((LM_DEBUG, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Package Path: %s\n", + package_path.c_str ())); + DANCE_DEBUG ((LM_DEBUG, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Descriptor path: %s\n", + descriptor_dir.c_str ())); + + //check if URL or local file + //download or load into memory + + if (ACE_OS::strstr (location, "http://")) + { + DANCE_DEBUG ((LM_INFO, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Downloading package over HTTP: %s\n", + location)); + + ACE_Message_Block* mb = 0; + ACE_NEW_THROW_EX (mb, ACE_Message_Block (), CORBA::NO_MEMORY ()); + + try + { + //get the remote file + if (!HTTP_Get (location, *mb)) + { + throw CORBA::INTERNAL (); + } + + // Write file to designated location on disk + if (!RM_Helper::write_to_disk (package_path.c_str (), *mb)) + { + throw CORBA::INTERNAL (); + } + + mb->release (); + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Caught unexpected exception while fetching path %s\n", + location)); + + mb->release (); + throw; + } + } + else + { + if (!RM_Helper::copy_from_disk_to_disk (location, package_path.c_str ())) + throw CORBA::INTERNAL (); + } + + + DANCE_DEBUG ((LM_TRACE, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Uncompressing file %s to directory %s\n", + package_path.c_str (), + this->install_root_.c_str ())); + + ZIP_Wrapper::uncompress (const_cast<char*> (package_path.c_str ()), + const_cast<char*> (this->install_root_.c_str ()), + false //not verbose + ); + + //Start the parsing + + ACE_CString pc_name; + + this->find_PC_name (const_cast<char*> (package_path.c_str ()), pc_name); + + //if the PackageConfiguration name cannot be found, then there is nothing to install + if (pc_name == "") + { + DANCE_ERROR ((LM_ERROR, DLINFO "RepositoryManagerDaemon_i::installPackage - " + "Unable to find PC name %s in path %s\n", + pc_name.c_str (), + package_path.c_str ())); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + + throw Deployment::PackageError (); + } + + //TODO: move exception throwing out of this func. User boolean error handling!!! + //TODO: check for errors! + Deployment::PackageConfiguration_var pc; + pc = this->retrieve_PC_from_descriptors (const_cast<char*> (pc_name.c_str ()), + descriptor_dir.c_str ()); + + + if (this->uuids_.find (ACE_CString (pc->UUID), entry) == 0) + { + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + + throw Deployment::NameExists (); + } + + //forming the server path info + ACE_CString server_path (this->HTTP_server_); + server_path += installationName; + + //NOTE: ComponentPackageReferences are currently NOT supported + if (!(pc->basePackage.length () > 0)) + { + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + + throw CORBA::NO_IMPLEMENT (); + } + + PC_Updater updater (server_path, package_path); + + if (!updater.update (pc)) + { + DANCE_DEBUG ((LM_ERROR, DLINFO "[RM] problem updating the PackageConfiguration!\n")); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + throw Deployment::PackageError (); + } + + + //now lets externalize the PackageConfiguration, so that we can access it later on + //without having to do the whole parsing again. + //NOTE: Order here is important. Do not populate maps before the externalization! + RM_Helper::externalize (pc, pc_path.c_str ()); + + //insert the package into the database + if (this->names_.bind (ACE_CString (installationName), path) == -1) + { + ACE_ERROR ((LM_ERROR, + "[RM] could not bind %s.\n", + installationName)); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + //remove the PackageConfiguration externalization + remove (pc_path.c_str ()); + + //throw exception + throw CORBA::INTERNAL (); + } + + //ALSO NEED THE UUID here + if (this->uuids_.bind (ACE_CString (pc->UUID), path) == -1) + { + ACE_ERROR ((LM_ERROR, + "[RM] could not bind %s.\n", + ACE_CString (pc->UUID).c_str ())); + + //unbind the name + this->names_.unbind (installationName); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + //remove the PackageConfiguration externalization + remove (pc_path.c_str ()); + + //throw exception + throw CORBA::INTERNAL (); + } + + //now add the type interface + if(!this->add_type (pc, installationName)) + ACE_ERROR ((LM_ERROR, "Failed to add the type\n")); + + this->dump (); + + this->save (); + + ACE_DEBUG ((LM_INFO, + "Installed PackageConfiguration \n\tname: %s \n\tuuid: %s\n", + installationName, ACE_CString (pc->UUID).c_str ())); + } + + + //----------------------------------------------------------------- + //createPackage + // + //----------------------------------------------------------------- + + void RepositoryManagerDaemon_i::createPackage (const char * installationName, + const ::Deployment::PackageConfiguration & package, + const char * baseLocation, + ::CORBA::Boolean replace) + { + ::Deployment::PackageConfiguration pc = package; + + // Find if there is a PackageConfiguration with the same name. + PCEntry *entry = 0; + if (this->names_.find (ACE_CString (installationName), entry) == 0) + { + if (!replace) + throw Deployment::NameExists (); + else + deletePackage (installationName); + } + + // Find if there is a PackageConfiguration with the same uuid. + if (this->uuids_.find (ACE_CString (pc.UUID), entry) == 0) + throw Deployment::NameExists (); + + // Find if the PackageConfiguration has a basePackage. + // NOTE: ComponentPackageReferences are currently NOT supported. + if (!(pc.basePackage.length () > 0)) + throw CORBA::NO_IMPLEMENT (); + + // Form the path for the local file + ACE_CString path (this->install_root_); + path += "/"; + path += installationName; + + ACE_CString package_path (path); + package_path += ".cpk"; //package extension + + ACE_CString pc_path (path); + pc_path += PC_EXTENSION; //external PackageConfiguration extension + + // Check if URL or local file, download or load into memory + if (ACE_OS::strstr (baseLocation, "http://")) + { + //TODO: how can I incorporate a Auto_Ptr is explicit release is needed + ACE_Message_Block* mb; + ACE_NEW_THROW_EX (mb, ACE_Message_Block (), CORBA::NO_MEMORY ()); + + //get the remote file + if (!HTTP_Get (baseLocation, *mb)) + { + mb->release (); + throw CORBA::INTERNAL (); + } + + // Write file to designated location on disk + if (!RM_Helper::write_to_disk (package_path.c_str (), *mb)) + { + mb->release (); + throw CORBA::INTERNAL (); + } + + mb->release (); + } + else + { + if (!RM_Helper::copy_from_disk_to_disk (baseLocation, package_path.c_str ())) + throw CORBA::INTERNAL (); + } + + + ZIP_Wrapper::uncompress (const_cast<char*> (package_path.c_str ()), + const_cast<char*> (this->install_root_.c_str ()), + false //not verbose + ); + + // Form the server path info + ACE_CString server_path (this->HTTP_server_); + server_path += installationName; + + // Update the newly installed package configration informantion. + PC_Updater updater (server_path, package_path); + + if (!updater.update (pc)) + { + ACE_ERROR ((LM_ERROR, "[RM] problem updating the PackageConfiguration!\n")); + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + throw Deployment::PackageError (); + } + + // Externalize the PackageConfiguration, so that we can access it later on + // without having to do the whole parsing again. + // NOTE: Order here is important. Do not populate maps before the externalization! + RM_Helper::externalize (pc, pc_path.c_str ()); + + // Insert the name of the package. + if (this->names_.bind (ACE_CString (installationName), path) == -1) + { + ACE_ERROR ((LM_ERROR, + "[RM] could not bind %s.\n", + installationName)); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + //remove the PackageConfiguration externalization + remove (pc_path.c_str ()); + + //throw exception + throw CORBA::INTERNAL (); + } + + // Insert the UUID of the package. + if (this->uuids_.bind (ACE_CString (pc.UUID), path) == -1) + { + ACE_ERROR ((LM_ERROR, + "[RM] could not bind %s.\n", + ACE_CString (pc.UUID).c_str ())); + + //unbind the name + this->names_.unbind (installationName); + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + //remove the PackageConfiguration externalization + remove (pc_path.c_str ()); + + //throw exception + throw CORBA::INTERNAL (); + } + + //now add the type interface + //TODO: CHECK if successful + if(!this->add_type (pc, installationName)) + ACE_ERROR ((LM_ERROR, "Failed to add the type\n")); + + this->dump (); + + this->save (); + + ACE_DEBUG ((LM_INFO, + "Created PackageConfiguration \n directory: %s \n name: %s \n uuid: %s\n", + path.c_str (), installationName, ACE_CString (pc.UUID).c_str ())); + } + + + //----------------------------------------------------------------- + //findPackageByName + // + //----------------------------------------------------------------- + + ::Deployment::PackageConfiguration* + RepositoryManagerDaemon_i::findPackageByName (const char * name) + + { + // Find out if the PackageConfiguration was installed in the repository, + // return it if found or throw and exception otherwise + + PCEntry *entry = 0; + + if (this->names_.find (ACE_CString (name), entry) != 0) + throw Deployment::NoSuchName (); + //PackageConfiguration was not found + + ACE_CString pc_path (entry->int_id_.c_str ()); + pc_path += PC_EXTENSION; + + Deployment::PackageConfiguration_var pc; + ACE_NEW_THROW_EX (pc, + Deployment::PackageConfiguration (), + CORBA::NO_MEMORY ()); + + + if(!RM_Helper::reincarnate (pc, pc_path.c_str ())) + throw CORBA::INTERNAL (); + + ACE_DEBUG ((LM_INFO, "Successfully looked up \'%s\'.\n", name)); + + return pc._retn (); + } + + + //----------------------------------------------------------------- + //findPackageByUUID + // + //----------------------------------------------------------------- + + ::Deployment::PackageConfiguration* + RepositoryManagerDaemon_i::findPackageByUUID (const char * UUID) + + { + // Find out if the PackageConfiguration was installed in the repository, + // return it if found or throw and exception otherwise + + PCEntry *entry = 0; + + if (this->uuids_.find (ACE_CString (UUID), entry) != 0) + throw Deployment::NoSuchName (); + //PackageConfiguration was not found + + ACE_CString pc_path (entry->int_id_.c_str ()); + pc_path += PC_EXTENSION; + + Deployment::PackageConfiguration_var pc; + ACE_NEW_THROW_EX (pc, + Deployment::PackageConfiguration (), + CORBA::NO_MEMORY ()); + + + if(!RM_Helper::reincarnate (pc, pc_path.c_str ())) + throw CORBA::INTERNAL (); + + ACE_DEBUG ((LM_INFO, "Successfully looked up %s.\n", UUID)); + + return pc._retn (); + } + + //----------------------------------------------------------------- + //findPackageByType + // + //----------------------------------------------------------------- + + ::CORBA::StringSeq * RepositoryManagerDaemon_i::findNamesByType (const char * type) + { + CIEntry *entry = 0; + + //find the type in the interface map + if (this->types_.find (ACE_CString (type), entry) != 0) + { + //return an empty sequence + CORBA::StringSeq_var seq; + ACE_NEW_THROW_EX (seq, CORBA::StringSeq (0), CORBA::NO_MEMORY ()); + + return seq._retn (); + } + else + { + CISet ci_set = (*entry).int_id_set_; + + CORBA::ULong len = ci_set.size (); + + //allocate a sequence of the right length + CORBA::StringSeq_var seq; + ACE_NEW_THROW_EX (seq, + CORBA::StringSeq (len), + CORBA::NO_MEMORY ()); + seq->length (len); + + //store the elements in the string sequence + CISet_Iterator ci_set_iter (ci_set); + CORBA::ULong index = 0; + for (ci_set_iter = ci_set.begin (); + ci_set_iter != ci_set.end () && index < len; + ++ci_set_iter, ++index) + { + seq[index] = CORBA::string_dup ((*ci_set_iter).c_str ()); + } + + return seq._retn (); + } + } + + + //----------------------------------------------------------------- + //getAllNames + // + //----------------------------------------------------------------- + + ::CORBA::StringSeq* + RepositoryManagerDaemon_i::getAllNames () + + { + //Map.current_size () gives you the current number with the duplicates + //Map.total_size () gives you the allocated space + the empty slots + //Apparently the only way to figure out the number of keys is to + //count them with an iterator. + + CORBA::ULong num_entries = 0; + + for (PCMap_Iterator i = this->names_.begin (); + i != this->names_.end (); + ++i) + ++num_entries; + + CORBA::StringSeq_var seq; + ACE_NEW_THROW_EX (seq, CORBA::StringSeq (num_entries), CORBA::NO_MEMORY ()); + + + seq->length (num_entries); + + CORBA::ULong index = 0; + for (PCMap_Iterator iter = this->names_.begin (); + iter != this->names_.end () && index < num_entries; + ++iter, ++index) + { + PCEntry& element = *iter; + seq[index] = CORBA::string_dup (element.ext_id_.c_str ()); + } + + ACE_DEBUG ((LM_INFO, "The number of packages %d\n", seq->length ())); + + return seq._retn (); //release the underlying CORBA::StringSeq + } + + + //----------------------------------------------------------------- + //getAllTypes + // + //----------------------------------------------------------------- + + ::CORBA::StringSeq * RepositoryManagerDaemon_i::getAllTypes () + { + //Map.current_size () gives you the current number with the duplicates + //Map.total_size () gives you the allocated space + the empty slots + //Apparently the only way to figure out the number of keys is to + //count them with an iterator. + + CORBA::ULong num_entries = 0; + + for (CIMap_Iterator i = this->types_.begin (); + i != this->types_.end (); + ++i) + ++num_entries; + + CORBA::StringSeq_var seq; + ACE_NEW_THROW_EX (seq, + CORBA::StringSeq (num_entries), + CORBA::NO_MEMORY ()); + + + seq->length (num_entries); + + CORBA::ULong index = 0; + for (CIMap_Iterator iter = this->types_.begin (); + iter != this->types_.end () && index < num_entries; + ++iter, ++index) + + { + CIEntry& element = *iter; + seq[index] = CORBA::string_dup (element.ext_id_.c_str ()); + } + + ACE_DEBUG ((LM_DEBUG, "The number of types: %d\n", num_entries)); + + return seq._retn (); //release the underlying CORBA::StringSeq + } + + + //----------------------------------------------------------------- + //DeletePackage + // + //----------------------------------------------------------------- + + void RepositoryManagerDaemon_i::deletePackage (const char * installationName) + { + bool internal_err = false; + + PCEntry *entry = 0; + + if (this->names_.find (ACE_CString (installationName), entry) != 0) + throw Deployment::NoSuchName (); + + //cache the package path + ACE_CString path (entry->int_id_.c_str ()); + + //remove the name association + if (this->names_.unbind (installationName) == -1) + { + ACE_ERROR ((LM_ERROR, + "Unable to unbind %s.\n", + installationName)); + internal_err = true; + } + + //the package location + ACE_CString package_path (path); + package_path += ".cpk"; //package extension + + //the PackageConfiguration externalization location + ACE_CString pc_path (path); + pc_path += PC_EXTENSION; //external PackageConfiguration extension + + Deployment::PackageConfiguration_var pc; + ACE_NEW_THROW_EX (pc, + Deployment::PackageConfiguration (), + CORBA::NO_MEMORY ()); + + + if(!RM_Helper::reincarnate (pc, pc_path.c_str ())) + { + ACE_ERROR ((LM_ERROR, "Could not reincarnate PC\n")); + internal_err = true; + } + + if (this->uuids_.unbind (ACE_CString (pc->UUID)) == -1) + { + ACE_ERROR ((LM_ERROR, "Could not remove UUID\n")); + internal_err = true; + } + + //remove the type from the interface map + if (!this->remove_type (pc, installationName)) + { + ACE_ERROR ((LM_ERROR, "Could not remove type\n")); + internal_err = true; + } + + //actually delete the package here! + + //clean the extracted files + remove_extracted_package (path.c_str ()); + //remove the package + remove (package_path.c_str ()); + //remove the PackageConfiguration externalization + remove (pc_path.c_str ()); + + this->dump (); + + this->save (); + + if (internal_err) + throw CORBA::INTERNAL (); + else + ACE_DEBUG ((LM_INFO, "Successfully deleted \'%s\'\n", installationName)); + + } + + + //==========================================HELPER METHODS================================================== + + Deployment::PackageConfiguration* + RepositoryManagerDaemon_i::retrieve_PC_from_package (char* package) + { + char temp[128]; + // ACE_thread_t thread_id = ACE_Thread::self (); + char* PID = ACE_OS::itoa (ACE_OS::getpid (), temp, 10); + + ACE_OS::mkdir(PID); + //if dir already exists a -1 is returned + //we ignore this, just need to make sure the directory exists + + //change the working dir + ACE_OS::chdir (PID); + + ACE_CString pcd_name; + //extract the necessary descriptors + if (extract_descriptor_files (package, + pcd_name) < 0) + { + ACE_OS::chdir (this->cwd_); + ACE_ERROR ((LM_ERROR, + "(%P|%t) RepositoryManager: error extracting necessary files\n")); + throw CORBA::INTERNAL (); + } + + Deployment::PackageConfiguration_var pc; + //parse the PCD to make sure that there are no package errors + try + { + //CIAO::Config_Handlers::STD_PC_Intf intf (pcd_name.c_str ()); + //pc = intf.get_PC (); + } + catch (...) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) RepositoryManager: Error parsing the PCD\n")); + + //change back the the old working dir + ACE_OS::chdir (this->cwd_); + throw Deployment::PackageError (); + } + //able to parse the PC. So lets install the package in the repo + + //we no longer need the descriptors, so lets erase them! + remove_descriptor_files (package); + + //change back the the old working dir + ACE_OS::chdir (this->cwd_); + + //now lets erase the directory! + ACE_OS::rmdir (PID); + //the ACE_OS::rmdir does not work. Possibly because we need to delete + //the contents first. I will look into it more closely when I am back. + + return pc._retn (); + } + + + //function to retvieve a file via HTTP + //stores the file in the passed preallocated ACE_Message_Block + //returns 1 on success + // 0 on error + + int RepositoryManagerDaemon_i::HTTP_Get (const char* URL, ACE_Message_Block &mb) + { + URL_Parser *parser = TheURL_Parser::instance (); + if (!parser->parseURL (const_cast<char*> (URL))) + return 0; + + // Create a client + TAO_HTTP_Client client; + + // Open the client + if (client.open (parser->filename_, + parser->hostname_, + parser->port_) == -1) + { + client.close (); + return 0; + } + + // Read from it + if (client.read (&mb) <= 0) + { + client.close (); + return 0; + } + + return 1; + } + + + + //function to parse and return the PackageConfiguration from the already + //extracted descriptor files + Deployment::PackageConfiguration* + RepositoryManagerDaemon_i::retrieve_PC_from_descriptors (const char* pc_name, + const char* descriptor_dir) + { + //change the working dir + ACE_OS::chdir (descriptor_dir); + + Deployment::PackageConfiguration_var pc = new Deployment::PackageConfiguration (); + //parse the PCD to make sure that there are no package errors + try + { + CIAO::Config_Handlers::Packaging::PCD_Handler::package_config (pc_name, *pc); + } + catch (...) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) [RM::retrieve_PC_from_descriptors] Error parsing the PCD\n")); + + //change back the the old working dir + ACE_OS::chdir (this->cwd_); + throw Deployment::PackageError (); + } + //able to parse the PC. So lets install the package in the repo + + //change back the the old working dir + ACE_OS::chdir (this->cwd_); + + return pc._retn (); + } + + + //find out what the name of the PackageConfiguration file is + void RepositoryManagerDaemon_i::find_PC_name (char* package, ACE_CString& pcd_name) + { + pcd_name = ""; //empty the contents of the ACE_CString + + //create a doubly link list + ACE_New_Allocator allocator; + ACE_Double_Linked_List<ZIP_File_Info> list (&allocator); + + //get the list of files in the package and figure out the names of all necessary files + if (!(ZIP_Wrapper::file_list_info (package, list))) + return; + + size_t skip_len = ACE_OS::strlen ("descriptors") + 1; + + while (!list.is_empty ()) + { + ZIP_File_Info* inf = list.delete_head (); + + if (ACE_OS::strstr (inf->name_.c_str (), "descriptors")) + if (ACE_OS::strstr (inf->name_.c_str (), ".pcd")) + pcd_name = inf->name_.c_str () + skip_len; + + //deallocate the head of the filename list + delete inf; + } + } + + + //We are using Xercesc in the Config_Handlers and unfortunately its API only + //takes a file in the local file system as an argument, thus need to + //write out the contents of the deployent plan to a file + //in the current directory. I use the thread id to guarrantee + //lack of race conditions if multithreading is enabled + + int RepositoryManagerDaemon_i::extract_descriptor_files (char* package, ACE_CString& pcd_name) + { + //create a doubly link list + ACE_New_Allocator allocator; + ACE_Double_Linked_List<ZIP_File_Info> list (&allocator); + + //get the list of files in the package and figure out the names of all necessary files + if (!(ZIP_Wrapper::file_list_info (package, list))) + return 0; + + size_t skip_len = ACE_OS::strlen ("descriptors") + 1; + + while (!list.is_empty ()) + { + ZIP_File_Info* inf = list.delete_head (); + ACE_Message_Block* file = 0; + if (ACE_OS::strstr (inf->name_.c_str (), "descriptors")) + { + if (ACE_OS::strstr (inf->name_.c_str (), ".pcd")) + pcd_name = inf->name_.c_str () + skip_len; + + //extract the descriptor from the package + ACE_NEW_RETURN (file, ACE_Message_Block (0,0), 0); + if (!ZIP_Wrapper::get_file(const_cast<char*> (package), + const_cast<char*> (inf->name_.c_str ()), + *file)) + { + ACE_ERROR ((LM_ERROR, + "[RM::extract_descriptor_files] Unable to retrieve file!\n")); + //release the message block chain + file->release (); + return 0; + } + + + //write the file to disk + if(!RM_Helper::write_to_disk (inf->name_.c_str () + skip_len, *file)) + { + ACE_ERROR ((LM_ERROR, + "[RM::extract_descriptor_files] Unable to write out descriptor to disk!\n")); + //release the message block chain + file->release (); + return 0; + } + + //release the message block chain + file->release (); + } + + //deallocate the head of the filename list + delete inf; + } + + return 1; + } + + int RepositoryManagerDaemon_i::remove_descriptor_files (char* package) + { + int return_code = 1; + + //create a doubly link list + ACE_New_Allocator allocator; + ACE_Double_Linked_List<ZIP_File_Info> list (&allocator); + + //get the list of files in the package and figure out the names of all necessary files + if (!(ZIP_Wrapper::file_list_info (package, list))) + return 0; + + size_t skip_len = ACE_OS::strlen ("descriptors") + 1; + + while (!list.is_empty ()) + { + ZIP_File_Info* inf = list.delete_head (); + if (ACE_OS::strstr (inf->name_.c_str (), "descriptors")) + { + //delete disk + if(remove (inf->name_.c_str () + skip_len)) + { + ACE_ERROR ((LM_ERROR, + "[RM::remove_descriptor_files] Unable to remove file from disk!\n")); + return_code = 0; + } + } + //deallocate the head of the filename list + delete inf; + } + + return return_code; + } + + int RepositoryManagerDaemon_i::remove_extracted_package (const char* path) + { + ACE_TCHAR full_path[MAXPATHLEN]; + ACE_OS::getcwd (full_path, sizeof(full_path)); + + ACE_OS::chdir (path); + + ACE_Dirent dir (path); + + for (ACE_DIRENT *directory; (directory = dir.read ()) != 0;) + { + if (ACE::isdotdir (directory->d_name) == true) + continue; + + ACE_stat stat_buf; + ACE_OS::lstat (directory->d_name, &stat_buf); + + ACE_CString temp = path; + temp += "/"; + temp += directory->d_name; + switch (stat_buf.st_mode & S_IFMT) + { + case S_IFREG: // Either a regular file or an executable. + remove (temp.c_str ()); + break; + + case S_IFDIR: + remove_extracted_package (temp.c_str ()); + break; + + default: + break; + } + } + + ACE_OS::chdir (full_path); + + ACE_OS::rmdir (path); + + return 0; + } + + //function to extract the type of the component from + //the PackageConfiguration and update the interface map + //returns 1 on success + // 0 on error + + int RepositoryManagerDaemon_i::add_type (Deployment::PackageConfiguration& pc, + const char* name) + { + if (pc.basePackage.length () > 0) + { + ::CORBA::StringSeq supportedTypes = pc.basePackage[0] + .implementation[0] + .referencedImplementation + .implements + .supportedType; + + if (supportedTypes.length () != 0) + { + CORBA::ULong len = supportedTypes.length (); + for (CORBA::ULong i = 0; i < len; ++i) + { + this->types_.bind (ACE_CString (supportedTypes[i]), name); + } + } + } + else //ComponentPackageReference + { + //not implemented yet + return 0; + } + + return 1; + } + + //function to remove the interface type of the component + //being removed from the interface map + //returns 1 on success + // 0 on error + + int RepositoryManagerDaemon_i::remove_type (Deployment::PackageConfiguration& pc, + const char* name) + { + if (pc.basePackage.length () > 0) + { + ::CORBA::StringSeq supportedTypes = pc.basePackage[0] + .implementation[0] + .referencedImplementation + .implements + .supportedType; + + if (supportedTypes.length () != 0) + { + CORBA::ULong len = supportedTypes.length (); + for (CORBA::ULong i = 0; i < len; ++i) + { + if (this->types_.unbind (ACE_CString (supportedTypes[i]), ACE_CString (name)) != 0) + ACE_DEBUG ((LM_DEBUG, "Could not find type %s with package name %s!\n", + ACE_CString (supportedTypes[i]).c_str (), + name)); + } + } + } + else //ComponentPackageReference + { + //not implemented yet + return 0; + } + + return 1; + } + + //function to dump the state of the RepositoryManager + void RepositoryManagerDaemon_i::dump (void) + { +#if defined (ACE_HAS_DUMP) + + ACE_DEBUG(LM_DEBUG, "NAMES:\n"); + this->names_.dump (); + ACE_DEBUG(LM_DEBUG, "UUIDs:\n"); + this->uuids_.dump (); + ACE_DEBUG (LM_DEBUG, "Component Interface Types:\n"); + this->types_.dump (); + +#endif /* ACE_HAS_DUMP */ + } + + //function to save the package info of the RepositoryManager + void RepositoryManagerDaemon_i::save (void) + { + // Save the names, UUIDs, & types info to the configuration files. + ACE_Configuration_Heap cfg; + cfg.open (); + ACE_Configuration_Section_Key root = cfg.root_section (); + + ACE_Configuration_Section_Key NameSection; + cfg.open_section (root, RM_RECORD_NAME_SECTION, 1, NameSection); + for (PCMap_Iterator iter = this->names_.begin (); + iter != this->names_.end (); + ++iter) + { + PCEntry& element = *iter; + cfg.set_string_value (NameSection, element.ext_id_.c_str (), element.int_id_.c_str ()); + } + + ACE_Configuration_Section_Key UUIDSection; + cfg.open_section (root, RM_RECORD_UUID_SECTION, 1, UUIDSection); + for (PCMap_Iterator iter = this->uuids_.begin (); + iter != this->uuids_.end (); + ++iter) + { + PCEntry& element = *iter; + cfg.set_string_value (UUIDSection, element.ext_id_.c_str (), element.int_id_.c_str ()); + } + + ACE_Registry_ImpExp exporter (cfg); + ACE_OS::chdir (install_path.c_str ()); + exporter.export_config (RM_RECORD_FILE); + ACE_OS::chdir (this->cwd_); + } +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.h b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.h new file mode 100644 index 00000000000..051c6577514 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/RepositoryManager_Impl.h @@ -0,0 +1,235 @@ + +/* -*- C++ -*- */ + +//====================================================================== +/** + * @file RepositoryManager_Impl.h + * + * $Id$ + * + * Description: + * This file is the main implementation file for the RepositoryManager + * in CIAO. We have used a number of techniques in order to increase + * scalability of the RepoMan while still maintaining complience with + * the D&C spec + * + * @author Stoyan Paunov + * @author Shanshan Jiang <shanshan.jiang@vanderbilt.edu> + * @author William R. Otte <wotte@dre.vanderbilt.edu> + */ +//====================================================================== + +#ifndef REPOSITORYMANAGERI_H_ +#define REPOSITORYMANAGERI_H_ + + +//-----------------------------NOTE--------------------------------- +//I need to disable all the code which has to do with interface +//type information because we currently do not support assembly +//interfaces which causes undesired behavior with respect to the +//hash tables because the specificType field in assembly interfaces +//is empty, so two unrelated intefaces appear to be related. + + +#include "RepositoryManagerDaemonS.h" + +#include "ace/Hash_Map_Manager_T.h" //for the ACE_Hash_Map_Manager +#include "ace/Hash_Multi_Map_Manager_T.h" //for the ACE_Hash_MultiMap_Manager +#include "ace/Null_Mutex.h" //for ACE_Null_Mutex +#include "ace/RW_Mutex.h" //for ACE_RW_Mutex +#include "ace/OS_NS_string.h" //for ACE_CString +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace +{ + static const size_t TEMP_LEN = 1024; +} + +namespace DAnCE +{ + class RepositoryManagerDaemon_i : + public virtual POA_CIAO::RepositoryManagerDaemon + { + public: + /// Constructor + RepositoryManagerDaemon_i (CORBA::ORB_ptr the_orb, + const ACE_TCHAR* server = ACE_TEXT("localhost:5432"), + const ACE_TCHAR* install_dir = ACE_TEXT("RepositoryManager")); + + /// Destructor + virtual ~RepositoryManagerDaemon_i (void); + + virtual void shutdown (); + + virtual + void installPackage (const ACE_TCHAR * installationName, + const ACE_TCHAR * location, + ::CORBA::Boolean replace); + + virtual + void createPackage (const ACE_TCHAR * installationName, + const ::Deployment::PackageConfiguration & package, + const ACE_TCHAR * baseLocation, + ::CORBA::Boolean replace); + + virtual + ::Deployment::PackageConfiguration * findPackageByName (const ACE_TCHAR * name); + + virtual + ::Deployment::PackageConfiguration * findPackageByUUID (const ACE_TCHAR * UUID); + + virtual + ::CORBA::StringSeq * findNamesByType (const ACE_TCHAR * type); + + virtual + ::CORBA::StringSeq * getAllNames (); + + virtual + ::CORBA::StringSeq * getAllTypes (); + + virtual + void deletePackage (const ACE_TCHAR * installationName); + + protected: + + /// Function to parse and return the PackageConfiguration from a specified + /// package + Deployment::PackageConfiguration* retrieve_PC_from_package (ACE_TCHAR* package); + + /// Find out what the name of the PackageConfiguration file is + void find_PC_name (ACE_TCHAR* package, ACE_CString& pcd_name); + + /// Function to parse and return the PackageConfiguration from the already + /// extracted descriptor files + Deployment::PackageConfiguration* retrieve_PC_from_descriptors (const ACE_TCHAR* pc_name, + const ACE_TCHAR* descriptor_dir); + + + /// Function to retrieve a file via HTTP + /// stores the file in the passed preallocated ACE_Message_Block + /// @retval 1 success + /// @retval 0 error + int HTTP_Get (const ACE_TCHAR* URL, ACE_Message_Block &mb); + + /// Function to extract all necessary files for parsing the + /// PackageConfiguration descriptor and populating the idl struct. + /// @retval 1 success + /// @retval 0 error + /// + /// @note ACE_CString& pcd_name is an out parameter + int extract_descriptor_files (ACE_TCHAR* package, + ACE_CString& pcd_name); + + + /// Function to remove the files extracted for parsing the PackageConfiguration + /// descriptor and populating the idl struct. It reads the names of the files + /// from the package. They correspond to the names on disk. + /// @retval 1 on success + /// @retval 0 on error + int remove_descriptor_files (ACE_TCHAR* package); + + + /// Function to remove the files extracted from the package upon istallation + /// It reads the names of the files from the package. They correspond to the + /// names on disk. It deletes each file, then it deletes the directories that + /// contain them. + /// @note extraction location is path/*archive_name*/ + /// @retval 1 on success + /// @retval 0 on error + int remove_extracted_package (const ACE_TCHAR* package_path); + + /// Function to extract the type of the component from + /// the PackageConfiguration and update the interface map + /// @retval 1 on success + /// @retval 0 on error + int add_type (::Deployment::PackageConfiguration& pc, + const ACE_TCHAR* name); + + /// Function to remove the interface type of the component + /// being removed from the interface map + /// @retval 1 on success + /// @retval 0 on error + int remove_type (::Deployment::PackageConfiguration& pc, + const ACE_TCHAR* name); + + /// Function to dump the state of the RepositoryManager + void dump (void); + + /// Function to save the package info of the RepositoryManager + void save (void); + + private: + /// Cached information about the installed PackageConfigurations + /// A separate map for the installation names and their UUID's + /// Key: PackageConfiguration name or its UUID (CString type) + /// Value: The location of the local copy of the package + + ///Based on the synchronization needed we can parametrize this with either + ///ACE_Null_Mutex or ACE_RW_Mutex + + typedef ACE_Hash_Map_Manager_Ex<ACE_CString, + ACE_CString, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_RW_Mutex> PCMap; + + typedef PCMap::ITERATOR PCMap_Iterator; + typedef PCMap::ENTRY PCEntry; + + + /// Cached information about the installed Component Interfaces + /// A map which associates Component supportedType with the + /// names of packages which implement this component type + /// Key: Component supportedType + /// Value: Unbounded set of the names of installed packages which + /// implement this component type + + ///Based on the synchronization needed we can parametrize this with either + ///ACE_Null_Mutex or ACE_RW_Mutex + + typedef ACE_Hash_Multi_Map_Manager<ACE_CString, + ACE_CString, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_RW_Mutex> CIMap; + + typedef CIMap::ITERATOR CIMap_Iterator; + typedef CIMap::ENTRY CIEntry; + typedef CIEntry::VALUE_SET CISet; + typedef CIEntry::VALUE_SET_ITERATOR CISet_Iterator; + + /// A hash map that associates the names of + /// PackageConfigurations with their location + PCMap names_; + + /// a hash map that associates the UUIDs of + /// PackageConfigurations with their location + PCMap uuids_; + + /// a hash map which associates Component Interface + /// UUIDs with their implementations + CIMap types_; + + /// The ORB + CORBA::ORB_var the_orb_; + + /// Will hold the current working directory + ACE_TCHAR cwd_ [TEMP_LEN]; + + /// Full path for the install directory + ACE_CString install_root_; + + /// Location of the server + ACE_CString HTTP_server_; + + /// Directory where the packages will be stored locally + ACE_CString install_path; +}; + +} + +#endif /* REPOSITORYMANAGER_H_ */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Admin_Export.h b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Admin_Export.h new file mode 100644 index 00000000000..a705cd0c2b7 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Admin_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl DAnCE_RepositoryManager_Admin +// ------------------------------ +#ifndef DANCE_REPOSITORYMANAGER_ADMIN_EXPORT_H +#define DANCE_REPOSITORYMANAGER_ADMIN_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL) +# define DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL */ + +#if !defined (DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL) +# define DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL 1 +#endif /* ! DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL */ + +#if defined (DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL) && (DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL == 1) +# if defined (DANCE_REPOSITORYMANAGER_ADMIN_BUILD_DLL) +# define DAnCE_RepositoryManager_Admin_Export ACE_Proper_Export_Flag +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* DANCE_REPOSITORYMANAGER_ADMIN_BUILD_DLL */ +# define DAnCE_RepositoryManager_Admin_Export ACE_Proper_Import_Flag +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* DANCE_REPOSITORYMANAGER_ADMIN_BUILD_DLL */ +#else /* DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL == 1 */ +# define DAnCE_RepositoryManager_Admin_Export +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARATION(T) +# define DANCE_REPOSITORYMANAGER_ADMIN_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* DANCE_REPOSITORYMANAGER_ADMIN_HAS_DLL == 1 */ + +// Set DANCE_REPOSITORYMANAGER_ADMIN_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (DANCE_REPOSITORYMANAGER_ADMIN_NTRACE) +# if (ACE_NTRACE == 1) +# define DANCE_REPOSITORYMANAGER_ADMIN_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define DANCE_REPOSITORYMANAGER_ADMIN_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !DANCE_REPOSITORYMANAGER_ADMIN_NTRACE */ + +#if (DANCE_REPOSITORYMANAGER_ADMIN_NTRACE == 1) +# define DANCE_REPOSITORYMANAGER_ADMIN_TRACE(X) +#else /* (DANCE_REPOSITORYMANAGER_ADMIN_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define DANCE_REPOSITORYMANAGER_ADMIN_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (DANCE_REPOSITORYMANAGER_ADMIN_NTRACE == 1) */ + +#endif /* DANCE_REPOSITORYMANAGER_ADMIN_EXPORT_H */ + +// End of auto generated file. diff --git a/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Exec.cpp b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Exec.cpp new file mode 100644 index 00000000000..371fabf1406 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Exec.cpp @@ -0,0 +1,6 @@ +// $Id$ +#include "Repository_Manager_Module.h" + +#define DANCE_MODULE_MAIN_CLASS_NAME DAnCE_RepositoryManager_Module +#include "Deployment/Module_Main.h" + diff --git a/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.cpp b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.cpp new file mode 100644 index 00000000000..a8fcdf872ab --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.cpp @@ -0,0 +1,520 @@ +// -*- C++ -*- +// $Id$ + +#include "Repository_Manager_Module.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" +#include "ace/Task.h" +#include "ace/Atomic_Op.h" +#include "tao/IORTable/IORTable.h" +#include "tao/Utils/PolicyList_Destroyer.h" +#include "orbsvcs/CosNamingC.h" +#include "orbsvcs/orbsvcs/Naming/Naming_Loader.h" +#include "DAnCE/Logger/Log_Macros.h" +#include "DAnCE/Deployment/DAnCE_PropertiesC.h" + +#ifdef DANCE_RM_USES_JAWS +#include "JAWS/server/HTTP_Server.h" +#endif + +#include "RepositoryManager_Impl.h" + +ACE_RCSID (DAnCE, + Repository_Manager_Module, + "$Id$") + +namespace DAnCE +{ + namespace Repository_Manager + { + bool + write_IOR (const ACE_TCHAR * ior_file_name, const char* ior) + { + FILE* ior_output_file_ = + ACE_OS::fopen (ior_file_name, ACE_TEXT("w")); + + if (ior_output_file_) + { + ACE_OS::fprintf (ior_output_file_, + "%s", + ior); + ACE_OS::fclose (ior_output_file_); + return true; + } + return false; + } + + class Worker : public virtual ACE_Task_Base + { + public: + Worker (CORBA::ORB_ptr orb) : + orb_(CORBA::ORB::_duplicate (orb)) + { + } + + virtual int svc (void) + { + DANCE_TRACE ("DAnCE::Repository_Manager::Worker::svc"); + + size_t thread_id = ++this->thread_counter_; + + try + { + DANCE_DEBUG ((LM_INFO, DLINFO ACE_TEXT("DAnCE::Repository_Manager::Worker::svc - ") + ACE_TEXT("Spawning thread %u for the ORB.\n"), thread_id)); + this->orb_->run (); + DANCE_DEBUG ((LM_INFO, DLINFO ACE_TEXT("DAnCE::Repository_Manager::Worker::svc - ") + ACE_TEXT("ORB event loop for thread %u completed successfully.\n"), thread_id)); + } + catch (const CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("DAnCE::Repository_Manager::Worker::svc - ") + ACE_TEXT("Caught CORBA exception from ORB event loop for thread %u: %C\n"), + thread_id, ex._info ().c_str ())); + return -1; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("DAnCE::Repository_Manager::Worker::svc - ") + ACE_TEXT("Caught unknown C++ exception from ORB event loop for thread %u\n"), + thread_id)); + return -1; + } + + return 0; + } + + private: + ACE_Atomic_Op<TAO_SYNCH_MUTEX, unsigned long> thread_counter_; + CORBA::ORB_var orb_; + }; + } +} + +DAnCE_RepositoryManager_Module::DAnCE_RepositoryManager_Module (void) +{ + DANCE_TRACE("DAnCE_RepositoryManager_Module::DAnCE_RepositoryManager_Module"); +} + +DAnCE_RepositoryManager_Module::~DAnCE_RepositoryManager_Module (void) +{ + DANCE_TRACE ("DAnCE_RepositoryManager_Module::~DAnCE_RepositoryManager_Module"); + + for (Servant_Map::iterator it = this->rm_map_.begin (); + it != this->rm_map_.end (); + ++it) + { + delete (*it).int_id_; + } +} + +const char * +DAnCE_RepositoryManager_Module::usage (void) +{ + DANCE_TRACE ("DAnCE_RepositoryManager_Module::usage"); + return "Repository Manager Options:\n" + "\t-n|--name [name]\t Name to register in the naming service\n" + "\t-t|--threads [num]\t Number of threads to run.\n" + "\t-f|--file [name]\t Filename to output IOR.\n" + "\t-p|--package-dir [directory]\t Directory to store packages.\n" + "\t-s|--server-address [address]\t Address of the HTTP server associated with this RM.\n" + "\t-d|--domain-nc [NC]\t Default naming context for domain objects.\n" + "\t-h|help\t\t\t print this help message\n" +#ifdef DANCE_RM_USES_JAWS + "\t--spawn-http\t\t Spawn a JAWS http server, controlled by following options:\n" + "\t--http-port [port]\t Spawn JAWS HTTP server with provided port, default is 5432\n" + "\t--http-threads [number]\t Spawn provided number of threads in HTTP server, default is 1\n" + "\t--http-threading [strategy]\t Use provided threading strategy. POOL (Default), PER_REQUEST, THROTTLE.\n" + "\t--http-io [stratety]\t Use provided I/O strategy. SYNCH (default), ASYNCH.\n" + "\t--http-caching [strategy]\t Use provided caching strategy. NO_CACHE (default), CACHE\n" +#endif + ; + +} + +bool +DAnCE_RepositoryManager_Module::parse_args (int argc, ACE_TCHAR * argv[]) +{ + DANCE_TRACE ("DAnCE_RepositoryManager_Module::parse_args"); + + ACE_Get_Opt get_opts (argc - 1, + argv + 1, + ACE_TEXT(":hd:t:f:p:n:"), + 0, + 0, + ACE_Get_Opt::RETURN_IN_ORDER, + 1); + + get_opts.long_option (ACE_TEXT("help"), 'h', ACE_Get_Opt::NO_ARG); + get_opts.long_option (ACE_TEXT("domain-nc"), 'd', ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("file"), 'f', ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("threads"), 't', ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("package-dir"), 'p', ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("name"), 'n', ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("server-address"), 's', ACE_Get_Opt::ARG_REQUIRED); +#ifdef DANCE_RM_USES_JAWS + get_opts.long_option (ACE_TEXT("spawn-http"), ACE_Get_Opt::NO_ARG); + get_opts.long_option (ACE_TEXT("http-port"), ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("http-threads"), ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("http-threading"), ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("http-io"), ACE_Get_Opt::ARG_REQUIRED); + get_opts.long_option (ACE_TEXT("http-caching"), ACE_Get_Opt::ARG_REQUIRED); +#endif /* DANCE_RM_USES_JAWS */ + + //get_opts.long_option ("help", '?'); + + char c; + while ( (c = get_opts ()) != -1) + { + switch (c) + { + case 'd': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Binding to provided Domain Naming Context: '%s'\n"), + get_opts.opt_arg ())); + this->options_.domain_nc_ = get_opts.opt_arg (); + break; + + case 'f': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Output filename for IOR is %s\n"), + get_opts.opt_arg ())); + this->options_.ior_file_ = get_opts.opt_arg (); + break; + + case 't': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Number of threads is %s\n"), get_opts.opt_arg ())); + this->options_.threads_ = (ACE_OS::atoi (get_opts.opt_arg ())); + break; + + case 'p': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Package directory is %s\n"), + get_opts.opt_arg ())); + this->options_.package_dir_ = get_opts.opt_arg (); + break; + + case 'n': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Name is %s\n"), + get_opts.opt_arg ())); + this->options_.name_ = get_opts.opt_arg (); + break; + + case 's': + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Server address is %s\n"), + get_opts.opt_arg ())); + this->options_.server_address_ = get_opts.opt_arg (); + break; + + case 0: + if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("spawn-http")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Found option to spawn in-process HTTP server\n"))); + this->options_.spawn_http_ = true; + } + else if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("http-port")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Using %s as the spawned HTTP server port\n"), + get_opts.opt_arg ())); + this->options_.spawn_http_ = true; + this->options_.http_port_ = get_opts.opt_arg (); + } + else if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("http-threads")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Using %s as the spawned HTTP number of threads\n"), + get_opts.opt_arg ())); + this->options_.spawn_http_ = true; + this->options_.http_threads_ = get_opts.opt_arg (); + } + else if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("http-threading")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Using %s as the spawned HTTP server threading model\n"), + get_opts.opt_arg ())); + this->options_.spawn_http_ = true; + this->options_.http_threading_ = get_opts.opt_arg (); + } + else if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("http-io")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Using %s as the spawned HTTP server IO strategy\n"), + get_opts.opt_arg ())); + this->options_.spawn_http_ = true; + this->options_.http_io_ = get_opts.opt_arg (); + } + else if (ACE_OS::strcmp (get_opts.long_option (), ACE_TEXT("http-caching")) == 0) + { + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Using %s as the spawned HTTP server caching strategy\n"), + get_opts.opt_arg ())); + this->options_.spawn_http_ = true; + this->options_.http_caching_ = get_opts.opt_arg (); + } + else + { + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("ERROR: unknown long option %s\n"), + get_opts.long_option ())); + } + + break; + + case 'h': + case '?': // Display help for use of the server. + default: + DANCE_ERROR_RETURN ( (LM_ERROR, + this->usage (), + argv [0], c), + false); + break; + } + + } + + if (this->options_.server_address_ == 0) + { + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("Repository_Manager_Module::parse_args - ") + ACE_TEXT("Must provider server address using --server-address option.\n"))); + return false; + } + + return true; +} + +CORBA::Object_ptr +DAnCE_RepositoryManager_Module::create_object (CORBA::ORB_ptr orb, + int argc, + ACE_TCHAR *argv[]) +{ + DANCE_TRACE ("DAnCE_RepositoryManager_Module::create_object"); + + try + { + if (CORBA::is_nil(orb)) + { + DANCE_ERROR((LM_ERROR, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Attempted to create Repository Manager with a nil orb.\n"))); + return CORBA::Object::_nil(); + } + else + { + this->orb_ = CORBA::ORB::_duplicate (orb); + } + + if (ACE_OS::strcmp(orb->id(), this->orb_->id()) != 0) + { + DANCE_DEBUG((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Resetting NM's orb.\n"))); + this->orb_ = CORBA::ORB::_duplicate (orb); + this->domain_nc_ = CosNaming::NamingContext::_nil(); + } + + if (!this->parse_args (argc, argv)) + { + return CORBA::Object::_nil (); + } + + if (this->options_.spawn_http_) + this->spawn_http (); + + this->create_poas (); + + if (this->options_.domain_nc_) + { + try + { + DANCE_DEBUG((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Resolving DomainNC.\n"))); + CORBA::Object_var domain_obj = this->orb_->string_to_object (this->options_.domain_nc_); + if (!CORBA::is_nil (domain_obj.in ())) + { + this->domain_nc_ = CosNaming::NamingContext::_narrow (domain_obj.in()); + if (CORBA::is_nil (this->domain_nc_.in ())) + { + DANCE_ERROR ((LM_ERROR,DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Narrow to NamingContext return nil for DomainNC.\n"))); + return CORBA::Object::_nil (); + } + } + } + catch (const CORBA::Exception&) + { + DANCE_DEBUG ((LM_WARNING, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("DomainNC context not found!\n"))); + } + } + + + DANCE_DEBUG ((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Initializing the IOR Table\n"))); + // Initialize IOR table + CORBA::Object_var table_object = orb->resolve_initial_references ("IORTable"); + + IORTable::Table_var adapter = IORTable::Table::_narrow (table_object.in ()); + + if (CORBA::is_nil (adapter.in ())) + { + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Unable to RIR the IORTable.\n"))); + return CORBA::Object::_nil (); + } + + + //Creating repository manager servant + DAnCE::RepositoryManagerDaemon_i * rm = new DAnCE::RepositoryManagerDaemon_i (orb, + this->options_.server_address_, + this->options_.package_dir_); + PortableServer::ServantBase_var safe_svt (rm); + + ACE_CString repository_manager_oid; + + if (this->options_.name_ == 0) + repository_manager_oid = "RepositoryManager"; + else + { + repository_manager_oid = this->options_.name_; + repository_manager_oid += ".RepositoryManager"; + } + + // Registering servant in poa + PortableServer::ObjectId_var oid = + PortableServer::string_to_ObjectId (repository_manager_oid.c_str()); + this->rm_poa_->activate_object_with_id (oid, rm); + + // Getting repository manager ior + CORBA::Object_var nm_obj = this->rm_poa_->id_to_reference (oid.in ()); + CORBA::String_var ior = orb->object_to_string (nm_obj.in ()); + + // Binding ior to IOR Table + adapter->bind (repository_manager_oid.c_str (), ior.in ()); + + // Binding repository menager to DomainNC + if (!CORBA::is_nil (this->domain_nc_.in ())) + { + ACE_CString ns_name; + if (this->options_.name_ == 0) + ns_name = "RepositoryManager"; + else ns_name = this->options_.name_; + + DANCE_DEBUG((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Registering NM in NC as \"%C\".\n"), ns_name.c_str ())); + CosNaming::Name name (1); + name.length (1); + name[0].id = CORBA::string_dup (ns_name.c_str ()); + name[0].kind = CORBA::string_dup ("RepositoryManager"); + this->domain_nc_->rebind (name, nm_obj.in ()); + } + + // Writing ior to file + if (0 != this->options_.ior_file_) + { + DANCE_DEBUG ((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Writing RM IOR %C to file %C.\n"), this->options_.ior_file_, ior.in ())); + if (!DAnCE::Repository_Manager::write_IOR (this->options_.ior_file_, ior.in ())) + DANCE_ERROR ((LM_ERROR, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("Error: Unable to write IOR to file %C\n"), + this->options_.ior_file_)); + } + + // Activate POA manager + PortableServer::POAManager_var mgr = this->root_poa_->the_POAManager (); + mgr->activate (); + + // Finishing Deployment part + DANCE_DEBUG ((LM_NOTICE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("DAnCE_RepositoryManager is running...\n"))); + + DANCE_DEBUG ((LM_DEBUG, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_object - ") + ACE_TEXT("RepositoryManager IOR: %C\n"), ior.in ())); + + return nm_obj._retn (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("DAnCE_RepositoryManager::main\t\n"); + return CORBA::Object::_nil (); + } +} + +void +DAnCE_RepositoryManager_Module::create_poas (void) +{ + DANCE_TRACE("DAnCE_Repository_Manager_Module::create_poas"); + // Get reference to Root POA. + DANCE_DEBUG ((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_poas - ") + ACE_TEXT("Resolving root POA\n"))); + CORBA::Object_var obj = this->orb_->resolve_initial_references ("RootPOA"); + + this->root_poa_ = PortableServer::POA::_narrow (obj.in ()); + + DANCE_DEBUG ((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_poas - ") + ACE_TEXT("Obtaining the POAManager\n"))); + PortableServer::POAManager_var mgr = this->root_poa_->the_POAManager (); + + TAO::Utils::PolicyList_Destroyer policies (2); + policies.length (2); + + try + { + DANCE_DEBUG ((LM_TRACE, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_poas - ") + ACE_TEXT("DAnCE_RepositoryManager_Module::create_poas - ") + ACE_TEXT("Creating the \"Repository\" POA.\n"))); + + policies[0] = this->root_poa_->create_id_assignment_policy (PortableServer::USER_ID); + policies[1] = this->root_poa_->create_lifespan_policy (PortableServer::PERSISTENT); + this->rm_poa_ = this->root_poa_->create_POA ("Repository", + mgr.in(), + policies); + } + catch (const PortableServer::POA::AdapterAlreadyExists &) + { + DANCE_DEBUG ((LM_INFO, DLINFO ACE_TEXT("DAnCE_RepositoryManager_Module::create_poas - ") + ACE_TEXT("Using existing \"Repository\" POA\n"))); + this->rm_poa_ = this->root_poa_->find_POA ("Repository", 0); + } +} + +void +DAnCE_RepositoryManager_Module::spawn_http (void) +{ + DANCE_TRACE ("DAnCE_RepositoryManager_Module::spawn_http"); + + ACE_CString directive = +#if (ACE_USES_CLASSIC_SVC_CONF == 0) + ACE_TEXT ("<dynamic id=\"HTTP_Server\" type=\"Service_Object\">") + ACE_TEXT (" <initializer init=\"_make_HTTP_Server\" path=\"JAWS\" params=\""); +#else + ACE_TEXT ("dynamic HTTP_Server Service_Object *") + ACE_TEXT (" JAWS:_make_HTTP_Server() \""); +#endif + + directive += ACE_TEXT ("-p "); + directive += this->options_.http_port_; + directive += ACE_TEXT (" -n "); + directive += this->options_.http_threads_; + directive += ACE_TEXT (" -i "); + directive += this->options_.http_io_; + directive += ACE_TEXT (" -t "); + directive += this->options_.http_threading_; + directive += ACE_TEXT (" -c "); + directive += this->options_.http_caching_; + directive += ACE_TEXT (" -b 50 -f THR_NEW_LWP"); + directive += ACE_TEXT ("\""); + +#if (ACE_USES_CLASSIC_SVC_CONF == 0) + directive += ACE_TEXT ("/>"); + directive += ACE_TEXT ("</dynamic>"); +#endif + + ACE_Service_Config::current ()->process_directive (directive.c_str ()); +} + +#ifndef BUILD_REPOSITORY_MANAGER_EXE +ACE_FACTORY_DEFINE (DAnCE_RepositoryManager_Module, DAnCE_RepositoryManager_Module) +#endif /*BUILD_REPOSITORY_MANAGER_EXE */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.h b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.h new file mode 100644 index 00000000000..18a149e5e21 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/Repository_Manager_Module.h @@ -0,0 +1,128 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Repository_Manager_Module.h + * + * $Id$ + * + * @Brief To start RepositoryManager by starter + * + * @author Vinzenz Tornow <vt@prismtech.com> + * @author William R. Otte <wotte@dre.vanderbilt.edu> + */ +//============================================================================= + +#ifndef NODE_MANAGER_MODULE_H +#define NODE_MANAGER_MODULE_H + +#include /**/ "ace/pre.h" + +#include "DAnCE_RepositoryManager_Module_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Service_Config.h" +#include "ace/Vector_T.h" +#include "ace/Map_Manager.h" +#include "ace/Null_Mutex.h" +#include "tao/ORB.h" +#include "tao/PortableServer/POAC.h" +#include "orbsvcs/CosNamingC.h" +#include "tao/Object_Loader.h" +#include "Deployment/DAnCE_Loader.h" +#include "DAnCE/Deployment/Deployment_common.h" + +namespace DAnCE +{ + class RepositoryManagerDaemon_i; +} + +/** + * @class Repository_Manager_Module + * + * @brief The shared object that is instantiated when the node manager + * module/library is dynamically loaded. + * + * This class runs the node manager instance + */ +class DAnCE_RepositoryManager_Module_Export DAnCE_RepositoryManager_Module + : public DAnCE::DAnCE_Object_Loader +{ + public: + struct SOptions + { + const ACE_TCHAR * domain_nc_; + const ACE_TCHAR * ior_file_; + size_t threads_; + const ACE_TCHAR * package_dir_; + const ACE_TCHAR * name_; + const ACE_TCHAR * server_address_; + + bool spawn_http_; + const ACE_TCHAR *http_port_; + const ACE_TCHAR *http_threads_; + const ACE_TCHAR *http_threading_; + const ACE_TCHAR *http_io_; + const ACE_TCHAR *http_caching_; + + SOptions() : + domain_nc_ (0), + ior_file_ (0), + threads_ (1), + package_dir_ (ACE_TEXT("RepositoryManager_Packages")), + server_address_ (0), + spawn_http_ (false), + http_port_ (ACE_TEXT("5432")), + http_threads_ (ACE_TEXT("1")), + http_threading_ (ACE_TEXT("POOL")), + http_io_ (ACE_TEXT("SYNCH")), + http_caching_ (ACE_TEXT("NO_CACHE")) + { + } + }; + + /// Constructor. + DAnCE_RepositoryManager_Module (void); + + /// Destructor. + ~DAnCE_RepositoryManager_Module (void); + + /// Overload the base class method to create a new instance + /// of a DAnCE_RepositoryManager_Module object. + virtual CORBA::Object_ptr create_object (CORBA::ORB_ptr orb, + int argc, + ACE_TCHAR *argv []); + + virtual const char * usage (void); + + virtual bool parse_args (int argc, ACE_TCHAR *argv []); + + private: + void create_poas (void); + + void spawn_http (void); + + /// Here we store the servants. + typedef ACE_Map_Manager < ACE_CString, + DAnCE::RepositoryManagerDaemon_i *, + ACE_Null_Mutex > Servant_Map; + + Servant_Map rm_map_; + + CORBA::ORB_var orb_; + CosNaming::NamingContext_var domain_nc_; + + SOptions options_; + + PortableServer::POA_var root_poa_; + PortableServer::POA_var rm_poa_; +}; + +ACE_FACTORY_DECLARE (DAnCE_RepositoryManager_Module, DAnCE_RepositoryManager_Module) + +#include /**/ "ace/post.h" + +#endif /* NODE_MANAGER_MODULE_H */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.cpp b/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.cpp new file mode 100644 index 00000000000..47cf4fbb039 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.cpp @@ -0,0 +1,101 @@ +// $Id$ + +#include "ace/Get_Opt.h" +#include "ace/ARGV.h" +#include "URL_Parser.h" + +#include "ace/ACE.h" +#include "ace/OS_NS_string.h" + +bool +URL_Parser::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("rwu:h:p:f:d")); + + bool success = true; + int c; + + while ((c = get_opt ()) != -1) + switch (c) + { + case 'd': + this->debug_ = true; + break; + case 'u': + success = parseURL (get_opt.opt_arg ()); + break; + // Usage fallthrough. + default: + success = false; + } + + if (this->hostname_ == 0 || this->filename_ == 0) + { + success = false; + } + + return success; +} + +URL_Parser::URL_Parser (void) + : hostname_ (ACE::strnew (ACE_TEXT("127.0.0.1"))), + port_ (ACE_DEFAULT_HTTP_SERVER_PORT), + filename_ (0), + debug_ (false) +{ +} + +bool URL_Parser::parseURL (ACE_TCHAR* url) +{ + ACE_TCHAR* ptr = 0; + bool success = true; + ptr = ACE_OS::strstr (url, ACE_TEXT("http://")); + if (ptr) + url += ACE_OS::strlen (ACE_TEXT("http://")); + + if (url[0] == '/') + { + this->filename_ = ACE_OS::strdup (url); + } + else + { + ptr = ACE_OS::strstr (url, ":"); + if (ptr) + this->port_ = ACE_OS::atoi (ptr + 1); + else + ptr = ACE_OS::strstr (url, "/"); + + if(!ptr) + success = false; + else + { + size_t host_len = ptr - url; + ACE::strdelete (this->hostname_); + ACE_NEW_RETURN (this->hostname_, char [host_len + 1], false); + ACE_OS::strncpy (this->hostname_, url, host_len); + this->hostname_ [host_len] = '\0'; + ptr = ACE_OS::strstr (ptr, "/"); + if (ptr) + { + this->filename_ = ACE_OS::strdup(ptr); + } + else + { + success = false; + } + } + } + return success; +} + + +void URL_Parser::Error (void) +{ + ACE_DEBUG ((LM_DEBUG, "./http_client -u http://hostname:port/filename [-d]\n")); +} + +URL_Parser::~URL_Parser() +{ + delete [] this->hostname_; + ACE_OS::free (this->filename_); +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.h b/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.h new file mode 100644 index 00000000000..16805c390b7 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/URL_Parser.h @@ -0,0 +1,66 @@ + +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file URL_Parser.h + * + * $Id$ + * + * Parses a URL into its logical chunks + * + * @author Stoyan Paunov + */ +//============================================================================= + + +#ifndef URL_PARSER_H +#define URL_PARSER_H + +#include "ace/Get_Opt.h" +#include "ace/ARGV.h" +#include "ace/Singleton.h" //for ACE_Singleton +#include "ace/Null_Mutex.h" //for ACE_Null_Mutex + +// Forward declaration +class URL_Parser; + +typedef ACE_Singleton <URL_Parser, ACE_Null_Mutex> TheURL_Parser; + +class URL_Parser +{ +public: + + friend class ACE_Singleton <URL_Parser, ACE_Null_Mutex>; + + /// Parses commandline arguments + bool parse_args (int argc, ACE_TCHAR *argv[]); + + /// Return false on failure + bool parseURL (ACE_TCHAR* url); + + void Error (void); + + /// Hostname to connect to + ACE_TCHAR *hostname_; + + /// Port number to use + u_short port_; + + /// Filename to upload/download + ACE_TCHAR *filename_; + + /// Turns on verbosity + bool debug_; + + /// destructor + ~URL_Parser (void); + +protected: + /// protected constructor, singleton + URL_Parser (void); +}; + + + +#endif /* URL_PARSER_H */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.cpp b/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.cpp new file mode 100644 index 00000000000..d5f130b828f --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.cpp @@ -0,0 +1,377 @@ + +//=============================================================================== +/** + * @file ZIP_Wrapper.cpp + * + * $Id$ + * + * Purpose: implementing the ZIP_Wrapper class + * + * @author Stoyan Paunov, Vipul Singh + * + */ +//=============================================================================== + +#include "ace/Containers_T.h" //for ACE_Double_Linked_List +#include "ace/Message_Block.h" //for ACE_Message_Block +#include "ace/OS_NS_fcntl.h" //for open +#include "ace/OS_NS_unistd.h" //for close +#include "ace/OS_NS_string.h" //for strncpy +#include "ace/SString.h" //for ACE_CString +#include "ace/OS_NS_sys_stat.h" //for stat +#include "ace/OS_NS_sys_stat.h" //for filesize and mkdir +#include "ace/OS_Memory.h" //for ACE_NEW* macros + +#include <string> +#include "minizip/unzip.h" +#define MAXFILENAME (256) +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) + +#include "ZIP_Wrapper.h" + +//ZIP_File_Info constructor +ZIP_File_Info::ZIP_File_Info (char* name, size_t size) + : name_ (name), + size_ (size), + next_ (0), + prev_ (0) +{ +} + +//ZIP_File_Info default constructor +ZIP_File_Info::ZIP_File_Info () + : name_ (""), + size_ (0), + next_ (0), + prev_ (0) +{ +} + + +/// Gets a list of the files in the archive. +int ZIP_Wrapper::file_list_info (char* zip_name, + ACE_Double_Linked_List<ZIP_File_Info> &list) +{ + unzFile uf=0; + char filename_try[MAXFILENAME+16] = ""; + if (zip_name!=0) + { + ACE_OS::strncpy(filename_try, zip_name, MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, if the string is too long. */ + filename_try[ MAXFILENAME ] = '\0'; + /* open the zip file */ + uf = unzOpen(zip_name); + /* if zipfile could not be opened, try appending .zip to name */ + if (uf==0) + { + ACE_OS::strcat(filename_try, ".zip"); + uf = unzOpen(filename_try); + } + } + /* If zipfile could not be opened still, return */ + if (uf==0) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("There is some problem in opening") + ACE_TEXT(" %s or %s.zip using unzOpen\n"), zip_name, zip_name)); + return 1; + } + unz_global_info gi; + /* get information about all the files in zip file*/ + int err = unzGetGlobalInfo(uf, &gi); + if (err!=UNZ_OK) + ACE_DEBUG((LM_DEBUG, ACE_TEXT("unzGetGlobalInfo failed while trying") + ACE_TEXT(" to get global information about zipfile\n"), err)); + /* gi.number_entry corresponds to the number of directory entries + in the zip file */ + for (uLong i=0;i<gi.number_entry;i++) + { + char filename_inzip[256]; + unz_file_info file_info; + /* get information about the current file in zip file */ + err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, + sizeof(filename_inzip), 0, 0, 0, 0); + if (err!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("unzGetCurrentFileInfo failed") + ACE_TEXT(" while trying to get information") + ACE_TEXT(" about current file\n"), err)); + break; + } + ZIP_File_Info* next = 0; + ACE_NEW_RETURN (next, ZIP_File_Info (filename_inzip, + sizeof(filename_inzip)), -1); + /* add information about current file to the list */ + list.insert_tail (next); + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT(" unzGoToNextFile failed") + ACE_TEXT(" while trying to go to next file\n"), + err)); + break; + } + } + } + unzCloseCurrentFile(uf); + return gi.number_entry; +} + + +//get file and store it into ACE message block. +bool ZIP_Wrapper::get_file (char* archive_path, char* filename, + ACE_Message_Block &file) +{ + bool return_code = true; + unzFile uf=0; + uf = unzOpen(archive_path); + /* locate the desired file in the zip file and set it as current file*/ + int j=unzLocateFile(uf, filename, 0); + if (j==UNZ_END_OF_LIST_OF_FILE) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("File not found in zip archive"))); + return false; + } + else if (j==UNZ_OK) + { + int k=unzOpenCurrentFile(uf); + if (k!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("Error in opening the current") + ACE_TEXT(" file using unzOpenCurrentFile"))); + return false; + } + else + { + int num_read = 0; + ACE_Message_Block* head = &file; + + //read the file into the ACE_Message_Block + do + { + if (head->space () == 0) + { + ACE_Message_Block* next = 0; + ACE_NEW_RETURN (next, ACE_Message_Block (BUFSIZ), false); + head->cont (); + head = head->cont (); + } + num_read = unzReadCurrentFile(archive_path, head->wr_ptr(), + head->space()); + if (num_read > 0) + head->wr_ptr (num_read); + } while (num_read > 0); + if (num_read < 0) + return_code = false; + unzCloseCurrentFile(uf); + unzClose(uf); + return return_code; + } + } + return return_code; +} + + +/// uncompress the zip file +/// The zip file will be uncompressed into a directory +/// with the name of zip archive. +/// the path is assumed to be an existing directory + +bool ZIP_Wrapper::uncompress (char* zip_archive, char* path, bool verbose) +{ + //open the zip archive + unzFile uf=0; + uf = unzOpen(zip_archive); + if (uf==0) + { + ACE_DEBUG((LM_DEBUG,ACE_TEXT("unzOpen failed to open the") + ACE_TEXT(" zipfile\n"))); + return false; + } + //get the name of the archive + ACE_CString arch_dir (path); + arch_dir += "/"; + //get only the name of the archive; remove path info + char* n = ACE_OS::strstr (zip_archive, "/"); + char* zip_name = 0; + while (n != 0) + { + zip_name = ++n; + n = ACE_OS::strstr (n, "/"); + } + arch_dir += zip_name; + //NOTE: Assumes .zip or cpk extension + arch_dir = arch_dir.substring (0, arch_dir.length () - 4); + //create directory with the name of zip archive + ACE_OS::mkdir(arch_dir.c_str()); + //if dir exists -1 is returned and ignored + unz_global_info gi; + int err = unzGetGlobalInfo(uf, &gi); + if (err!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("unzGetGlobalInfo failed to get global") + ACE_TEXT(" information about zipfile\n"), err)); + return false; + } + err =unzGoToFirstFile(uf); + if (err!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG,ACE_TEXT("error %d with zipfile in" + ACE_TEXT(" unzGoToFirstFile\n")), err)); + return false; + } + /* read each entry of zip file, create directory structure if it is + a non existing directory whereas if it is a file, write the file + at the proper path in the directory structure */ + for (uLong i=0;i<gi.number_entry;i++) + { + char filename_inzip[256]; + unz_file_info file_info; + err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, + sizeof(filename_inzip), 0, 0, 0, 0); + if (err!=UNZ_OK) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("unzGetCurrentFileInfo failed") + ACE_TEXT(" while trying to get information") + ACE_TEXT(" about currentfile\n"), err)); + break; + } + int direc = checkdir(filename_inzip); + /* If it is a directory, we create directory structure */ + if (direc==1) + { + makethedir(filename_inzip, arch_dir); + } + /* If it is a file, we read its data and write the uncompressed + data to the file with proper path.*/ + else if (direc==0) + { + handlethefile(filename_inzip, uf, file_info, verbose, arch_dir); + } + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + { + ACE_ERROR((LM_ERROR,ACE_TEXT("unzGoToNextFile failed") + ACE_TEXT(" while trying to go to") + ACE_TEXT(" nextfile\n"), err)); + break; + } + } + } + unzClose(uf); + return true; +} + + + +///try to find if it is a directory OR file +int ZIP_Wrapper::checkdir (char* filename_inzip) +{ + int direc = 0; + char* dircheck = ACE_OS::strstr (filename_inzip, "/"); + /* We assume that a directory will have its entry terminating in a / + We also assume that the directory entries in the zip file use + forward slash for both unix and windows */ + while (dircheck != 0) + { + int i = ACE_OS::strcmp(dircheck, "/"); + if (i == 0) + { + direc = 1; + break; + } + ++dircheck; + dircheck = ACE_OS::strstr (dircheck, "/"); + } + return direc; +} + +///Create directory structure if entry in zipfile is a directory +int ZIP_Wrapper::makethedir (char* filename_inzip, ACE_CString arch_dir) +{ +//let's try to create the directory structure for the package + char dir_name [2048]; + char* next = ACE_OS::strstr (filename_inzip, "/"); + while (next != 0) + { + ACE_CString location (arch_dir); + ACE_OS::strncpy (dir_name, filename_inzip, next - filename_inzip + + 1); + + dir_name[next - filename_inzip + 1] = '\0'; + location += "/"; + location += dir_name; + ACE_stat stat; + if (ACE_OS::stat (location.c_str (), &stat) == -1) + ACE_OS::mkdir (location.c_str ()); + next++; + next = ACE_OS::strstr (next, "/"); + } + return 0; +} + +///If entry in zipfile is a file, then read the file and write the +///uncompressed data at the proper filepath. +int ZIP_Wrapper::handlethefile (char* filename_inzip, unzFile uf, + unz_file_info file_info, bool verbose, + ACE_CString arch_dir) +{ + int k = unzOpenCurrentFile(uf); + if (k!=UNZ_OK) + { + ACE_ERROR((LM_ERROR,ACE_TEXT("unzOpenCurrentFile failed in" + " opening the current file"))); + return false; + } + else + { + size_t const file_size = file_info.uncompressed_size; + char* temp = 0; + ACE_NEW_RETURN (temp, char [file_size], false); + ACE_Auto_Basic_Array_Ptr<char> buffer (temp); + //read in the data + unzReadCurrentFile(uf, &(*buffer), file_size); + //close the zip handle + unzCloseCurrentFile(uf); + //create file name + path to open + std::string file_path (arch_dir.c_str ()); + //NOTE: need the c-style char to stop at '\0' + file_path += "/"; + file_path += filename_inzip; + //print out the file to be uncompressed + if (verbose) + { + ACE_OS::write(ACE_STDOUT, file_path.c_str (), + file_path.length () ); + ACE_OS::write(ACE_STDOUT, "\n", 1); + } + // Open a file handle to the local filesystem + ACE_HANDLE handle = ACE_OS::open (file_path.c_str (), + O_CREAT | O_TRUNC | O_WRONLY); + if (handle == ACE_INVALID_HANDLE) + { + unzClose(uf); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[uncompress] file creation error")), + 0); + } + //write the uncompressed data to the file + if (ACE_OS::write (handle, &(*buffer), file_size) == -1) + { + unzClose(uf); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("[uncompress] file write error")), + 0); + } + // Close the file handle + ACE_OS::close (handle); + } + return 0; +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.h b/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.h new file mode 100644 index 00000000000..cb1be6c2843 --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/ZIP_Wrapper.h @@ -0,0 +1,117 @@ + +/* -*- C++ -*- */ + +//======================================================================= +/** + * @file ZIP_Wrapper.h + * + * $Id$ + * + * Purpose: to provide a wrapper around minizip for easy handling of + * ZIP archives. This wrapper can be used as an auxiliary + * class that allows a program to become ZIP-aware + * + * @author Stoyan Paunov, Vipul Singh + * + * + */ +//======================================================================= + +#ifndef _ZIP_WRAPPER_H_ +#define _ZIP_WRAPPER_H_ + +#include "ace/Containers_T.h" //for ACE_Double_Linked_List +#include "ace/Message_Block.h" //for ACE_Message_Block +#include "ace/SString.h" //for ACE_CString +#include "ace/Log_Msg.h" +#include "ace/Synch.h" +#include "ace/OS_NS_fcntl.h" //for open +#include "ace/OS_NS_sys_stat.h" //for filesize and mkdir + +#include "minizip/unzip.h" + + +/** + * @class ZIP_File_Info + * + * This class is used as a carrier of information + * about entities residing inside a ZIP archive + */ +class ZIP_File_Info +{ +public: + ACE_CString name_; + size_t size_; + ZIP_File_Info* next_; + ZIP_File_Info* prev_; + + ZIP_File_Info (char* name, size_t size); + ZIP_File_Info (); +}; + +/** + * @class ZIP_Wrappers + * + * This class is the actual workhorse that provides all of + * the necessary functionality + */ +class ZIP_Wrapper +{ +public: + + /// Get file and store it into an ACE_Message_Block. The function + /// averts subdirectory traversal problems. + /// NOTE: Be sure to release the message block even if the function returns + /// false becuase the return value might be due to unsuccessful allocation + + ///archive_path is the zip archive with the path + ///filename is the name of the file to be looked for in the zip archive. + ///the file is stored in ACE message block. + static bool get_file (char* archive_path, char* filename, + ACE_Message_Block &file); + + /// uncompress the zip file + /// The zip file will be uncompressed into a directory with the + ///name of zip archive. + /// The path is assumed to be an existing directory + + ///zip_archive is the arcive to be uncompressed with full path. + ///path is used for creating a directory with the name of zip archive. + static bool uncompress (char* zip_archive, char* path = 0, + bool verbose = true); + + /// Get a list of the files in the archive + + ///zip_name is the name of zipfile with fullpath. + ///list stores information about each entry in zip file. + static int file_list_info (char* zip_name, + ACE_Double_Linked_List<ZIP_File_Info> &list); + + ///Check if an entry of a zip file is a file or directory + ///We assume a directoryname terminates with a forward slash + ///Returns 1 for directory while 0 for file. + + ///filename_inzip is an entry in a zipfile + static int checkdir (char* filename_inzip); + + ///Create directory structure if entry in zipfile is a directory + + ///filename_inzip is an entry in a zipfile + ///arch_dir stores the name of the directory to be created + static int makethedir (char* filename_inzip, ACE_CString arch_dir); + + ///If entry in zipfile is a file, then read the file and write + /// the uncompressed data at the proper filepath. + + ///filename_inzip is an entry in a zipfile + ///uf refers to the zip archive + ///file_info is used to get information about current file + ///verbose decides if the details are to be printed or not + ///arch_dir is the name of file with full path where it is to be + ///uncompressed + static int handlethefile (char* filename_inzip, unzFile uf, + unz_file_info file_info, + bool verbose, ACE_CString arch_dir); +}; + +#endif diff --git a/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.cpp b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.cpp new file mode 100644 index 00000000000..1ad95d626eb --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.cpp @@ -0,0 +1,241 @@ +// $Id$ +#include "repository_manager_admin.h" +#include "DAnCE/Logger/Log_Macros.h" +#include "RepositoryManagerDaemonC.h" + +namespace DAnCE +{ + namespace RepositoryManager + { + Admin::Admin (Deployment::RepositoryManager_ptr rm) + : rm_ (Deployment::RepositoryManager::_duplicate (rm)) + { + DANCE_TRACE ("Admin::Admin"); + } + + + /// Install a package at a provided filesystem path. + bool + Admin::install_package (const ACE_TCHAR *uri, + const ACE_TCHAR *name, + bool replace) + { + DANCE_TRACE ("Admin::install_package"); + + try + { + DANCE_DEBUG ((LM_TRACE, DLINFO "Admin::install_package - " + "Installing package with URI: %C, name: %C\n", + uri, name)); + this->rm_->installPackage (ACE_TEXT_ALWAYS_CHAR (name), + ACE_TEXT_ALWAYS_CHAR (uri), + replace); + DANCE_DEBUG ((LM_TRACE, DLINFO "Admin::install_package - " + "Package installed successfully\n")); + } + catch (Deployment::NameExists &) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::install_package - " + "Package with name %C already installed.\n", + name)); + return false; + } + catch (Deployment::PackageError &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::install_package - " + "Internal error while installing package with name %C: %C - %C\n", + name, ex.source.in (), ex.reason.in ())); + return false; + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::install_package - " + "Unexpected CORBA Exception while installing package with name: %C. Reason: %C\n", + name, + ex._info ().c_str ())); + return false; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::install_package - " + "Unexpected C++ exception while installing package with name: %C\n", + name)); + return false; + } + + return true; + } + + /// Create new package. + bool + Admin::create_package (const ACE_TCHAR * /* pc_path */, + const ACE_TCHAR * /** name*/, + const ACE_TCHAR * /*baselocation*/, + bool /*replace*/) + { + DANCE_TRACE ("Admin::create_package"); + + return false; + } + + /// Uninstall a package with a provided UUID. + /// Fails if the NoSuchName exception was raised. + bool + Admin::uninstall_package (const ACE_TCHAR *uuid) + { + DANCE_TRACE ("Admin::uninstall_package"); + + try + { + DANCE_DEBUG ((LM_TRACE, DLINFO "Admin::uninstall_package - " + "Attempting to uninstall package %s\n", + uuid)); + this->rm_->deletePackage (ACE_TEXT_ALWAYS_CHAR (uuid)); + DANCE_DEBUG ((LM_INFO, DLINFO "Admin::uninstall_package - " + "Successfully uninstalled package %s\n", + uuid)); + } + catch (Deployment::NoSuchName &) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::uninstall_package - " + "No package with the given UUID found: %C\n", + uuid)); + return false; + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::uninstall_package - " + "Unexpected CORBA Exception while uninstalling package with uuid: %C. Reason: %C\n", + uuid, + ex._info ().c_str ())); + return false; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::uninstall_package - " + "Unexpected C++ exception while installing package with uuid: %C\n", + uuid)); + return false; + } + + return true; + } + + /// List all installed packages + ::CORBA::StringSeq * + Admin::list_packages (void) + { + DANCE_TRACE ("Admin::list_packages"); + + try + { + CORBA::StringSeq_var packages = this->rm_->getAllNames (); + return packages._retn (); + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::list_packages - " + "Unexpected CORBA Exception while listing packages: %C\n", + ex._info ().c_str ())); + return 0; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::list_package - " + "Unexpected C++ exception while listing packages\n")); + return 0; + } + + return 0; + } + + /// List all installed package types + ::CORBA::StringSeq * + Admin::list_types (void) + { + DANCE_TRACE ("Admin::list_types"); + + try + { + CORBA::StringSeq_var packages = this->rm_->getAllTypes (); + return packages._retn (); + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::list_types - " + "Unexpected CORBA Exception while listing package types: %C\n", + ex._info ().c_str ())); + return 0; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::list_types - " + "Unexpected C++ exception while listing package types\n")); + return 0; + } + + return 0; + } + + /// Find package names by type + ::CORBA::StringSeq * + Admin::find_by_type (const ACE_TCHAR *type) + { + DANCE_TRACE ("Admin::find_by_type"); + + if (type == 0) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::find_by_type - " + "Nill type passed to find_by_type\n")); + return 0; + } + + try + { + ::CORBA::StringSeq_var types = this->rm_->findNamesByType (ACE_TEXT_ALWAYS_CHAR (type)); + types._retn (); + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::find_by_type - " + "Unexpected CORBA Exception while listing packages of type %C: %C\n", + type, + ex._info ().c_str ())); + return 0; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::find_by_type - " + "Unexpected C++ exception while listing packages by type %C\n", + type)); + return 0; + } + + return 0; + } + + /// Attempt to shutdown the server. + bool + Admin::shutdown (void) + { + DANCE_TRACE ("Admin::shutdown"); + + DANCE_DEBUG ((LM_TRACE, DLINFO "Admin::shutdown - " + "Attempting to shut down Repository Manager\n")); + CIAO::RepositoryManagerDaemon_var rmd = + CIAO::RepositoryManagerDaemon::_narrow (this->rm_.in ()); + DANCE_DEBUG ((LM_INFO, DLINFO "Admin::shutdown - " + "Repository Manager shut down.\n")); + if (CORBA::is_nil (rmd.in ())) + { + DANCE_ERROR ((LM_ERROR, DLINFO "Admin::shutdown - " + "Unable to narrow provided RM reference to a CIAO::RepositoryManagerDaemon\n")); + return false; + } + + rmd->shutdown (); + + return true; + } + } +} diff --git a/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.h b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.h new file mode 100644 index 00000000000..867b4b0a18a --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin.h @@ -0,0 +1,68 @@ + +// $Id$ + +/** + * @file repository_manager_admin.h + * @author William R. Otte <wotte@dre.vanderbilt.edu>? + * + * Class which implements most repository admin functions. + */ + +#ifndef REPOSITORY_MANAGER_ADMIN_H_ +#define REPOSITORY_MANAGER_ADMIN_H_ + +#include /**/ "ace/pre.h" +#include "Deployment/Deployment_RepositoryManagerC.h" + +#include "Repository_Manager_Admin_Export.h" + +namespace DAnCE +{ + namespace RepositoryManager + { + /** + * @class Admin + * @brief Implements administrative functions for the Repository Manager. + */ + class DAnCE_RepositoryManager_Admin_Export Admin + { + public: + Admin (Deployment::RepositoryManager_ptr rm); + + /// Install a package at a provided filesystem path. + bool install_package (const ACE_TCHAR *uri, + const ACE_TCHAR *name, + bool replace); + + /// Create new package. + bool create_package (const ACE_TCHAR *pc_path, + const ACE_TCHAR *name, + const ACE_TCHAR *baselocation, + bool replace); + + /// Uninstall a package with a provided UUID. + /// Fails if the NoSuchName exception was raised. + bool uninstall_package (const ACE_TCHAR *uuid); + + /// List all installed packages + ::CORBA::StringSeq * list_packages (void); + + /// List all installed package types + ::CORBA::StringSeq * list_types (void); + + /// Find package names by type + ::CORBA::StringSeq * find_by_type (const ACE_TCHAR *type); + + /// Attempt to shutdown the server. + bool shutdown (void); + + private: + Deployment::RepositoryManager_var rm_; + + }; + } +} + +#include /**/ "ace/post.h" + +#endif /* REPOSITORY_MANAGER_ADMIN_H_ */ diff --git a/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin_exec.cpp b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin_exec.cpp new file mode 100644 index 00000000000..f348ade098e --- /dev/null +++ b/modules/CIAO/DAnCE/RepositoryManager/repository_manager_admin_exec.cpp @@ -0,0 +1,466 @@ +// $Id$ + +/** + * @file repository_manager_admin_exec.cpp + * @author William R. Otte <wotte@dre.vanderbilt.edu> + * + * Simple administration program for the Repository Manager. + */ + +#include "ace/Auto_Ptr.h" +#include "ace/Get_Opt.h" +#include "ace/Unbounded_Set.h" +#include "ace/String_Base.h" +#include "DAnCE/Logger/Log_Macros.h" +#include "DAnCE/Logger/Logger_Service.h" +#include "Deployment/Deployment_RepositoryManagerC.h" + +#include "repository_manager_admin.h" + +struct Options +{ + Options (void) + : rm_ior_ (""), + domain_nc_ (""), + list_ (false), + shutdown_ (false) + { + } + + struct Installation + { + Installation (void) + { + } + + bool init (const ACE_TCHAR *inst) + { + ACE_CString tmp (inst); + + size_t begin = 0; + size_t pos = tmp.find (',', begin); + + if (pos != ACE_CString::npos) + path_ = tmp.substring (begin, pos - begin); + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Installation::init - " + "Installation directive missing name and replace parameters, " + "must have form path,name,replace\n")); + return false; + } + + + begin = pos + 1; + pos = tmp.find (',', begin); + + if (pos != ACE_CString::npos) + name_ = tmp.substring (begin, pos - begin); + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Installation::init - " + "Installation directive mssing replace parameter, " + "must have form path,name,replace\n")); + return false; + } + + begin = pos + 1; + + if (tmp[begin] == '0') replace_ = false; + else if (tmp[begin] == '1') replace_ = true; + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Installation::init - " + "Replace directive muse be 1 or 0.\n")); + return false; + } + + return true; + } + + bool operator== (const Installation &rhs) const + { + return (replace_ == rhs.replace_) && + (path_ == rhs.path_) && + (name_ == rhs.name_); + } + + ACE_CString path_, name_; + bool replace_; + }; + + struct Creation + { + Creation (void) + { + } + + bool init (const ACE_TCHAR *inst) + { + ACE_CString tmp (inst); + + size_t begin = 0; + size_t pos = tmp.find (',', begin); + + if (pos != ACE_CString::npos) + path_ = tmp.substring (begin, pos - begin); + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Creation::init - " + "Creation directive missing name, base location, and replace parameters, " + "must have form path,name,base,replace\n")); + return false; + } + + + begin = pos + 1; + pos = tmp.find (',', begin); + + if (pos != ACE_CString::npos) + name_ = tmp.substring (begin, pos - begin); + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Creation::init - " + "Creation directive mssing base location and replace parameter, " + "must have form path,name,base,replace\n")); + return false; + } + + begin = pos + 1; + pos = tmp.find (',', begin); + + if (pos != ACE_CString::npos) + base_location_ = tmp.substring (begin, pos - begin); + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Creation::init - " + "Creation directive mssing replace parameter, " + "must have form path,name,base,replace\n")); + return false; + } + + begin = pos + 1; + + if (tmp[begin] == '0') replace_ = false; + else if (tmp[begin] == '1') replace_ = true; + else + { + ACE_ERROR ((LM_ERROR, DLINFO "Options::Creation::init - " + "Replace directive muse be 1 or 0.\n")); + return false; + } + + return true; + } + + bool operator== (const Creation &rhs) const + { + return (replace_ == rhs.replace_) && + (path_ == rhs.path_) && + (name_ == rhs.name_); + } + + ACE_CString path_, name_, base_location_; + bool replace_; + }; + + const ACE_TCHAR *rm_ior_; + const ACE_TCHAR *domain_nc_; + ACE_Unbounded_Set< Installation > install_; + ACE_Unbounded_Set< Creation > create_; + ACE_Unbounded_Set< ACE_CString > uninstall_; + bool list_; + bool shutdown_; + + void usage (void) + { + ACE_ERROR ((LM_EMERGENCY, "usage:\n" + "\t-h,--help\t\t\tThis message.\n" + "\t-r,--rm-ior <ior>\t\tIOR where the RM instance may be found\n" + "\t-i,--install <path>,<name>,<1|0>\tInstall package found at <path> into the RM, with <name>,\n" + "\t\t\t<1> replacing or <0> not replacing an existing package. *\n" + "\t-c,--create <path>,<name>,<base location>,<1|0>\tInstall package found at <path> into the RM, with <name>,\n" + "\t\t\t<base location>, <1> replacing or <0> not replacing an existing package. *\n" + "\t-u,--uninstall <uuid>\t\tUninstall package identified by UUID. *\n" + "\t-l,--list\t\t\tList all packages installed in the RM\n" + "\t-s,--shutdown\t\t\tShutdown the RM.\n" + "\t-d,--domain-nc <ior>\t\tProvide a reference to the domain naming context\n" + + "\n\n\tArguments with a * may be specified multiple times.\n")); + } + + + int parse_args (int argc, ACE_TCHAR *argv[]) + { + ACE_Get_Opt get_opt (argc, argv, + ACE_TEXT ("hr:i:c:u:lsd:"), + 0, 0, + ACE_Get_Opt::RETURN_IN_ORDER, + 1); + + get_opt.long_option (ACE_TEXT("help"), 'h', ACE_Get_Opt::NO_ARG); + get_opt.long_option (ACE_TEXT("rm-ior"), 'r', ACE_Get_Opt::ARG_REQUIRED); + get_opt.long_option (ACE_TEXT("install"), 'i', ACE_Get_Opt::ARG_REQUIRED); + get_opt.long_option (ACE_TEXT("create"), 'c', ACE_Get_Opt::ARG_REQUIRED); + get_opt.long_option (ACE_TEXT("uninstall"), 'u', ACE_Get_Opt::ARG_REQUIRED); + get_opt.long_option (ACE_TEXT("list"), 'l', ACE_Get_Opt::NO_ARG); + get_opt.long_option (ACE_TEXT("shutdown"), 's', ACE_Get_Opt::NO_ARG); + get_opt.long_option (ACE_TEXT("domain-nc"), 'd', ACE_Get_Opt::ARG_REQUIRED); + + char c; + Installation inst; + Creation create; + + while ((c = get_opt ()) != -1) + { + switch (c) + { + case 'h': + this->usage (); + return 1; + break; + + case 'r': + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Using provided RM IOR: %C\n", + get_opt.opt_arg ())); + rm_ior_ = get_opt.opt_arg (); + break; + + case 'i': + if (!inst.init (get_opt.opt_arg ())) + { + this->usage (); + return -1; + } + + if (inst.replace_) + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Replacing installed package from path %C with name %C.\n", inst.path_.c_str (), + inst.name_.c_str ())); + else + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Installing package from path %C with name %C.\n", inst.path_.c_str (), + inst.name_.c_str ())); + + this->install_.insert (inst); + break; + + case 'c': + if (!create.init (get_opt.opt_arg ())) + { + this->usage (); + return -1; + } + + if (create.replace_) + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Replacing installed package from path %C with name %C and base location %C.\n", + create.path_.c_str (), + create.name_.c_str (), + create.base_location_.c_str ())); + else + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Installing new package from path %C with name %C and base location %C.\n", + create.path_.c_str (), + create.name_.c_str (), + create.base_location_.c_str ())); + + this->create_.insert (create); + break; + + case 'u': + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Removing package with UUID %C\n", get_opt.opt_arg ())); + this->uninstall_.insert (get_opt.opt_arg ()); + break; + + case 'l': + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Listing all packages.\n")); + this->list_ = true; + break; + + case 's': + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Shutting down the RM instance.\n")); + this->shutdown_ = true; + break; + + case 'd': + DANCE_DEBUG ((LM_DEBUG, DLINFO "Options::parse_args - " + "Using provided Domain NC: %C\n", + get_opt.opt_arg ())); + domain_nc_ = get_opt.opt_arg (); + + case 0: + if (ACE_OS::strcmp (get_opt.long_option (), ACE_TEXT ("domain-nc")) == 0) + { + } + else + { + DANCE_ERROR ((LM_ERROR, DLINFO "Options::parse_args - " + "Unknown long option: %C\n", + get_opt.long_option ())); + this->usage (); + return -1; + } + } + } + return 0; + } +}; + +int ACE_TMAIN (int argc, ACE_TCHAR **argv) +{ + DANCE_DISABLE_TRACE (); + + auto_ptr<DAnCE::Logger_Service> logger; + + int retval (0); + + try + { + DAnCE::Logger_Service + * dlf = ACE_Dynamic_Service<DAnCE::Logger_Service>::instance ("DAnCE_Logger_Backend_Factory"); + + if (!dlf) + { + dlf = new DAnCE::Logger_Service; + logger.reset (dlf); + } + + dlf->init (argc, argv); + + DANCE_DEBUG ((LM_TRACE, DLINFO + "Module_main.h - initializing ORB\n")); + + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); + + ACE_Log_Msg_Backend * backend = dlf->get_logger_backend(orb); + + if (backend != 0) + { + backend->open(0); + ACE_Log_Msg::msg_backend (backend); + ACE_Log_Msg * ace = ACE_Log_Msg::instance(); + ace->clr_flags(ace->flags()); + ace->set_flags(ACE_Log_Msg::CUSTOM); + } + + Options options; + int error = options.parse_args (argc, argv); + if (error == -1) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "Failed to parse command line arguments.\n")); + } + else if (error == 1) + { //help was issued -> quit + return 0; + } + + if (options.rm_ior_ == 0) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "No RepositoryManager IOR provided\n")); + return -1; + } + + // Resolve the RepositoryManager reference + CORBA::Object_var obj = orb->string_to_object (options.rm_ior_); + + Deployment::RepositoryManager_var rm = + Deployment::RepositoryManager::_narrow (obj); + + if (CORBA::is_nil (obj)) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "Provided IOR was invalid or could not be narrowed: %s\n", + options.rm_ior_)); + return -1; + } + + DAnCE::RepositoryManager::Admin admin (rm.in ()); + + ACE_Unbounded_Set_Iterator<Options::Installation> inst_it = + options.install_.begin (); + Options::Installation *inst (0); + + while (inst_it.next (inst) == 1) + { + if (!admin.install_package (inst->path_.c_str (), + inst->name_.c_str (), + inst->replace_)) + retval = -1; + inst_it.advance (); + } + + ACE_Unbounded_Set_Iterator<Options::Creation> creat_it (options.create_); + Options::Creation *creat (0); + + while (creat_it.next (creat) == 1) + { + if (!admin.create_package (creat->path_.c_str (), + creat->name_.c_str (), + creat->base_location_.c_str (), + creat->replace_)) + retval = -1; + creat_it.advance (); + } + + ACE_Unbounded_Set_Iterator<ACE_CString> uninst_it (options.uninstall_); + ACE_CString *uninst = 0; + + while (uninst_it.next (uninst) == 1) + { + if (!admin.uninstall_package (uninst->c_str ())) + retval = -1; + uninst_it.advance (); + } + + if (options.list_) + { + ::CORBA::StringSeq * packages = admin.list_packages (); + if (packages == 0) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "No packages returned from list_packages\n")); + retval = -1; + } + + DANCE_DEBUG ((LM_EMERGENCY, "Listing %u packages installed on server:\n")); + + for (CORBA::ULong i = 0; i < packages->length (); ++i) + { + DANCE_DEBUG ((LM_EMERGENCY, "\t%s\n", + (*packages)[i].in ())); + } + + delete packages; + } + + if (options.shutdown_) + { + DANCE_DEBUG ((LM_EMERGENCY, "Shutting down the Repository Manager\n")); + if (!admin.shutdown ()) + retval = -1; + } + } + catch (CORBA::Exception &ex) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "Caught unexpected CORBA Exception: %s\n", + ex._info ().c_str ())); + return -1; + } + catch (...) + { + DANCE_ERROR ((LM_ERROR, DLINFO "repository_manager_admin_exec::main - " + "Caught unexpected C++ exception.\n")); + return -1; + } + + return 0; +} + |