/**************************************************************************** Copyright 2004, Virginia Polytechnic Institute and State University This file is part of the OSSIE Core Framework. OSSIE Core Framework is free software; you can redistribute it and/or modify it under the terms of the Lesser GNU General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. OSSIE Core Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public License for more details. You should have received a copy of the Lesser GNU General Public License along with OSSIE Core Framework; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ****************************************************************************/ #include #ifdef MS_dotNET #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "ossie/ApplicationFactory_impl.h" using namespace std; ApplicationFactory_impl::ComponentInfo::ComponentInfo () { implId = NULL; localFileName = NULL; entryPoint = NULL; name = NULL; } ApplicationFactory_impl::ComponentInfo:: ComponentInfo ( const ComponentInfo & ComponentInfoCopy ) { // populate object with the component information this->name = new char[ strlen ( ComponentInfoCopy.name ) + 1 ]; strcpy ( this->name, ComponentInfoCopy.name ); this->implId = new char[ strlen ( ComponentInfoCopy.implId ) + 1 ]; strcpy ( this->implId, ComponentInfoCopy.implId ); this->codeType = ComponentInfoCopy.codeType; this->localFileName = new char[ strlen ( ComponentInfoCopy.localFileName ) + 1 ]; strcpy ( this->localFileName, ComponentInfoCopy.localFileName ); this->entryPoint = new char[ strlen ( ComponentInfoCopy.entryPoint ) + 1 ]; strcpy ( this->entryPoint, ComponentInfoCopy.entryPoint ); for ( unsigned int i = 0; i < ComponentInfoCopy.usesDevices->size (); i++ ) this->usesDevices->push_back ( ( *ComponentInfoCopy.usesDevices ) [ i ] ); this->allocationCapacities = ComponentInfoCopy.allocationCapacities; this->execParameters = ComponentInfoCopy.execParameters; this->factoryParameters = ComponentInfoCopy.factoryParameters; this->configureProperties = ComponentInfoCopy.configureProperties; this->options = ComponentInfoCopy.options; } ApplicationFactory_impl::ApplicationFactory_impl ( const char *_softProfile ) { // population application factory with the appropriate information this->_softwareProfile = new char[ strlen ( _softProfile ) + 1 ]; strcpy ( this->_softwareProfile, _softProfile ); this->_sadParser = new SADParser ( _softwareProfile ); this->_name = new char[ strlen ( _sadParser->getName () ) + 1 ]; strcpy ( this->_name, _sadParser->getName () ); this->_identifier = new char[ strlen ( _sadParser->getID () ) + 1 ]; strcpy ( this->_identifier, _sadParser->getID () ); //Get reference to DomainManager (to register w/event channel) CORBAOBJ obj = _orb.lookup ( "/DomainName1/DomainManager" ); dmnMgr = CF::DomainManager::_narrow ( obj ); ApplicationFactoryEventHandler *_evtHandler = new ApplicationFactoryEventHandler ( this ); dmnMgr->registerWithEventChannel ( _evtHandler->_this (), CORBA::string_dup ( _identifier ), CORBA::string_dup ( "ODM_Channel" ) ); }; CF::Application_ptr ApplicationFactory_impl::create ( const char *name, const CF::Properties & initConfiguration, const CF::DeviceAssignmentSequence & deviceAssignments ) throw ( CORBA::SystemException, CF::ApplicationFactory::CreateApplicationError, CF::ApplicationFactory::CreateApplicationRequestError, CF::ApplicationFactory::InvalidInitConfiguration ) { cout << "entering appFactory->create" << endl; std::vector * ComponentsVector = _sadParser->getComponents(); //Get SPD file names from SAD: //Makes list of SPD files. std::vector SPDList; { // this is here because Microsoft does not believe in following standards for ( unsigned int i = 0; i < ComponentsVector->size(); i++ ) { SPDList.push_back( ( *ComponentsVector ) [ i ] ->getSPDFile() ); } } // initialize DeviceLoadInfoVector while ( DeviceLoadInfoVector.size() != 0 ) { DeviceLoadInfoVector.pop_back(); } verifyDeviceAssignments( SPDList, deviceAssignments ); // allocate space for device assignment // (assume maximum length of 10 - will make dynamic in later version) CF::DeviceAssignmentSequence* _availableDevs = new CF::DeviceAssignmentSequence( deviceAssignments ); //_availableDevs->length (0); PROC_ID_SEQ* _pidSeq = new PROC_ID_SEQ ( 30 ); _pidSeq->length ( 0 ); //get a sequence of registeredDeviceManagers CF::DomainManager::DeviceManagerSequence * devMgrs; devMgrs = dmnMgr->deviceManagers (); bool requestedDeviceFound = false; CF::DeviceSequence * rgstdDevices; for ( unsigned int componentIndex = 0; componentIndex < DeviceLoadInfoVector.size (); componentIndex++ ) { //get the intended assignedDeviceId from deviceAssignments int assignmentIndex = 0; while ( strcmp( DeviceLoadInfoVector[ componentIndex ] ->name, deviceAssignments[ assignmentIndex ].componentId ) != 0 ) { assignmentIndex++; } //search in all deviceManagers for intended device for ( unsigned int devMgrIndex = 0; devMgrIndex < devMgrs->length (); devMgrIndex++ ) { //get all devices registered in this device Manager rgstdDevices = ( *devMgrs ) [ devMgrIndex ] ->registeredDevices (); for ( unsigned int deviceIndex = 0; deviceIndex < rgstdDevices->length (); deviceIndex++ ) { //find a match for the intended device if ( strcmp( ( *rgstdDevices ) [ deviceIndex ] ->label (), deviceAssignments[ assignmentIndex ].assignedDeviceId ) == 0 ) { requestedDeviceFound = true; cout << "the host is " << ( *rgstdDevices ) [ deviceIndex ] ->label () << endl; //printf("the host is: %s\n", (*rgstdDevices)[deviceIndex]->label ()); //now we have a pointer to the required device //Get allocation properties //allocate ( *rgstdDevices ) [ deviceIndex ] -> allocateCapacity ( DeviceLoadInfoVector[ componentIndex ] -> allocationCapacities ); //Get file name //load if it is not empty if ( strcmp ( DeviceLoadInfoVector[ componentIndex ] ->localFileName, "" ) != 0 ) { //load it //TODO: Validate that the intended device supports the // LoadableDevice interface cout << "loading " << DeviceLoadInfoVector[ componentIndex ] ->localFileName << endl; //printf("loading -> %s\n",DeviceLoadInfoVector[componentIndex]->localFileName); CF::LoadableDevice_var loadDev = CF::LoadableDevice::_narrow ( ( *rgstdDevices ) [ deviceIndex ] ); loadDev->load ( ( *devMgrs ) [ devMgrIndex ] ->fileSys (), DeviceLoadInfoVector[ componentIndex ] ->localFileName, DeviceLoadInfoVector[ componentIndex ] ->codeType ); //execute when necesary // if(DeviceLoadInfoVector[componentIndex]->codeType == CF::LoadableDevice::LoadType::EXECUTABLE || if ( DeviceLoadInfoVector[ componentIndex ] ->codeType == CF::LoadableDevice::EXECUTABLE || DeviceLoadInfoVector[ componentIndex ] ->codeType == CF::LoadableDevice::SHARED_LIBRARY && strcmp ( DeviceLoadInfoVector[ componentIndex ] -> entryPoint, "" ) != 0 ) { //execute //TODO: Validate that the intended device supports // the LoadableDevice interface cout << "executing-> " << DeviceLoadInfoVector[ componentIndex ] ->localFileName << endl; //printf("executing-> %s\n",DeviceLoadInfoVector[componentIndex]->localFileName); CF::ExecutableDevice_var execDev = CF::ExecutableDevice:: _narrow ( ( *rgstdDevices ) [ deviceIndex ] ); CF::ExecutableDevice:: ProcessID_Type tempPid = execDev-> execute ( DeviceLoadInfoVector[ componentIndex ] -> localFileName, DeviceLoadInfoVector[ componentIndex ] ->options, DeviceLoadInfoVector[ componentIndex ] -> execParameters ); if ( tempPid < 0 ) { //throw exception here } else { _pidSeq->length ( _pidSeq->length() + 1 ); ( * _pidSeq ) [ _pidSeq->length() - 1 ].processId = tempPid; ( * _pidSeq ) [ _pidSeq->length() - 1 ].componentId = strdup( deviceAssignments[ assignmentIndex ].componentId ); } //execDev->execute( LoadInfoVector[componentIndex]->entryPoint, LoadInfoVector[componentIndex]->options, LoadInfoVector[componentIndex]->parameters ); //NOTE: The PID returned by execute is not handled //An exception shall be thrown when PID = -1 } } } } } } CF::Resource_ptr _assemblyController; ELEM_SEQ* _namingCtxSeq = new ELEM_SEQ (); _namingCtxSeq->length ( ComponentsVector->size () ); ELEM_SEQ* _implSeq = new ELEM_SEQ (); _implSeq->length ( ComponentsVector->size () ); std::vector _resourceVector; SADComponentInstantiation* _assemblyControllerProfile = _sadParser->getAssemblyController (); int vector_access = 0; { // this is here because Microsoft does not believe in following standards // install the different components in the system for ( unsigned int i = 0; i < ComponentsVector->size (); i++ ) { std::vector * ComponentInstantiationVector = ( *ComponentsVector ) [ i ] ->getSADInstantiations (); // dbl chk for mem leaks SPDParser _spdParser ( SPDList[ i ] ); // dbl chk for mem leaks, also SCDParser _scdParser ( _spdParser.getSCDFile () ); if ( !_scdParser.isResource () ) { // this makes sure that the resource factory // is not handled like a resource continue; } ( *_namingCtxSeq ) [ i ].componentId = CORBA::string_dup ( ( *ComponentInstantiationVector ) [ 0 ] ->getID () ); ( *_implSeq ) [ i ].componentId = CORBA::string_dup ( ( *ComponentInstantiationVector ) [ 0 ] ->getID () ); // assuming 1 instantiation for each componentplacement if ( ( *ComponentInstantiationVector ) [ 0 ] ->isNamingService () ) { // this is for the naming-service based configuration // it assumes that the component already exists (like a device) char * _lookupName = ( *ComponentInstantiationVector ) [ 0 ] -> getFindByNamingServiceName (); ( *_namingCtxSeq ) [ i ].elementId = CORBA::string_dup ( _lookupName ); CORBAOBJ _obj; do { #ifdef HAVE_UNISTD_H // todo Must be a better way sleep( 1 ); #else Sleep( 1000 ); #endif _obj = _orb.lookup ( _lookupName ); } /* * What does this do? -TT */ while ( CORBA::is_nil ( _obj ) ); // check to see if the resource is the assembly controller // either way, the resource is initialized and configured if ( _assemblyControllerProfile == ( *ComponentInstantiationVector ) [ 0 ] ) { _assemblyController = CF::Resource::_narrow ( _obj ); _assemblyController->initialize (); _assemblyController->configure ( initConfiguration ); _assemblyController->configure ( DeviceLoadInfoVector[ i ] -> configureProperties ); } else { if ( _scdParser.isResource () && _scdParser.isConfigurable () ) { CF::Resource_ptr _rsc = CF::Resource::_narrow ( _obj ); _rsc->initialize (); _rsc->configure ( DeviceLoadInfoVector[ i ] ->configureProperties ); _resourceVector.push_back ( CF::Resource::_duplicate ( _rsc ) ); } } } else if ( ( *ComponentInstantiationVector ) [ 0 ] ->isResourceFactoryRef () ) { // resource-factory based component instantiation SADComponentInstantiation * _resourceFacInstantiation = NULL; int tmpCnt = 0; // figure out which resource factory is used while ( _resourceFacInstantiation == NULL ) { _resourceFacInstantiation = ( *ComponentsVector ) [ tmpCnt ] -> getSADInstantiationById ( ( *ComponentInstantiationVector ) [ 0 ] ->getResourceFactoryRefId () ); tmpCnt++; } ( *_namingCtxSeq ) [ i ].elementId = CORBA::string_dup ( _resourceFacInstantiation-> getFindByNamingServiceName () ); CORBAOBJ _obj = _orb.lookup ( _resourceFacInstantiation-> getFindByNamingServiceName () ); CF::ResourceFactory_ptr _resourceFactory = CF::ResourceFactory::_narrow ( _obj ); // configure factory /*std::vector < InstantiationProperty * >*_factoryInstantiationProps = (*ComponentInstantiationVector)[0]->getFactoryProperties (); CF::Properties _factoryProperties (_factoryInstantiationProps-> size ()); for (unsigned int j = 0; j < _factoryInstantiationProps->size (); j++) { _factoryProperties[j].id = CORBA::string_dup ((*_factoryInstantiationProps)[j]-> getID ()); _factoryProperties[j]. value <<= CORBA:: string_dup ((*_factoryInstantiationProps)[j]->getValue ()); }*/ // unused PJB char *value = LoadInfoVector[vector_access]->name; // instantiate resource // (mechanism for this is left up to the factory's implementation) CF::Resource_ptr _resourceCreated = _resourceFactory-> createResource ( LoadInfoVector[ vector_access ] ->name, LoadInfoVector[ vector_access ] ->factoryParameters ); if ( CORBA::is_nil ( _resourceCreated ) ) throw CF::ApplicationFactory::CreateApplicationError (); // check to see if the resource is the assembly controller // either way, the resource is initialized and configured if ( strcmp ( _assemblyControllerProfile->getID (), ( *ComponentInstantiationVector ) [ 0 ] ->getID () ) == 0 ) { _assemblyController = _resourceCreated; _assemblyController->initialize (); _assemblyController->configure ( initConfiguration ); _assemblyController-> configure ( LoadInfoVector[ vector_access ] ->configureProperties ); } else { _resourceCreated->initialize (); _resourceCreated-> configure ( LoadInfoVector[ vector_access ] ->configureProperties ); _resourceVector.push_back ( _resourceCreated ); } vector_access++; } else { char* _id, *_usagename; _id = LoadInfoVector[ i ] ->implId; _usagename = LoadInfoVector[ i ] ->name; char* _lookup = new char[ strlen ( _usagename ) + strlen ( _id ) + 1 ]; strcpy ( _lookup, _usagename ); strcat ( _lookup, "_" ); strcat ( _lookup, _id ); ( *_namingCtxSeq ) [ i ].elementId = CORBA::string_dup ( _lookup ); CORBAOBJ _obj = _orb.lookup ( _lookup ); if ( _assemblyControllerProfile == ( *ComponentInstantiationVector ) [ 0 ] ) { _assemblyController = CF::Resource::_narrow ( _obj ); _assemblyController->initialize (); _assemblyController->configure ( initConfiguration ); _assemblyController->configure ( LoadInfoVector[ i ] -> configureProperties ); } else { CF::Resource_ptr _rsc = CF::Resource::_narrow ( _obj ); _rsc->initialize (); _rsc->configure ( LoadInfoVector[ i ] ->configureProperties ); _resourceVector.push_back ( _rsc ); } delete _lookup; _lookup = NULL; } } // end for() } std::vector < Connection * >*_connection = _sadParser->getConnections (); // create all resource connections for ( int _numConnections = _connection->size () - 1; _numConnections >= 0; _numConnections-- ) { UsesPort* _usesPortParser = ( *_connection ) [ _numConnections ] ->getUsesPort (); FindBy* _findUsesPortBy = _usesPortParser->getFindBy (); ProvidesPort* _providesPortParser = NULL; FindBy* _findProvidesPortBy = NULL; if ( ( *_connection ) [ _numConnections ] ->isProvidesPort () ) _providesPortParser = ( *_connection ) [ _numConnections ] ->getProvidesPort (); else if ( ( *_connection ) [ _numConnections ] ->isFindBy () ) _findProvidesPortBy = ( *_connection ) [ _numConnections ] ->getFindBy (); else { //throw an exception? } CORBAOBJ _usesObj; CORBAOBJ _providesObj; if ( _providesPortParser != NULL ) { _findProvidesPortBy = _providesPortParser->getFindBy (); } if ( _findUsesPortBy->isFindByNamingService () ) { while ( CORBA::is_nil ( _usesObj ) ) _usesObj = _orb.lookup ( _findUsesPortBy->getFindByNamingServiceName () ); } if ( _findProvidesPortBy->isFindByNamingService () ) { while ( CORBA::is_nil ( _providesObj ) ) _providesObj = _orb.lookup ( _findProvidesPortBy-> getFindByNamingServiceName () ); } CF::PortSupplier_ptr _usesPort = CF::PortSupplier::_narrow ( _usesObj ); CF::Port_ptr _port = CF::Port::_narrow ( _usesPort->getPort ( _usesPortParser->getID () ) ); _port->connectPort ( _providesObj, CORBA::string_dup ( ( *_connection ) [ _numConnections ] ->getID () ) ); } // We are assuming that all components and their resources are collocated. // This means that we assume the SAD element contains the // element. Application_impl* _application = new Application_impl ( _identifier, name, _softwareProfile, _availableDevs, // need to provide support for device searching _implSeq, _namingCtxSeq, _pidSeq, // need to provide support for PID SEQ CF::Resource::_duplicate ( _assemblyController ) ); ///\todo Figure out what this commented out code is supposed to do // StandardEvent::DomainManagementObjectAddedEventType _objAddedEvent; //_objAddedEvent.producerId = CORBA::string_dup (_identifier); //_objAddedEvent.sourceId = CORBA::string_dup (_application->identifier ()); //_objAddedEvent.sourceName = CORBA::string_dup (_application->name ()); //_objAddedEvent.sourceIOR = _application->_this (); //_objAddedEvent.sourceCategory = StandardEvent::APPLICATION; //CORBA::Any _anyObjAddedEvent; //_anyObjAddedEvent <<= _objAddedEvent; // sendEventToOutgoingChannel( _anyObjAddedEvent ); // _assemblyController=CF::Resource::_nil(); return CF::Application::_duplicate ( _application->_this () ); } ; /* END ApplicationFactory_impl::create() */ /*Creates a vector of components and their pertinent info listed in the order they must be loaded and executed (deepest dependancies first). Need to add getImplementations() for allocation loop???*/ void ApplicationFactory_impl::ComponentDependencies ( SPDParser * SPDFile, bool assignmentMatch ) { // unused PJB int TBD_Length = 2; //Need to figure out how to find number of dependancy files. vector * SPDImpl = SPDFile->getImplementations (); // unused PJB char** DependantFiles = (*SPDImpl)[0]->getSoftwareDependencies(); //Assuming only one implementation. //Open property file and get properties: char *PRFFileName = SPDFile->getPRFFile (); PRFParser PRFFile ( PRFFileName ); PRFProperty *prfSimpleProp = PRFFile.getFactoryParamProperties (); ComponentInfo *CurrentComponentInfo = new ComponentInfo; CurrentComponentInfo->factoryParameters.length ( prfSimpleProp->size () ); { // this is here because Microsoft does not believe in following standards for ( unsigned int i = 0; i < prfSimpleProp->size (); i++ ) { CF::DataType * dt = ( *prfSimpleProp ) [ i ] ->getDataType (); CurrentComponentInfo->factoryParameters[ i ].id = CORBA::string_dup ( dt->id ); CurrentComponentInfo->factoryParameters[ i ].value = dt->value; } } prfSimpleProp = PRFFile.getExecParamProperties (); CurrentComponentInfo->execParameters.length ( prfSimpleProp->size () ); { // this is here because Microsoft does not believe in following standards for ( unsigned int i = 0; i < prfSimpleProp->size (); i++ ) { CF::DataType * dt = ( *prfSimpleProp ) [ i ] ->getDataType (); CurrentComponentInfo->execParameters[ i ].id = CORBA::string_dup ( dt->id ); CurrentComponentInfo->execParameters[ i ].value = dt->value; } } prfSimpleProp = PRFFile.getMatchingProperties (); CurrentComponentInfo->allocationCapacities.length ( prfSimpleProp->size () ); { // this is here because Microsoft does not believe in following standards for ( unsigned int i = 0; i < prfSimpleProp->size (); i++ ) { CF::DataType * dt = ( *prfSimpleProp ) [ i ] ->getDataType (); CurrentComponentInfo->allocationCapacities[ i ].id = CORBA::string_dup ( dt->id ); CurrentComponentInfo->allocationCapacities[ i ].value = dt->value; } } prfSimpleProp = PRFFile.getConfigureProperties (); CurrentComponentInfo->configureProperties.length ( prfSimpleProp->size () ); { // this is here because Microsoft does not believe in following standards for ( unsigned int i = 0; i < prfSimpleProp->size (); i++ ) { CF::DataType * dt = ( *prfSimpleProp ) [ i ] ->getDataType (); CurrentComponentInfo->configureProperties[ i ].id = CORBA::string_dup ( dt->id ); CurrentComponentInfo->configureProperties[ i ].value = dt->value; } } CurrentComponentInfo->implId = ( *SPDImpl ) [ 0 ] ->getID (); CurrentComponentInfo->localFileName = ( *SPDImpl ) [ 0 ] ->getCodeFile (); CurrentComponentInfo->codeType = ( *SPDImpl ) [ 0 ] ->getCodeType (); CurrentComponentInfo->entryPoint = ( *SPDImpl ) [ 0 ] ->getEntryPoint (); CurrentComponentInfo->usesDevices = ( *SPDImpl ) [ 0 ] ->getUsesDevices (); CurrentComponentInfo->name = SPDFile->getSoftPkgName (); if ( assignmentMatch ) DeviceLoadInfoVector.push_back ( CurrentComponentInfo ); else LoadInfoVector.push_back ( CurrentComponentInfo ); } void /*char* _spdFileName, */ ApplicationFactory_impl::verifyDeviceAssignments ( std::vector < char *>&SPDList, const CF:: DeviceAssignmentSequence & _deviceAssignments ) { bool assignmentMatch; for ( unsigned int i = 0; i < SPDList.size (); i++ ) { SPDParser SPDFile ( SPDList[ i ] ); assignmentMatch = false; char *component = SPDFile.getSoftPkgName (); //Verify that the component assigned to the device exists in the SAD for ( unsigned int j = 0; j < _deviceAssignments.length (); j++ ) { if ( strcmp ( _deviceAssignments[ j ].componentId, component ) == 0 ) { assignmentMatch = true; } } ComponentDependencies ( &SPDFile, assignmentMatch ); } } ApplicationFactoryEventHandler:: ApplicationFactoryEventHandler ( ApplicationFactory_impl * _appFac ) { appFactory = _appFac; } void ApplicationFactoryEventHandler::push ( const CORBA::Any & _any ) throw ( CORBA::SystemException, CosEventComm::Disconnected ) {} void ApplicationFactoryEventHandler::disconnect_push_consumer () throw ( CORBA::SystemException ) {}