diff options
Diffstat (limited to 'sca-cpp/tags/cpp-1.0-incubating-M2-final/sca/runtime/extensions/ruby/src/tuscany/sca/ruby/RubyServiceWrapper.cpp')
-rw-r--r-- | sca-cpp/tags/cpp-1.0-incubating-M2-final/sca/runtime/extensions/ruby/src/tuscany/sca/ruby/RubyServiceWrapper.cpp | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/sca-cpp/tags/cpp-1.0-incubating-M2-final/sca/runtime/extensions/ruby/src/tuscany/sca/ruby/RubyServiceWrapper.cpp b/sca-cpp/tags/cpp-1.0-incubating-M2-final/sca/runtime/extensions/ruby/src/tuscany/sca/ruby/RubyServiceWrapper.cpp new file mode 100644 index 0000000000..a0eb97142d --- /dev/null +++ b/sca-cpp/tags/cpp-1.0-incubating-M2-final/sca/runtime/extensions/ruby/src/tuscany/sca/ruby/RubyServiceWrapper.cpp @@ -0,0 +1,724 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + + +#include "tuscany/sca/ruby/RubyServiceWrapper.h" + +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/util/Utils.h" +#include "tuscany/sca/util/Library.h" +#include "tuscany/sca/model/Component.h" +#include "tuscany/sca/model/Composite.h" +#include "tuscany/sca/model/Service.h" +#include "tuscany/sca/model/ServiceType.h" +#include "tuscany/sca/model/Reference.h" +#include "tuscany/sca/model/ReferenceType.h" +#include "tuscany/sca/core/SCARuntime.h" +#include "tuscany/sca/ruby/model/RubyImplementation.h" +#include "tuscany/sca/ruby/model/RubyServiceBinding.h" +#include "tuscany/sca/ruby/RubyServiceProxy.h" +#include "commonj/sdo/SDO.h" + +using commonj::sdo::PropertyList; + +namespace tuscany +{ + namespace sca + { + namespace ruby + { + + // =========== + // Constructor + // =========== + RubyServiceWrapper::RubyServiceWrapper(Service* service) + : ServiceWrapper(service) + { + LOGENTRY(1,"RubyServiceWrapper::constructor"); + + component = service->getComponent(); + implementation = (RubyImplementation*)component->getType(); + interf = service->getType()->getInterface(); + + LOGEXIT(1,"RubyServiceWrapper::constructor"); + + } + + // ========== + // Destructor + // ========== + RubyServiceWrapper::~RubyServiceWrapper() + { + LOGENTRY(1,"RubyServiceWrapper::destructor"); + LOGEXIT(1,"RubyServiceWrapper::destructor"); + } + + // ====================================================================== + // invoke: wrapper call to service with setting the component context + // ====================================================================== + void RubyServiceWrapper::invoke(Operation& operation) + { + LOGENTRY(1,"RubyServiceWrapper::invoke"); + + SCARuntime* runtime = SCARuntime::getInstance(); + runtime->setCurrentComponent(component); + + try + { + + // Create a new instance of the Ruby implementation class + VALUE instance = rb_class_new_instance(0, NULL, implementation->getImplementationClass()); + + // Set all the references + const Component::REFERENCE_MAP& references = component->getReferences(); + Component::REFERENCE_MAP::const_iterator refiter = references.begin(); + for (int ri=0; ri< references.size(); ri++) + { + Reference* reference = refiter->second; + RubyServiceProxy* proxy = (RubyServiceProxy*)reference->getBinding()->getServiceProxy(); + if (proxy != NULL) + { + VALUE proxyValue = proxy->getProxyValue(); + string varName = "@" + refiter->first; + rb_iv_set(instance, varName.c_str(), proxyValue); + } + refiter++; + } + + // Set all the configured properties + DataObjectPtr properties = component->getProperties(); + PropertyList pl = properties->getInstanceProperties(); + for (int i = 0; i < pl.size(); i++) + { + if (properties->isSet(pl[i])) + { + string varName = "@"; + varName += pl[i].getName(); + string cstr = properties->getCString(pl[i]); + VALUE propertyValue; + if (cstr == "true") + { + propertyValue = Qtrue; + } + else if (cstr == "false") + { + propertyValue = Qfalse; + } + else + { + //TODO use one of the rb_str_to_inum() functions + // to convert a numeric value to a Ruby numeric + propertyValue = rb_str_new2(cstr.c_str()); + } + rb_iv_set(instance, varName.c_str(), propertyValue); + } + } + + // Get the ID of the specified method + ID method = rb_intern(operation.getName().c_str()); + + // Convert C++ parameters to Ruby parameters + VALUE *args = NULL; + int n = operation.getNParms(); + if (n != 0) + { + args=new VALUE[n]; + + for(int i = 0; i < operation.getNParms(); i++) + { + VALUE value; + + const Operation::Parameter& parm = operation.getParameter(i); + Operation::ParameterType parmType = parm.getType(); + switch(parmType) + { + case Operation::BOOL: + { + if( *(bool*)parm.getValue()) + { + //boolean true + value = rb_int2inum(1); + } + else + { + value = rb_int2inum(0); + } + break; + } + case Operation::SHORT: + { + value = rb_int2inum(*(short*)parm.getValue()); + break; + } + case Operation::USHORT: + { + value = rb_uint2inum(*(unsigned short*)parm.getValue()); + break; + } + case Operation::LONG: + { + value = rb_int2inum(*(long*)parm.getValue()); + break; + } + case Operation::ULONG: + { + value = rb_uint2inum(*(unsigned long*)parm.getValue()); + break; + } + case Operation::FLOAT: + { + value = rb_float_new(*(float*)parm.getValue()); + break; + } + case Operation::DOUBLE: + { + value = rb_float_new(*(double*)parm.getValue()); + break; + } + case Operation::LONGDOUBLE: + { + value = rb_float_new(*(long double*)parm.getValue()); + break; + } + case Operation::CHARS: + { + value = rb_str_new2(*(char**)parm.getValue()); + break; + } + case Operation::STRING: + { + value = rb_str_new2((*(string*)parm.getValue()).c_str()); + break; + } + case Operation::DATAOBJECT: + { + DataObjectPtr dob = *(DataObjectPtr*)parm.getValue(); + + // Convert a DataObject to a REXML Document object + Composite* composite = component->getComposite(); + commonj::sdo::XMLHelper* xmlHelper = composite->getXMLHelper(); + char* str = xmlHelper->save( + dob, + dob->getType().getURI(), + dob->getType().getName()); + VALUE vstr[1]; + vstr[0] = rb_str_new2(str); + + value = rb_class_new_instance(1, vstr, RubyImplementation::getXMLDocumentClass()); + break; + } + default: + { + //throw new ComponentInvocationException("Operation parameter type not supported"); + string msg = "Operation parameter type not supported" + parmType; + throw msg.c_str(); + } + } + + args[i] = value; + } + } + + + // Invoke the specified method + VALUE result; + if (n == 0) + { + result = rb_funcall(instance, method, 0); + } + else + { + result = rb_funcall2(instance, method, n, args); + } + + // Convert the Ruby result value to a C++ result + int resultType = TYPE(result); + char buf[20]; + switch(resultType) + { + case T_FLOAT: + { + float* data = new float; + *data = rb_num2dbl(result); + + // Check if the return type has already been set for typed languages + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + *(bool*)operation.getReturnValue() = (*data != 0.0); + break; + } + case Operation::SHORT: + { + *(short*)operation.getReturnValue() = (short)*data; + break; + } + case Operation::USHORT: + { + *(unsigned short*)operation.getReturnValue() = (unsigned short)*data; + break; + } + case Operation::INT: + { + *(int*)operation.getReturnValue() = (int)*data; + break; + } + case Operation::UINT: + { + *(unsigned int*)operation.getReturnValue() = (unsigned int)*data; + break; + } + case Operation::LONG: + { + *(long*)operation.getReturnValue() = (long)*data; + break; + } + case Operation::ULONG: + { + *(unsigned long*)operation.getReturnValue() = (unsigned long)*data; + break; + } + case Operation::FLOAT: + { + *(float*)operation.getReturnValue() = (float)*data; + break; + } + case Operation::DOUBLE: + { + *(double*)operation.getReturnValue() = (double)*data; + break; + } + case Operation::LONGDOUBLE: + { + *(long double*)operation.getReturnValue() = (long double)*data; + break; + } + case Operation::CHARS: + { + sprintf(buf, "%f", *data); + *(char**)operation.getReturnValue() = buf; + break; + } + case Operation::STRING: + { + sprintf(buf, "%f", *data); + *(string*)operation.getReturnValue() = buf; + break; + } + default: + { + // The type is set as something else or has not been set + operation.setReturnValue(data); + } + } + break; + } + case T_STRING: + { + string* stringdata = new string(rb_string_value_cstr(&result)); + const char** data = new const char*; + *data = stringdata->c_str(); + + // Check if the return type has already been set (for typed languages) + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + // If the string is empty or "0" or "false" set to false, otherwise true + if(strlen(*data) == 0 || strcmp(*data, "0") == 0 || strcmp(*data, "false") == 0) + { + *(bool*)operation.getReturnValue() = false; + } + else + { + *(bool*)operation.getReturnValue() = true; + } + break; + } + case Operation::SHORT: + { + *(short*)operation.getReturnValue() = (short)atoi(*data); + break; + } + case Operation::USHORT: + { + *(unsigned short*)operation.getReturnValue() = (unsigned short)atoi(*data); + break; + } + case Operation::INT: + { + *(int*)operation.getReturnValue() = (int)atoi(*data); + break; + } + case Operation::UINT: + { + *(unsigned int*)operation.getReturnValue() = (unsigned int)atoi(*data); + break; + } + case Operation::LONG: + { + *(long*)operation.getReturnValue() = (long)atol(*data); + break; + } + case Operation::ULONG: + { + *(unsigned long*)operation.getReturnValue() = (unsigned long)atol(*data); + break; + } + case Operation::FLOAT: + { + *(float*)operation.getReturnValue() = (float)atof(*data); + break; + } + case Operation::DOUBLE: + { + *(double*)operation.getReturnValue() = (double)atof(*data); + break; + } + case Operation::LONGDOUBLE: + { + *(long double*)operation.getReturnValue() = (long double)atof(*data); + break; + } + case Operation::CHARS: + { + *(const char**)operation.getReturnValue() = *data; + break; + } + case Operation::STRING: + { + *(string*)operation.getReturnValue() = *data; + break; + } + default: + { + // The type is set as something else or has not been set + operation.setReturnValue(data); + } + } + break; + } + case T_FIXNUM: + { + long* data = new long; + *data = rb_num2long(result); + + // Check if the return type has already been (set for typed languages) + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + *(bool*)operation.getReturnValue() = (*data != 0); + break; + } + case Operation::SHORT: + { + *(short*)operation.getReturnValue() = (short)*data; + break; + } + case Operation::USHORT: + { + *(unsigned short*)operation.getReturnValue() = (unsigned short)*data; + break; + } + case Operation::INT: + { + *(int*)operation.getReturnValue() = (int)*data; + break; + } + case Operation::UINT: + { + *(unsigned int*)operation.getReturnValue() = (unsigned int)*data; + break; + } + case Operation::LONG: + { + *(long*)operation.getReturnValue() = (long)*data; + break; + } + case Operation::ULONG: + { + *(unsigned long*)operation.getReturnValue() = (unsigned long)*data; + break; + } + case Operation::FLOAT: + { + *(float*)operation.getReturnValue() = (float)*data; + break; + } + case Operation::DOUBLE: + { + *(double*)operation.getReturnValue() = (double)*data; + break; + } + case Operation::LONGDOUBLE: + { + *(long double*)operation.getReturnValue() = (long double)*data; + break; + } + case Operation::CHARS: + { + sprintf(buf, "%d", *data); + *(char**)operation.getReturnValue() = buf; + break; + } + case Operation::STRING: + { + sprintf(buf, "%d", *data); + *(string*)operation.getReturnValue() = buf; + break; + } + default: + { + // The type is set as something else or has not been set + operation.setReturnValue(data); + } + } + + break; + } + case T_BIGNUM: + { + long double* data = new long double; + *data = rb_num2dbl(result); + + // Check if the return type has already been set (for typed languages) + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + *(bool*)operation.getReturnValue() = (*data != 0.0); + break; + } + case Operation::SHORT: + { + *(short*)operation.getReturnValue() = (short)*data; + break; + } + case Operation::USHORT: + { + *(unsigned short*)operation.getReturnValue() = (unsigned short)*data; + break; + } + case Operation::INT: + { + *(int*)operation.getReturnValue() = (int)*data; + break; + } + case Operation::UINT: + { + *(unsigned int*)operation.getReturnValue() = (unsigned int)*data; + break; + } + case Operation::LONG: + { + *(long*)operation.getReturnValue() = (long)*data; + break; + } + case Operation::ULONG: + { + *(unsigned long*)operation.getReturnValue() = (unsigned long)*data; + break; + } + case Operation::FLOAT: + { + *(float*)operation.getReturnValue() = (float)*data; + break; + } + case Operation::DOUBLE: + { + *(double*)operation.getReturnValue() = (double)*data; + break; + } + case Operation::LONGDOUBLE: + { + *(long double*)operation.getReturnValue() = (long double)*data; + break; + } + case Operation::CHARS: + { + sprintf(buf, "%f", *data); + *(char**)operation.getReturnValue() = buf; + break; + } + case Operation::STRING: + { + sprintf(buf, "%f", *data); + *(string*)operation.getReturnValue() = buf; + break; + } + default: + { + // The type is set as something else or has not been set + operation.setReturnValue(data); + } + } + break; + } + case T_TRUE: + case T_FALSE: + { + bool* data = new bool; + *data = (resultType == T_TRUE); + // Check if the return type has already been set (for typed languages) + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + *(bool*)operation.getReturnValue() = *data; + break; + } + case Operation::SHORT: + { + *(short*)operation.getReturnValue() = (short)*data; + break; + } + case Operation::USHORT: + { + *(unsigned short*)operation.getReturnValue() = (unsigned short)*data; + break; + } + case Operation::INT: + { + *(int*)operation.getReturnValue() = (int)*data; + break; + } + case Operation::UINT: + { + *(unsigned int*)operation.getReturnValue() = (unsigned int)*data; + break; + } + case Operation::LONG: + { + *(long*)operation.getReturnValue() = (long)*data; + break; + } + case Operation::ULONG: + { + *(unsigned long*)operation.getReturnValue() = (unsigned long)*data; + break; + } + case Operation::FLOAT: + { + *(float*)operation.getReturnValue() = (float)*data; + break; + } + case Operation::DOUBLE: + { + *(double*)operation.getReturnValue() = (double)*data; + break; + } + case Operation::LONGDOUBLE: + { + *(long double*)operation.getReturnValue() = (long double)*data; + break; + } + case Operation::CHARS: + { + if(*data) + { + *(char**)operation.getReturnValue() = "true"; + } + else + { + *(char**)operation.getReturnValue() = "false"; + } + break; + } + case Operation::STRING: + { + if(*data) + { + *(string*)operation.getReturnValue() = "true"; + } + else + { + *(string*)operation.getReturnValue() = "false"; + } + break; + } + default: + { + // The type is set as something else or has not been set + operation.setReturnValue(data); + } + } + + break; + } + case T_OBJECT: + { + VALUE klass = rb_obj_class(result); + if (klass == RubyImplementation::getXMLDocumentClass()) + { + // Convert a REXML::Document to a DataObject + ID to_s = rb_intern("to_s"); + VALUE vstr = rb_funcall(result, to_s, 0); + string str = string(rb_string_value_cstr(&vstr)); + + Composite* composite = component->getComposite(); + commonj::sdo::XMLHelper* xmlHelper = composite->getXMLHelper(); + commonj::sdo::XMLDocumentPtr xmlDoc = xmlHelper->load(str.c_str()); + + DataObjectPtr dob; + if (xmlDoc != NULL) + { + dob = xmlDoc->getRootDataObject(); + } + if (dob != NULL) + { + operation.setReturnValue(&dob); + } + else + { + string msg = "Document could not be converted to a DataObject"; + throw msg.c_str(); + } + } + else + { + string msg = "Ruby type not supported: " + resultType; + throw msg.c_str(); + } + break; + } + default: + { + string msg = "Ruby type not supported: " + resultType; + throw msg.c_str(); + } + } + + } + catch (...) + { + runtime->unsetCurrentComponent(); + throw; + } + runtime->unsetCurrentComponent(); + LOGEXIT(1,"RubyServiceWrapper::invoke"); + + } + + } // End namespace ruby + } // End namespace sca +} // End namespace tuscany |