From bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a Mon Sep 17 00:00:00 2001 From: dims Date: Tue, 17 Jun 2008 00:23:01 +0000 Subject: Move Tuscany from Incubator to top level. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68 --- .../runtime/extensions/python/Makefile.am | 24 + .../runtime/extensions/python/deploy.bat | 66 ++ .../runtime/extensions/python/deploymodule.bat | 61 ++ .../runtime/extensions/python/src/Makefile.am | 66 ++ .../src/tuscany/sca/python/PythonExtension.cpp | 76 ++ .../src/tuscany/sca/python/PythonExtension.h | 57 + .../sca/python/PythonImplementationExtension.cpp | 86 ++ .../sca/python/PythonImplementationExtension.h | 75 ++ .../sca/python/PythonInterfaceExtension.cpp | 123 +++ .../tuscany/sca/python/PythonInterfaceExtension.h | 74 ++ .../src/tuscany/sca/python/PythonServiceProxy.cpp | 81 ++ .../src/tuscany/sca/python/PythonServiceProxy.h | 83 ++ .../tuscany/sca/python/PythonServiceWrapper.cpp | 1096 ++++++++++++++++++++ .../src/tuscany/sca/python/PythonServiceWrapper.h | 142 +++ .../python/src/tuscany/sca/python/export.h | 41 + .../sca/python/model/PythonImplementation.cpp | 131 +++ .../sca/python/model/PythonImplementation.h | 145 +++ .../tuscany/sca/python/model/PythonInterface.cpp | 53 + .../src/tuscany/sca/python/model/PythonInterface.h | 77 ++ .../sca/python/model/PythonReferenceBinding.cpp | 61 ++ .../sca/python/model/PythonReferenceBinding.h | 92 ++ .../sca/python/model/PythonServiceBinding.cpp | 58 ++ .../sca/python/model/PythonServiceBinding.h | 81 ++ .../python/src/tuscany/sca/python/sca_module.cpp | 540 ++++++++++ .../python/src/tuscany/sca/python/sca_proxy.py | 57 + .../python/xsd/sca-implementation-python.xsd | 49 + .../extensions/python/xsd/sca-interface-python.xsd | 62 ++ 27 files changed, 3557 insertions(+) create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/Makefile.am create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploy.bat create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploymodule.bat create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/Makefile.am create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/export.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.h create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_module.cpp create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_proxy.py create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-implementation-python.xsd create mode 100644 tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-interface-python.xsd (limited to 'tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python') diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/Makefile.am new file mode 100644 index 0000000000..83e70b4b94 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/Makefile.am @@ -0,0 +1,24 @@ +# 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. + +SUBDIRS = src + +datadir=$(prefix)/extensions/python + +nobase_data_DATA = xsd/*.xsd + +EXTRA_DIST = xsd \ No newline at end of file diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploy.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploy.bat new file mode 100644 index 0000000000..43c7a45777 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploy.bat @@ -0,0 +1,66 @@ +@echo off + +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. + + +setlocal + +if . == .%1 ( +echo sca root not specified +goto usage +) +set rootdir=%1 +set deploydir=%rootdir%\deploy +set extdir=%deploydir%\extensions +set pythonextdir=%extdir%\python +set srcdir=%rootdir%\runtime\extensions\python\src + +if . == .%2 ( +echo input directory not specified +goto usage +) +set inpath=%2 +echo %inpath% + + +if not exist %deploydir% mkdir %deploydir% +if not exist %extdir% mkdir %extdir% +if not exist %pythonextdir% mkdir %pythonextdir% +if not exist %pythonextdir%\module mkdir %pythonextdir%\module +if not exist %pythonextdir%\bin mkdir %pythonextdir%\bin +if not exist %pythonextdir%\lib mkdir %pythonextdir%\lib +if not exist %pythonextdir%\xsd mkdir %pythonextdir%\xsd + +del %pythonextdir%\bin\tuscany_sca_python.* +del %pythonextdir%\lib\*.lib + +copy %srcdir%\..\xsd\*.* %pythonextdir%\xsd + +copy %inpath%\tuscany_sca_python.lib %pythonextdir%\lib +copy %inpath%\tuscany_sca_python.dll %pythonextdir%\bin +copy %inpath%\tuscany_sca_python.dll %pythonextdir%\module + +if exist %inpath%\tuscany_sca_python.pdb copy %inpath%\tuscany_sca_python.pdb %pythonextdir%\bin +if exist %inpath%\tuscany_sca_python.pdb copy %inpath%\tuscany_sca_python.pdb %pythonextdir%\module + +goto end +:usage +echo Usage: deploy +:end + +endlocal diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploymodule.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploymodule.bat new file mode 100644 index 0000000000..4403b0ce6c --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/deploymodule.bat @@ -0,0 +1,61 @@ +@echo off + +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. + + +setlocal + +if . == .%1 ( +echo sca root not specified +goto usage +) +set rootdir=%1 +set deploydir=%rootdir%\deploy +set extdir=%deploydir%\extensions +set pythonextdir=%extdir%\python +set srcdir=%rootdir%\runtime\extensions\python\src + +if . == .%2 ( +echo input directory not specified +goto usage +) +set inpath=%2 +echo %inpath% + + +if not exist %deploydir% mkdir %deploydir% +if not exist %extdir% mkdir %extdir% +if not exist %pythonextdir% mkdir %pythonextdir% +if not exist %pythonextdir%\bin mkdir %pythonextdir%\bin +if not exist %pythonextdir%\lib mkdir %pythonextdir%\lib +if not exist %pythonextdir%\xsd mkdir %pythonextdir%\xsd + +del %pythonextdir%\bin\sca.pyd +del %pythonextdir%\bin\sca_proxy.py + +copy %inpath%\sca.pyd %pythonextdir%\bin +copy %srcdir%\tuscany\sca\python\sca_proxy.py %pythonextdir%\bin + +if exist %inpath%\sca.pdb copy %inpath%\sca.pdb %pythonextdir%\bin + +goto end +:usage +echo Usage: deploy +:end + +endlocal diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/Makefile.am new file mode 100644 index 0000000000..ec81dd5840 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/Makefile.am @@ -0,0 +1,66 @@ +# 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. + +libdir=$(prefix)/extensions/python/lib +lib_LTLIBRARIES = libtuscany_sca_python.la + +pydir=$(prefix)/extensions/python/lib +py_DATA = tuscany/sca/python/sca_proxy.py +EXTRA_DIST = tuscany/sca/python/sca_proxy.py + +rootdir=$(prefix)/extensions/python + +noinst_HEADERS = \ +tuscany/sca/python/*.h \ +tuscany/sca/python/model/*.h + +libtuscany_sca_python_la_SOURCES = \ +tuscany/sca/python/PythonExtension.cpp \ +tuscany/sca/python/PythonImplementationExtension.cpp \ +tuscany/sca/python/PythonInterfaceExtension.cpp \ +tuscany/sca/python/PythonServiceWrapper.cpp \ +tuscany/sca/python/PythonServiceProxy.cpp \ +tuscany/sca/python/sca_module.cpp \ +tuscany/sca/python/model/PythonImplementation.cpp \ +tuscany/sca/python/model/PythonInterface.cpp \ +tuscany/sca/python/model/PythonReferenceBinding.cpp \ +tuscany/sca/python/model/PythonServiceBinding.cpp + +# Need python env varibles set. e.g: +# PYTHON_LIB=/usr/lib +# PYTHON_INCLUDE=/usr/include/python2.4 +# PYTHON_VERSION=python2.4 +libtuscany_sca_python_la_LIBADD = -L${TUSCANY_SDOCPP}/lib -ltuscany_sdo \ + -L$(top_builddir)/runtime/core/src -ltuscany_sca \ + -L${PYTHON_LIB} -l${PYTHON_VERSION} + +INCLUDES = -Imodel -I$(top_builddir)/runtime/core/src \ + -I${TUSCANY_SDOCPP}/include \ + -I${PYTHON_INCLUDE} + +AM_CPPFLAGS = $(CPPFLAGS) -D_DEBUG + + +moduledir=$(prefix)/extensions/python/module +extension = libtuscany_sca_python$(libsuffix) + +install-exec-hook: + test -z $(moduledir) || $(mkdir_p) $(moduledir); + -rm -f $(moduledir)/$(extension) + $(LN_S) $(libdir)/$(extension) $(moduledir)/$(extension) + -rm -f $(libdir)/sca.so + $(LN_S) $(libdir)/libtuscany_sca_python$(libsuffix) $(libdir)/sca.so \ No newline at end of file diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.cpp new file mode 100644 index 0000000000..0274ffc774 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.cpp @@ -0,0 +1,76 @@ +/* + * 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/python/PythonExtension.h" +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/core/SCARuntime.h" +#include "tuscany/sca/python/PythonImplementationExtension.h" +#include "tuscany/sca/python/PythonInterfaceExtension.h" + +using namespace std; +using namespace commonj::sdo; +using namespace tuscany::sca::model; + +extern "C" +{ +#if defined(WIN32) || defined(_WINDOWS) + __declspec(dllexport) +#endif + void tuscany_sca_python_initialize() + { + tuscany::sca::python::PythonExtension::initialize(); + } +} + +namespace tuscany +{ + namespace sca + { + namespace python + { + // =================================================================== + // Constructor for the PythonExtension class. + // =================================================================== + PythonExtension::PythonExtension() + { + logentry(); + } + + // =================================================================== + // Destructor for the PythonExtension class. + // =================================================================== + PythonExtension::~PythonExtension() + { + logentry(); + } + + void PythonExtension::initialize() + { + logentry(); + SCARuntime* runtime = SCARuntime::getCurrentRuntime(); + runtime->registerImplementationExtension(new PythonImplementationExtension()); + runtime->registerInterfaceExtension(new PythonInterfaceExtension()); + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.h new file mode 100644 index 0000000000..783f37a228 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonExtension.h @@ -0,0 +1,57 @@ +/* + * 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$ */ + +#ifndef tuscany_sca_python_pythonextension_h +#define tuscany_sca_python_pythonextension_h + +namespace tuscany +{ + namespace sca + { + namespace python + { + + class PythonExtension + { + public: + /** + * Default constructor + */ + PythonExtension(); + + /** + * Destructor + */ + virtual ~PythonExtension(); + + static void initialize(); + + private: + + }; + + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_pythonextension_h + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.cpp new file mode 100644 index 0000000000..84cc34c6a4 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.cpp @@ -0,0 +1,86 @@ +/* + * 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/python/PythonImplementationExtension.h" +#include "tuscany/sca/python/model/PythonImplementation.h" +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/util/Utils.h" + +using namespace std; +using namespace commonj::sdo; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + // =================================================================== + // Constructor for the PythonImplementationExtension class. + // =================================================================== + PythonImplementationExtension::PythonImplementationExtension() + { + logentry(); + } + + // =================================================================== + // Destructor for the PythonImplementationExtension class. + // =================================================================== + PythonImplementationExtension::~PythonImplementationExtension() + { + logentry(); + } + + const string PythonImplementationExtension::extensionName("python"); + const string PythonImplementationExtension::typeQName("http://www.osoa.org/xmlns/sca/1.0#PythonImplementation"); + + // =================================================================== + // loadModelElement - load the info from implementation.python + // =================================================================== + ComponentType* PythonImplementationExtension::getImplementation(Composite *composite, DataObjectPtr scdlImplementation) + { + logentry(); + + string module = scdlImplementation->getCString("module"); + string path = scdlImplementation->getCString("path"); + string className = scdlImplementation->getCString("class"); + string scopeName = scdlImplementation->getCString("scope"); + + PythonImplementation::Scope scope; + if (scopeName == "composite") + { + scope = PythonImplementation::COMPOSITE; + } + else + { + scope = PythonImplementation::STATELESS; + } + + PythonImplementation* pythonImpl = new PythonImplementation(composite, module, path, className, scope); + + return pythonImpl; + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.h new file mode 100644 index 0000000000..c94925c3fc --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonImplementationExtension.h @@ -0,0 +1,75 @@ +/* + * 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$ */ + + +#ifndef tuscany_sca_python_pythonimplementationextension_h +#define tuscany_sca_python_pythonimplementationextension_h + +#include "tuscany/sca/extension/ImplementationExtension.h" + +namespace tuscany +{ + namespace sca + { + namespace python + { + + class PythonImplementationExtension : public ImplementationExtension + { + public: + /** + * Default constructor + */ + PythonImplementationExtension(); + + /** + * Destructor + */ + virtual ~PythonImplementationExtension(); + + /** + * return the name of the extension + */ + virtual const std::string& getExtensionName() {return extensionName;} + + /** + * return the QName of schema elemant for this implementation extension + * (e.g. "http://www.osoa.org/xmlns/sca/1.0#implementation.python") + */ + virtual const std::string& getExtensionTypeQName() {return typeQName;} + + virtual tuscany::sca::model::ComponentType* getImplementation( + tuscany::sca::model::Composite* composite, + commonj::sdo::DataObjectPtr scdlImplementation); + + private: + static const std::string extensionName; + static const std::string typeQName; + + }; + + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_pythonimplementationextension_h + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.cpp new file mode 100644 index 0000000000..1d5e3b6361 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.cpp @@ -0,0 +1,123 @@ +/* + * 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/python/PythonInterfaceExtension.h" +#include "tuscany/sca/python/model/PythonInterface.h" +#include "tuscany/sca/util/Logging.h" + +using namespace std; +using namespace commonj::sdo; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + // =================================================================== + // Constructor for the PythonInterfaceExtension class. + // =================================================================== + PythonInterfaceExtension::PythonInterfaceExtension() + { + logentry(); + } + + // =================================================================== + // Destructor for the PythonInterfaceExtension class. + // =================================================================== + PythonInterfaceExtension::~PythonInterfaceExtension() + { + logentry(); + } + + const string PythonInterfaceExtension::extensionName("python"); + const string PythonInterfaceExtension::typeQName("http://www.osoa.org/xmlns/sca/1.0#PythonInterface"); + + // =================================================================== + // loadModelElement - load the info from interface.python + // =================================================================== + tuscany::sca::model::Interface* PythonInterfaceExtension::getInterface(Composite* composite, DataObjectPtr scdlInterface) + { + logentry(); + + // Determine the type + string ifType = scdlInterface->getType().getName(); + if (ifType == "PythonInterface") + { + bool remotable = scdlInterface->getBoolean("remotable"); + bool conversational = scdlInterface->getBoolean("conversational"); + + return new PythonInterface(remotable, conversational); + //DataObjectList& operationList = scdlInterface->getList("operation"); + + //for(int i=0; igetCString("name"); + + // if(operationList[i]->hasProperty("returnType")) + // { + // string returnType = operationList[i]->getCString("returnType"); + + // if(returnType == "string") + // { + // pythonInterface->addOperation(opName, PythonInterface::STRING); + // } + // else if(returnType == "int") + // { + // pythonInterface->addOperation(opName, PythonInterface::INT); + // } + // else if(returnType == "long") + // { + // pythonInterface->addOperation(opName, PythonInterface::LONG); + // } + // else if(returnType == "boolean") + // { + // pythonInterface->addOperation(opName, PythonInterface::BOOLEAN); + // } + // else if(returnType == "float") + // { + // pythonInterface->addOperation(opName, PythonInterface::FLOAT); + // } + // else if(returnType == "other") + // { + // pythonInterface->addOperation(opName, PythonInterface::OTHER); + // } + // else + // { + // pythonInterface->addOperation(opName, PythonInterface::NONE); + // } + // } + // else + // { + // // No return Type provided - set as NONE + // pythonInterface->addOperation(opName, PythonInterface::NONE); + // } + //} + // + //return pythonInterface; + } + return 0; + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.h new file mode 100644 index 0000000000..803d94743d --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonInterfaceExtension.h @@ -0,0 +1,74 @@ +/* + * 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$ */ + +#ifndef tuscany_sca_python_pythoninterfaceextension_h +#define tuscany_sca_python_pythoninterfaceextension_h + +#include "tuscany/sca/extension/InterfaceExtension.h" + +namespace tuscany +{ + namespace sca + { + namespace python + { + + class PythonInterfaceExtension : public InterfaceExtension + { + public: + /** + * Default constructor + */ + PythonInterfaceExtension(); + + /** + * Destructor + */ + virtual ~PythonInterfaceExtension(); + + /** + * return the name of the extension + */ + virtual const std::string& getExtensionName() {return extensionName;} + + /** + * return the QName of schema elemant for this implementation extension + * (e.g. "http://www.osoa.org/xmlns/sca/1.0#PythonInterface") + */ + virtual const std::string& getExtensionTypeQName() {return typeQName;} + + virtual tuscany::sca::model::Interface* getInterface( + tuscany::sca::model::Composite* composite, + commonj::sdo::DataObjectPtr scdlInterface); + + private: + static const std::string extensionName; + static const std::string typeQName; + + }; + + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_pythoninterfaceextension_h + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.cpp new file mode 100644 index 0000000000..9282bb953c --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.cpp @@ -0,0 +1,81 @@ +/* + * 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/python/PythonServiceProxy.h" +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/model/ServiceBinding.h" +#include "tuscany/sca/python/model/PythonReferenceBinding.h" + +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + + // ============================================ + // Constructor: Create a proxy from a reference + // ============================================ + PythonServiceProxy::PythonServiceProxy(Reference* reference) + : ServiceProxy(reference) + { + logentry(); + + // Get the service wrapper + PythonReferenceBinding* referenceBinding = (PythonReferenceBinding*)reference->getBinding(); + serviceWrapper = referenceBinding->getTargetServiceBinding()->getServiceWrapper(); + } + + // ========================================== + // Constructor: Create a proxy from a service + // ========================================== + PythonServiceProxy::PythonServiceProxy(Service* service) + : ServiceProxy(NULL) + { + logentry(); + + // Get the service wrapper + serviceWrapper = service->getBinding()->getServiceWrapper(); + } + + // ========== + // Destructor + // ========== + PythonServiceProxy::~PythonServiceProxy() + { + logentry(); + } + + // ===================================================== + // invokeService: invoke the service wired to this proxy + // ===================================================== + void PythonServiceProxy::invokeService(Operation& operation) + { + logentry(); + + // Invoke the service + serviceWrapper->invoke(operation); + } + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.h new file mode 100644 index 0000000000..64f856f51d --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceProxy.h @@ -0,0 +1,83 @@ +/* + * 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$ */ + +#ifndef tuscany_sca_python_pythonserviceproxy_h +#define tuscany_sca_python_pythonserviceproxy_h + +#include "export.h" +#include "tuscany/sca/core/ServiceProxy.h" +#include "tuscany/sca/core/ServiceWrapper.h" +#include "tuscany/sca/util/Library.h" +#include "tuscany/sca/model/Component.h" +#include "tuscany/sca/model/Reference.h" +#include "tuscany/sca/model/Service.h" + + +namespace tuscany +{ + namespace sca + { + namespace python + { + + /** + * Holds a proxy for a given reference from a component implemented in Python. + */ + class PythonServiceProxy : public ServiceProxy + { + public: + /** + * Create a new service proxy for a reference. The proxy will contain a pointer to + * the target ServiceWrapper. + * @param reference The reference on the source component. + */ + PythonServiceProxy(tuscany::sca::model::Reference* reference); + + /** + * Create a new service proxy for a service. The proxy will contain a pointer to + * the target ServiceWrapper. + * @param service The service on the target component. + */ + SCA_PYTHON_API PythonServiceProxy(tuscany::sca::model::Service* service); + + /** + * Destructor. + */ + virtual ~PythonServiceProxy(); + + /** + * Invoke the wired service. + */ + virtual void invokeService(Operation& operation); + + private: + + /** + * The target service wrapper + */ + ServiceWrapper* serviceWrapper; + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_pythonserviceproxy_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.cpp new file mode 100644 index 0000000000..57ac5baeb5 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.cpp @@ -0,0 +1,1096 @@ +/* + * 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 "commonj/sdo/SDO.h" + +#include "tuscany/sca/python/PythonServiceWrapper.h" +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/core/Exceptions.h" +#include "tuscany/sca/util/Utils.h" +#include "tuscany/sca/model/Component.h" +#include "tuscany/sca/model/Composite.h" +#include "tuscany/sca/model/ServiceType.h" +#include "tuscany/sca/model/Interface.h" +#include "tuscany/sca/core/SCARuntime.h" +#include "tuscany/sca/python/model/PythonImplementation.h" + +using namespace std; +using namespace commonj::sdo; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + + /** + * Prints out PyObject and dir(PyObject) + * for debugging purposes + */ + void printPyObject(char * name, PyObject *pObj) + { + PyObject* pObjRepr = PyObject_Repr(pObj); + loginfo("PyObject %s: %s", name, PyString_AsString(pObjRepr)); + Py_DECREF(pObjRepr); + + PyObject* pObjDir = PyObject_Dir(pObj); + PyObject* pObjDirRepr = PyObject_Repr(pObjDir); + loginfo("PyObject dir(%s): %s", name, PyString_AsString(pObjDirRepr)); + Py_DECREF(pObjDirRepr); + Py_DECREF(pObjDir); + } + + // =========== + // Constructor + // =========== + PythonServiceWrapper::PythonServiceWrapper(Service* service) + : ServiceWrapper(service) + { + logentry(); + + component = service->getComponent(); + implementation = (PythonImplementation*)component->getType(); + + pythonModule = NULL; + pythonClassInstance = NULL; + + // ----------------------------------------------- + // Get the implementation for the target component + // ----------------------------------------------- + PythonImplementation* impl = (PythonImplementation*)component->getType(); + if (!impl) + { + string msg = "Component " + component->getName() + " has no implementation defined"; + throwException(SystemConfigurationException, msg.c_str()); + } + + // Initialize the Python environment + Py_Initialize(); + + // Add the path to the composite (+ any further path specified) to the Python sys.path + string path = component->getComposite()->getRoot(); + if(impl->getModulePath().size() > 0) + { + path += "/" + impl->getModulePath(); + } + + loginfo("Module: %s", impl->getModule().c_str()); + loginfo("Path: %s", path.c_str()); + loginfo("Class: %s", impl->getClass().c_str()); + + PyObject* pSysName = PyString_FromString("sys"); + PyObject* pSys = PyImport_Import(pSysName); + Py_DECREF(pSysName); + + if(pSys != NULL) + { + PyObject* pSysPath = PyObject_GetAttrString(pSys, "path"); + + if(pSysPath != NULL && PyList_Check(pSysPath)) + { + PyObject* pPath = PyString_FromString(path.c_str()); + PyList_Append(pSysPath, pPath); + + Py_DECREF(pPath); + Py_DECREF(pSysPath); + } + Py_DECREF(pSys); + } + + if(&(impl->getModule()) != NULL && impl->getModule().size() > 0) + { + // Now import the module + PyObject* pModuleName = PyString_FromString(impl->getModule().c_str()); + + pythonModule = PyImport_Import(pModuleName); + Py_DECREF(pModuleName); + } + + if (!pythonModule) + { + if(PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Failed to load module named " + impl->getModule() + " on path " + path; + throwException(SystemConfigurationException, msg.c_str()); + } + printPyObject("pythonModule",pythonModule); + } + + // ========== + // Destructor + // ========== + PythonServiceWrapper::~PythonServiceWrapper() + { + logentry(); + + Py_XDECREF(pythonClassInstance); + Py_XDECREF(pythonModule); + Py_Finalize(); + } + + // ====================================================================== + // newInstance: create a new class instance + // ====================================================================== + PyObject* PythonServiceWrapper::newInstance() + { + logentry(); + + PythonImplementation* impl = (PythonImplementation*)component->getType(); + string className = impl->getClass(); + + PyObject* pClassInstance = NULL; + if (pythonModule != NULL) + { + if(&className != NULL && className.size() > 0) + { + // We have a class name, so create an instance and use this to invoke the correct function + PyObject* pClass = PyObject_GetAttrString(pythonModule, (char*) className.c_str()); + + if(pClass == NULL) + { + if(PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Cannot find class named " + className + " in Python module"; + throwException(SystemConfigurationException, msg.c_str()); + } + + pClassInstance = PyInstance_New(pClass, NULL, NULL); + + if(pClassInstance == NULL || !PyInstance_Check(pClassInstance)) + { + if(PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Could not create new instance of class named " + className + " in Python module"; + throwException(ServiceInvocationException, msg.c_str()); + } + Py_XDECREF(pClass); + } + } + return pClassInstance; + } + + // ====================================================================== + // getInstance: get a class instance for this scope + // ====================================================================== + PyObject* PythonServiceWrapper::getInstance() + { + logentry(); + + PythonImplementation::Scope scope = implementation->getScope(); + if (scope == PythonImplementation::COMPOSITE) + { + if (!pythonClassInstance) + { + pythonClassInstance = newInstance(); + } + return pythonClassInstance; + } + else // (scope == PythonImplementation::STATELESS) + { + return newInstance(); + } + } + + // ====================================================================== + // releaseImplementation: release the implementation for this scope + // ====================================================================== + void PythonServiceWrapper::releaseInstance() + { + logentry(); + + PythonImplementation::Scope scope = implementation->getScope(); + if(scope == PythonImplementation::STATELESS) + { + // Delete the class instance if there is one + if(pythonClassInstance != NULL && PyInstance_Check(pythonClassInstance)) + { + Py_DECREF(pythonClassInstance); + pythonClassInstance = NULL; + } + + // Need to reload the module + PyObject* reloadedPythonModule = PyImport_ReloadModule(pythonModule); + + if(reloadedPythonModule != NULL) + { + // Get rid of old pythonModule and replace with the reloaded one + Py_DECREF(pythonModule); + pythonModule = reloadedPythonModule; + } + } + } + + // ====================================================================== + // invoke: wrapper call to service with setting the component context + // ====================================================================== + void PythonServiceWrapper::invoke(Operation& operation) + { + logentry(); + + SCARuntime* runtime = SCARuntime::getCurrentRuntime(); + runtime->setCurrentComponent(component); + + + // Load the references & properties into the module + addReferences(pythonModule); + addProperties(pythonModule); + + try + { + loginfo("Operation: %s", operation.getName().c_str()); + + PyObject* pFunc = NULL; + pythonClassInstance = getInstance(); + + if(pythonClassInstance != NULL && PyInstance_Check(pythonClassInstance)) + { + // Get the function from the instance + pFunc = PyObject_GetAttrString(pythonClassInstance, (char*) operation.getName().c_str()); + } + if(pFunc == NULL && pythonModule != NULL) + { + // Get the function directly from the module if it could not be got from an instance + pFunc = PyObject_GetAttrString(pythonModule, (char*) operation.getName().c_str()); + } + if(pFunc == NULL) + { + // Can't get the function from the class or module + string msg = "Python module or class instance has not been created"; + throwException(ServiceInvocationException, msg.c_str()); + } + + if (pFunc && PyCallable_Check(pFunc)) + { + PyObject* pArgs = PyTuple_New(operation.getNParms()); + PyObject* pKeywordsDict = PyDict_New(); + PyObject* pValue = NULL; + + // Load up the xml.etree.ElementTree module for dealing with SDO params and return values + PyObject* elementTreeModuleName = PyString_FromString("xml.etree.ElementTree"); + PyObject* elementTreeModule = PyImport_Import(elementTreeModuleName); + + if(elementTreeModule == NULL) + { + // pre-Python2.5? - try to get an installed elementtree package + elementTreeModuleName = PyString_FromString("elementtree.ElementTree"); + elementTreeModule = PyImport_Import(elementTreeModuleName); + } + if(elementTreeModule == NULL) + { + // Still null - throw a warning but carry on - user may not need XML + logwarning("Could not load Python ElementTree module - is it installed? SDO and XML will not be supported"); + } + + for(unsigned int i = 0; i < operation.getNParms(); i++) + { + const Operation::Parameter& parm = operation.getParameter(i); + switch(parm.getType()) + { + case Operation::BOOL: + { + if( *(bool*)parm.getValue()) + { + //boolean true + pValue = Py_True; + } + else + { + pValue = Py_False; + } + break; + } + case Operation::SHORT: + { + pValue = PyInt_FromLong(*(short*)parm.getValue()); + break; + } + case Operation::USHORT: + { + pValue = PyInt_FromLong(*(unsigned short*)parm.getValue()); + break; + } + case Operation::INT: + { + pValue = PyInt_FromLong(*(int*)parm.getValue()); + break; + } + case Operation::UINT: + { + pValue = PyInt_FromLong(*(unsigned int*)parm.getValue()); + break; + } + case Operation::LONG: + { + pValue = PyLong_FromLong(*(long*)parm.getValue()); + break; + } + case Operation::ULONG: + { + pValue = PyLong_FromUnsignedLong(*(unsigned long*)parm.getValue()); + break; + } + case Operation::FLOAT: + { + pValue = PyFloat_FromDouble(*(float*)parm.getValue()); + break; + } + case Operation::DOUBLE: + { + pValue = PyFloat_FromDouble(*(double*)parm.getValue()); + break; + } + case Operation::LONGDOUBLE: + { + pValue = PyFloat_FromDouble(*(long double*)parm.getValue()); + break; + } + case Operation::CHARS: + { + pValue = PyString_FromString(*(char**)parm.getValue()); + break; + } + case Operation::STRING: + { + pValue = PyString_FromString((*(string*)parm.getValue()).c_str()); + break; + } + case Operation::DATAOBJECT: + { + if(elementTreeModule != NULL) + { + DataObjectPtr dob = *(DataObjectPtr*)parm.getValue(); + + // Convert a DataObject to a xml.etree.ElementTree Element object + Composite* composite = component->getComposite(); + XMLHelper* xmlHelper = composite->getXMLHelper(); + char* str = xmlHelper->save( + dob, + dob->getType().getURI(), + dob->getType().getName()); + + loginfo("Converting SDO DataObject to Python ElementTree: %s", str); + + // Get the xml.etree.ElementTree.XML function + PyObject* elementTreeXMLFunc = PyObject_GetAttrString(elementTreeModule, "XML"); + + // Call the XML() function with the XML string + pValue = PyObject_CallFunction(elementTreeXMLFunc, "s", str); + + Py_DECREF(elementTreeXMLFunc); + } + else + { + throwException(ServiceDataException, "Could not convert SDO DataObject to Python ElementTree as ElementTree module could not be loaded"); + } + break; + } + default: + throwException(ServiceDataException, "Operation parameter type not supported"); + } + + if (!pValue) + { + Py_DECREF(pArgs); + + if(PyErr_Occurred()) + { + PyErr_Print(); + } + + string msg = "Error converting parameter into Python type"; + throwException(ServiceDataException, msg.c_str()); + + } + //printPyObject("Param value", pValue); + + // If we have a param name, put it in the keyword args + if(parm.hasName()) + { + PyDict_SetItemString(pKeywordsDict, parm.getName().c_str(), pValue); + Py_DECREF(pValue); + } + else + { + /* pValue reference stolen here: */ + PyTuple_SetItem(pArgs, i, pValue); + } + } + + // Resize the args to the correct length + _PyTuple_Resize(&pArgs, operation.getNParms() - PyDict_Size(pKeywordsDict)); + + loginfo("Calling python func with %d args and %d keyword args", PyTuple_Size(pArgs), PyDict_Size(pKeywordsDict)); + + pValue = PyObject_Call(pFunc, pArgs, pKeywordsDict); + //printPyObject("Return value", pValue); + + Py_DECREF(pArgs); + if (pValue != NULL) + { + char buf[20]; + if(PyInt_Check(pValue) || PyLong_Check(pValue)) + { + long* data = new long; + if(PyInt_Check(pValue)) + { + loginfo("Int return value: %d", PyInt_AsLong(pValue)); + *data = PyInt_AsLong(pValue); + } + else + { + loginfo("Long return value: %l", PyLong_AsLong(pValue)); + *data = PyLong_AsLong(pValue); + } + + // 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); + } + } + } + else if(PyBool_Check(pValue)) + { + loginfo("Bool return value: %d", (pValue == Py_True)); + bool* data = new bool; + *data = (pValue == Py_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); + } + } + } + else if(PyFloat_Check(pValue)) + { + loginfo("Float return value: %f", PyFloat_AsDouble(pValue)); + + double* data = new double; + *data = PyFloat_AsDouble(pValue); + + // 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); + } + } + } + else if(PyString_Check(pValue)) + { + loginfo("String return value: %s", PyString_AsString(pValue)); + const char** data = new const char*; + *data = PyString_AsString(pValue); + + // 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 + string* stringData = new string; + *stringData = *data; + operation.setReturnValue(stringData); + } + } + } + else + { + PyObject* pIsElement = Py_False; + + if(elementTreeModule != NULL) + { + // Get the xml.etree.ElementTree.iselement function + PyObject* elementTreeIsElementFunc = PyObject_GetAttrString(elementTreeModule, "iselement"); + + // Call the iselement() function with pValue to check it + pIsElement = PyObject_CallFunction(elementTreeIsElementFunc, "O", pValue); + Py_DECREF(elementTreeIsElementFunc); + } + + if(PyObject_IsTrue(pIsElement) == 1) + { + // pValue is an xml.etree.ElementTree.Element - convert to SDO + PyObject* elementTreeToStringFunc = PyObject_GetAttrString(elementTreeModule, "tostring"); + PyObject* pElemString = PyObject_CallFunction(elementTreeToStringFunc, "O", pValue); + char* data = PyString_AsString(pElemString); + + loginfo("Converting Python ElementTree to SDO DataObject: %s", data); + + Composite* composite = component->getComposite(); + XMLHelper* xmlHelper = composite->getXMLHelper(); + XMLDocumentPtr xmlDoc = xmlHelper->load(data); + DataObjectPtr* dataObjectData = new DataObjectPtr; + if (xmlDoc != NULL) + { + *dataObjectData = xmlDoc->getRootDataObject(); + } + else + { + *dataObjectData = NULL; + } + + if (*dataObjectData != NULL) + { + operation.setReturnValue(dataObjectData); + } + else + { + string msg = "xml.etree.ElementTree.Element could not be converted to a DataObject"; + throwException(ServiceDataException, msg.c_str()); + } + + Py_DECREF(elementTreeToStringFunc); + Py_DECREF(pElemString); + } + else + { + PyObject* valueRepr = PyObject_Repr(pValue); + PyObject* valueType = PyObject_Type(pValue); + PyObject* valueTypeRepr = PyObject_Repr(valueType); + loginfo("Return value of unknown type (%s) has repr: %s", PyString_AsString(valueTypeRepr), PyString_AsString(valueRepr)); + Py_DECREF(valueTypeRepr); + Py_DECREF(valueType); + Py_DECREF(valueRepr); + } + + Py_DECREF(pIsElement); + } + + Py_DECREF(elementTreeModule); + Py_DECREF(elementTreeModuleName); + Py_DECREF(pValue); + } + else + { + Py_DECREF(pFunc); + Py_XDECREF(elementTreeModule); + Py_XDECREF(elementTreeModuleName); + + string msg = "Error whilst calling Python function "+operation.getName()+": "; + if(PyErr_Occurred()) + { + PyObject *pErrorType, *pErrorValue, *pErrorTraceback; + PyErr_Fetch(&pErrorType, &pErrorValue, &pErrorTraceback); + + if (pErrorType != NULL && pErrorValue != NULL) + { + PyObject* pErrorTypeStr = PyObject_Str(pErrorType); + PyObject* pErrorValueStr = PyObject_Str(pErrorValue); + msg += PyString_AsString(pErrorTypeStr); + msg += " : "; + msg += PyString_AsString(pErrorValueStr); + Py_DECREF(pErrorTypeStr); + Py_DECREF(pErrorValueStr); + } + else + { + msg += "No Python Error information provided"; + } + Py_XDECREF(pErrorType); + Py_XDECREF(pErrorValue); + Py_XDECREF(pErrorTraceback); + + PyErr_Print(); + } + + throwException(ServiceInvocationException, msg.c_str()); + } + } + else + { + if (PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Cannot find the operation named " + operation.getName() + " in the Python module"; + throwException(ServiceInvocationException, msg.c_str()); + } + Py_XDECREF(pFunc); + + } + catch (...) + { + releaseInstance(); + runtime->unsetCurrentComponent(); + throw; + } + releaseInstance(); + runtime->unsetCurrentComponent(); + } + + + // ========================================================================== + // Add any properties into the loaded implementation module as Python objects + // ========================================================================== + void PythonServiceWrapper::addProperties(PyObject* module) + { + logentry(); + + // Set all the configured properties + DataObjectPtr properties = component->getProperties(); + PropertyList pl = properties->getInstanceProperties(); + + for (unsigned int i = 0; i < pl.size(); i++) + { + if (properties->isSet(pl[i])) + { + string propName = pl[i].getName(); + string propValue = properties->getCString(pl[i]); + PyObject* property; + + if(pl[i].isMany()) + { + //TODO - deal with properties that are many + } + + switch(pl[i].getTypeEnum()) + { + case Type::BooleanType: + { + if(properties->getBoolean(pl[i])) + { + property = Py_True; + } + else + { + property = Py_False; + } + Py_INCREF(property); + break; + } + case Type::BigIntegerType: + case Type::BigDecimalType: + case Type::LongType: + { + property = PyLong_FromLongLong(properties->getLong(pl[i])); + break; + } + case Type::ShortType: + case Type::IntegerType: + { + property = PyInt_FromLong(properties->getInteger(pl[i])); + break; + } + case Type::DoubleType: + case Type::FloatType: + { + property = PyFloat_FromDouble(properties->getDouble(pl[i])); + break; + } + case Type::DataObjectType: + case Type::OpenDataObjectType: + { + // Serialize a DataObject and create a python string object from the XML + DataObjectPtr data = properties->getDataObject(pl[i]); + XMLHelperPtr helper = HelperProvider::getXMLHelper(properties->getDataFactory()); + string serializedData = helper->save(data, + data->getType().getURI(), + data->getType().getName()); + + loginfo("Converting SDO DataObject to Python ElementTree: %s", serializedData.c_str()); + + // Get the xml.etree.ElementTree.XML function + PyObject* elementTreeModuleName = PyString_FromString("xml.etree.ElementTree"); + PyObject* elementTreeModule = PyImport_Import(elementTreeModuleName); + PyObject* elementTreeXMLFunc = PyObject_GetAttrString(elementTreeModule, "XML"); + + // Call the XML() function with the XML string + property = PyObject_CallFunction(elementTreeXMLFunc, "s", serializedData.c_str()); + + Py_DECREF(elementTreeXMLFunc); + Py_DECREF(elementTreeModule); + Py_DECREF(elementTreeModuleName); + break; + } + case Type::CharacterType: + case Type::StringType: + case Type::TextType: + case Type::UriType: + default: + { + // For strings and by default create a python string object + property = PyString_FromString(propValue.c_str()); + break; + } + } + + int success = PyModule_AddObject(module, (char*)propName.c_str(), property); + + if(success == 0) + { + loginfo("Added property named %s with type %s and value %s to python module", propName.c_str(), pl[i].getType().getName(), propValue.c_str()); + } + else + { + logwarning("Failed to add property named %s to python module", propName.c_str()); + } + } + } + } + + + // ====================================================================== + // Add any references into the loaded implementation module as class instances that look like + // the classes defined in the interface.python xml + // ====================================================================== + void PythonServiceWrapper::addReferences(PyObject* module) + { + logentry(); + + // Import the TuscanySCA python-extension module + PyObject* pModuleName = PyString_FromString("sca_proxy"); + PyObject* sca_proxy_module = PyImport_Import(pModuleName); + Py_DECREF(pModuleName); + + if(!sca_proxy_module) + { + if(PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Failed to load the sca_proxy Python module - has it been successfully installed?\nReferences from Python components will not be supported"; + logwarning(msg.c_str()); + } + else + { + // Get the sca_proxy class + PyObject* sca_proxy_class = PyObject_GetAttrString(sca_proxy_module, "sca_proxy_class"); + + // Iterate through the references of the current component, adding + // each reference to the module + Component::REFERENCE_MAP references = component->getReferences(); + Component::REFERENCE_MAP::iterator pos; + for( pos = references.begin(); pos != references.end(); ++pos) + { + ReferenceType* referenceType = ((Reference*) pos->second)->getType(); + string referenceName = referenceType->getName(); + + PyObject* tuscanySCAArgs = PyTuple_New(2); + PyObject* refName = PyString_FromString(referenceType->getName().c_str()); + PyTuple_SetItem(tuscanySCAArgs, 0, refName); + Py_INCREF(Py_True); + PyTuple_SetItem(tuscanySCAArgs, 1, Py_True); + + // Create the instance of the TuscanySCAReference class + PyObject* sca_proxy_classInstance = PyInstance_New(sca_proxy_class, tuscanySCAArgs, NULL); + Py_DECREF(tuscanySCAArgs); + + int success = PyModule_AddObject(module, (char*)referenceName.c_str(), sca_proxy_classInstance); + + if(success == 0) + { + loginfo("Successfully added sca_proxy_class instance as %s to pythonModule", referenceName.c_str()); + } + else + { + logwarning("Failed to add sca_proxy_class instance as %s to pythonModule", referenceName.c_str()); + } + } + Py_DECREF(sca_proxy_module); + } + } + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.h new file mode 100644 index 0000000000..fbf75b3223 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/PythonServiceWrapper.h @@ -0,0 +1,142 @@ +/* + * 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$ */ + + +#ifndef tuscany_sca_python_pythonservicewrapper_h +#define tuscany_sca_python_pythonservicewrapper_h + + +// undefine _DEBUG so Python does not need it's deebug dll +#ifdef _DEBUG +#undef _DEBUG +#define _SCA_PYTHON_DEBUG +#endif +#include +#ifdef _SCA_PYTHON_DEBUG +#define _DEBUG +#endif + +#include "tuscany/sca/python/export.h" +#include "tuscany/sca/core/ServiceWrapper.h" +#include "tuscany/sca/core/Operation.h" +#include "tuscany/sca/model/Component.h" +#include "tuscany/sca/model/Interface.h" +#include "tuscany/sca/python/model/PythonImplementation.h" + + +namespace tuscany +{ + namespace sca + { + namespace python + { + class PythonInterface; + + /** + * Wraps the service on a component implementation. + * This abstract class is extended by generated code which provides + * the implementation of some of the methods. + * An instance of this class wraps the actual component implementation which + * has been written by a developer of an SCA application. + */ + class PythonServiceWrapper : public ServiceWrapper + { + public: + + /** + * Constructor. + * @param target The component service to which this wrapper refers. + */ + PythonServiceWrapper(tuscany::sca::model::Service* service); + + /** + * Destructor. + */ + virtual ~PythonServiceWrapper(); + + /** + * All business method calls to the target component go through the invoke method. + * @param operation The details of the method, paramaters and return value for the + * business method to be called on the target component. + */ + virtual void invoke(Operation& operation); + + + protected: + + /** + * Return the current instance of the python class. + * @return A pointer to an instance of the python class. + */ + virtual PyObject* getInstance(); + + /** + * Creates a new instance of the python class. + * @return A pointer to a new instance of the python class. + */ + virtual PyObject* newInstance(); + + /** + * Indicates that the current instance of the python module or class + * has been finished with. + */ + virtual void releaseInstance(); + + + private: + /** + * Holds a class instance if a classname is provided. + * Will be constructed each time if scope is set to STATELESS + */ + PyObject* pythonClassInstance; + + /** + * Holds the module + */ + PyObject* pythonModule; + + /** + * Adds references to the provided implementation module or class instance + */ + void addReferences(PyObject* module); + + /** + * Adds properties to the provided implementation module or class instance + */ + void addProperties(PyObject* module); + + /** + * The component to which this wrapper refers. + */ + tuscany::sca::model::Component* component; + + /** + * The component implementation + */ + PythonImplementation* implementation; + + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_pythonservicewrapper_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/export.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/export.h new file mode 100644 index 0000000000..b608a50711 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/export.h @@ -0,0 +1,41 @@ +/* + * 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$ */ + +#ifndef tuscany_sca_python_export_h +#define tuscany_sca_python_export_h + +#if defined(WIN32) || defined (_WINDOWS) +#pragma warning(disable: 4786) + +#ifdef TUSCANY_SCA_PYTHON_EXPORTS +#define SCA_PYTHON_API __declspec(dllexport) +#else +#define SCA_PYTHON_API __declspec(dllimport) +#endif + +#else +#include +#include +#include +#define SCA_PYTHON_API +#endif + +#endif // tuscany_sca_export_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.cpp new file mode 100644 index 0000000000..235468eca9 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.cpp @@ -0,0 +1,131 @@ +/* + * 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/util/Logging.h" +#include "tuscany/sca/python/model/PythonImplementation.h" +#include "tuscany/sca/python/model/PythonServiceBinding.h" +#include "tuscany/sca/python/model/PythonReferenceBinding.h" +#include "tuscany/sca/model/Component.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/util/Utils.h" + +using namespace std; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + + namespace python + { + + // Constructor + PythonImplementation::PythonImplementation( + Composite* composite, const string& module, const string& modulePath, const string& className, Scope scope) + : ComponentType(composite, modulePath + "/" + module), + module(module), modulePath(modulePath), className(className), scope(scope) + { + logentry(); + + // Create a default service for this componentType + ServiceType* defaultServiceType = new ServiceType(this, "", NULL, NULL); + addServiceType(defaultServiceType); + } + + PythonImplementation::~PythonImplementation() + { + logentry(); + } + + /** + * Overrides the findReferenceType method in ComponentType. + * This allows us to create references without needing a componentType file. + */ + ReferenceType* PythonImplementation::findReferenceType(const string& referenceName) + { + logentry(); + + ReferenceType* refType = ComponentType::findReferenceType(referenceName); + if(!refType) + { + // The reference has not yet been created - try creating it + refType = new ReferenceType(this, referenceName, NULL, NULL, ReferenceType::ONE_ONE); + addReferenceType(refType); + } + + return refType; + } + + /** + * Overrides the findPropertyType method in ComponentType. + * This allows us to create properties without needing a componentType file. + */ + const commonj::sdo::Property* PythonImplementation::findPropertyType(const string& propertyName) + { + logentry(); + + const commonj::sdo::Property* prop = ComponentType::findPropertyType(propertyName); + if(!prop) + { + ComponentType::addPropertyType(propertyName, "http://www.w3.org/2001/XMLSchema#string", false, NULL); + // Just added it so it should now be available + prop = ComponentType::findPropertyType(propertyName); + loginfo("Added string property named %s to Python component", propertyName.c_str()); + } + + return prop; + } + + void PythonImplementation::initializeComponent(Component* component) + { + logentry(); + ComponentType::initializeComponent(component); + + // Create Python bindings for all the services + const Component::SERVICE_MAP& services = component->getServices(); + Component::SERVICE_MAP::const_iterator iter = services.begin(); + for (unsigned int i=0; i< services.size(); i++) + { + Service *service = iter->second; + PythonServiceBinding* binding = new PythonServiceBinding(service); + service->setBinding(binding); + iter++; + } + + // Create Python bindings for 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; + PythonReferenceBinding* binding = new PythonReferenceBinding(reference); + reference->setBinding(binding); + refiter++; + } + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.h new file mode 100644 index 0000000000..75b14529bf --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonImplementation.h @@ -0,0 +1,145 @@ +/* + * 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$ */ + + +#ifndef tuscany_sca_python_model_pythonimplementation_h +#define tuscany_sca_python_model_pythonimplementation_h + +#include + +#include "commonj/sdo/SDO.h" + +#include "tuscany/sca/model/ComponentType.h" + + +namespace tuscany +{ + namespace sca + { + namespace python + { + /** + * Holds information about an SCA implementation written in Python + */ + class PythonImplementation : public tuscany::sca::model::ComponentType + { + + public: + /** + * Scope of the component implementation. + */ + enum Scope + { + COMPOSITE, + STATELESS + }; + + /** + * Constructor. + * @param composite The composite containing this implementation. + * @param module Name of the module. + * @param modulePath Path to the module (could be a blank string + * if this is not specified). + * @param className Name of the class in the module (could be a blank string + * if this is not specified). + */ + PythonImplementation(tuscany::sca::model::Composite* composite, + const std::string& module, const std::string& modulePath, const std::string& className, + Scope scope); + + /** + * Destructor + */ + virtual ~PythonImplementation(); + + /** + * Initialize a component of this type. + * @param component The component to initialize. + */ + virtual void initializeComponent(tuscany::sca::model::Component* component); + + /** + * Override the ComponentType::findReferenceType method + * to allow Python components to be defined without requiring + * a componentType side-file + */ + virtual tuscany::sca::model::ReferenceType* findReferenceType(const std::string& referenceName); + + /** + * Override the ComponentType::findPropertyType method + * to allow Python components to be defined without requiring + * a componentType side-file + */ + virtual const commonj::sdo::Property* findPropertyType(const std::string& propertyName); + + + /** + * Returns the name of the module. + * @return The name of the module. + */ + const std::string& getModule() const { return module; } + + /** + * Get the header path. + * @return The pathe element of the header. + */ + const std::string& getModulePath() const { return modulePath; } + + /** + * Get the name of the class. + * @return The class name if specified. + */ + const std::string& getClass() const { return className; } + + /** + * Returns the implementation scope + */ + Scope getScope() const { return scope; } + + private: + + /** + * Name of the module. + */ + std::string module; + + /** + * Path to the module. + */ + std::string modulePath; + + /** + * Name of the class in the header file declaring the implementation. + * May be an empty string if not set in the SCDL file. + */ + std::string className; + + /** + * The implementation scope + */ + Scope scope; + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_model_pythonimplementation_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.cpp new file mode 100644 index 0000000000..3c30f363b8 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.cpp @@ -0,0 +1,53 @@ +/* + * 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/util/Logging.h" +#include "tuscany/sca/python/export.h" +#include "tuscany/sca/python/model/PythonInterface.h" + +using namespace std; + +namespace tuscany +{ + namespace sca + { + namespace python + { + const string PythonInterface::typeQName("http://www.osoa.org/xmlns/sca/1.0#PythonInterface"); + + // Constructor + PythonInterface::PythonInterface( + bool remotable, + bool conversational) + : Interface(remotable, conversational) + { + logentry(); + } + + PythonInterface::~PythonInterface() + { + logentry(); + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.h new file mode 100644 index 0000000000..cfc2ca8914 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonInterface.h @@ -0,0 +1,77 @@ +/* + * 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$ */ + + +#ifndef tuscany_sca_python_model_pythoninterface_h +#define tuscany_sca_python_model_pythoninterface_h + +#include + +#include "tuscany/sca/python/export.h" +#include "tuscany/sca/model/Interface.h" + +namespace tuscany +{ + namespace sca + { + namespace python + { + /** + * Holds information about an interface described using a Python + * header file. + */ + class PythonInterface : public tuscany::sca::model::Interface + { + + public: + /** + * Constuctor. + * @param scope The scope of the interface (stateless or composite). + * @param remotable True if the interface is remotable. + */ + PythonInterface( + bool remotable, + bool conversational); + + /** + * Destructor. + */ + virtual ~PythonInterface(); + + /** + * return the QName of the schema type for this interface type + * (e.g. "http://www.osoa.org/xmlns/sca/1.0#interface.cpp") + */ + const std::string& getInterfaceTypeQName() { return typeQName; }; + + /** + * The QName of the schema type for this interface type. + */ + SCA_PYTHON_API static const std::string typeQName; + + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_model_pythoninterface_h + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.cpp new file mode 100644 index 0000000000..c2564c4db1 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.cpp @@ -0,0 +1,61 @@ +/* + * 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/util/Logging.h" +#include "tuscany/sca/python/model/PythonReferenceBinding.h" +#include "tuscany/sca/python/PythonServiceProxy.h" + +using namespace std; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + + // Constructor + PythonReferenceBinding::PythonReferenceBinding(Reference* reference) + : ReferenceBinding(reference, ""), serviceProxy(NULL) + { + } + + // Destructor + PythonReferenceBinding::~PythonReferenceBinding() + { + } + + ServiceProxy* PythonReferenceBinding::getServiceProxy() + { + return serviceProxy; + } + + void PythonReferenceBinding::configure(ServiceBinding* binding) + { + targetServiceBinding = binding; + + serviceProxy = new PythonServiceProxy(getReference()); + } + + } // End namespace python + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.h new file mode 100644 index 0000000000..f993730d8e --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonReferenceBinding.h @@ -0,0 +1,92 @@ +/* + * 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$ */ + +#ifndef tuscany_sca_python_model_pythonreferencebinding_h +#define tuscany_sca_python_model_pythonreferencebinding_h + +#include + +#include "tuscany/sca/model/ReferenceBinding.h" + + +namespace tuscany +{ + namespace sca + { + namespace python + { + /** + * Information about a Python service binding for service or a reference. + */ + class PythonReferenceBinding : public tuscany::sca::model::ReferenceBinding + { + public: + + /** + * Constructor. + */ + PythonReferenceBinding(tuscany::sca::model::Reference* reference); + + /** + * Destructor. + */ + virtual ~PythonReferenceBinding(); + + /** + * Returns the type of binding. + */ + virtual std::string getType() { return "http://www.osoa.org/xmlns/sca/1.0#PythonImplementationBinding"; }; + + /** + * Create a proxy representing the reference to the + * client component. + */ + virtual ServiceProxy* getServiceProxy(); + + /** + * Configure this binding from a service binding. + */ + virtual void configure(tuscany::sca::model::ServiceBinding* serviceBinding); + + /** + * Returns the target service binding. + */ + tuscany::sca::model::ServiceBinding* getTargetServiceBinding() const { return targetServiceBinding; }; + + private: + + /** + * The proxy representing the reference to the client + * component. + */ + ServiceProxy* serviceProxy; + + /** + * The service binding of the target + */ + tuscany::sca::model::ServiceBinding* targetServiceBinding; + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_model_pythonreferencebinding_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.cpp new file mode 100644 index 0000000000..061aeb7515 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.cpp @@ -0,0 +1,58 @@ +/* + * 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/util/Logging.h" +#include "tuscany/sca/python/model/PythonServiceBinding.h" +#include "tuscany/sca/python/PythonServiceWrapper.h" + +using namespace std; +using namespace tuscany::sca::model; + +namespace tuscany +{ + namespace sca + { + namespace python + { + + // Constructor + PythonServiceBinding::PythonServiceBinding(Service* service) + : ServiceBinding(service, "") + { + logentry(); + serviceWrapper = new PythonServiceWrapper(service); + } + + // Destructor + PythonServiceBinding::~PythonServiceBinding() + { + logentry(); + } + + ServiceWrapper* PythonServiceBinding::getServiceWrapper() + { + logentry(); + return (ServiceWrapper*)serviceWrapper; + } + + } // End namespace ws + } // End namespace sca +} // End namespace tuscany diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.h new file mode 100644 index 0000000000..9a803cdced --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/model/PythonServiceBinding.h @@ -0,0 +1,81 @@ +/* + * 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$ */ + + +#ifndef tuscany_sca_python_model_pythonservicebinding_h +#define tuscany_sca_python_model_pythonservicebinding_h + +#include + +#include "tuscany/sca/model/ServiceBinding.h" + +namespace tuscany +{ + namespace sca + { + namespace python + { + /** + * Information about a Python service binding for service or a reference. + */ + class PythonServiceBinding : public tuscany::sca::model::ServiceBinding + { + public: + + /** + * Constructor. + * @param uri The uri of the binding. + * @param port The definition of the port to which the entrypoint + * or external service is to be bound. This is of the form + * "namespace"#endpoint("service"/"port") + */ + PythonServiceBinding(tuscany::sca::model::Service* service); + + /** + * Destructor. + */ + virtual ~PythonServiceBinding(); + + /** + * Returns the type of binding. + */ + virtual std::string getType() { return "http://www.osoa.org/xmlns/sca/1.0#PythonImplementationBinding"; }; + + /** + * Create a wrapper for the service configured by this + * binding. + */ + virtual ServiceWrapper* getServiceWrapper(); + + private: + + /** + * The wrapper for the service configured by this binding. + */ + ServiceWrapper* serviceWrapper; + + }; + + } // End namespace python + } // End namespace sca +} // End namespace tuscany + +#endif // tuscany_sca_python_model_pythonservicebinding_h diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_module.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_module.cpp new file mode 100644 index 0000000000..bd34549f8a --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_module.cpp @@ -0,0 +1,540 @@ +/* + * 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 +#include +#include + +// undefine _DEBUG so Python does not need it's debug dll +#ifdef _DEBUG +#undef _DEBUG +#define _SCA_PYTHON_DEBUG +#endif +#include +#ifdef _SCA_PYTHON_DEBUG +#define _DEBUG +#endif + +#include "commonj/sdo/SDO.h" + +#include "PythonServiceProxy.h" +#include "tuscany/sca/util/Logging.h" +#include "tuscany/sca/core/Exceptions.h" +#include "tuscany/sca/core/SCARuntime.h" +#include "tuscany/sca/model/Component.h" +#include "tuscany/sca/model/Reference.h" +#include "tuscany/sca/model/ReferenceType.h" +#include "tuscany/sca/model/ServiceBinding.h" +#include "tuscany/sca/core/Operation.h" + +using namespace std; +using namespace commonj::sdo; +using namespace tuscany::sca; +using namespace tuscany::sca::model; + +static PyObject* scaError; + +/** +* Prints out PyObject and dir(PyObject) +* for debugging purposes +*/ +static void printPyObject(char* prefix, char* name, PyObject* pObj) +{ + PyObject* pObjRepr = PyObject_Repr(pObj); + PyTypeObject* type = pObj->ob_type; + loginfo("%s printPyObject (%s) %s = %s", prefix, type->tp_name, name, PyString_AsString(pObjRepr)); + Py_XDECREF(pObjRepr); + + if(pObj != NULL) + { + PyObject* pObjDir = PyObject_Dir(pObj); + PyObject* pObjDirRepr = PyObject_Repr(pObjDir); + loginfo("%s printPyObject dir(%s): %s", prefix, name, PyString_AsString(pObjDirRepr)); + Py_DECREF(pObjDirRepr); + Py_DECREF(pObjDir); + } +} + +static PyObject* sca_locateservice(PyObject *self, PyObject *args) +{ + logentry(); + + // Get the service name + PyObject* pServiceName = PyTuple_GetItem(args, 0); + + // Import the SCA python-extension module + PyObject* pModuleName = PyString_FromString("sca_proxy"); + PyObject* sca_proxy_module = PyImport_Import(pModuleName); + Py_DECREF(pModuleName); + + if(!sca_proxy_module) + { + if(PyErr_Occurred()) + { + PyErr_Print(); + } + string msg = "Failed to load the sca_proxy Python module - has it been successfully installed?\nReferences from Python components will not be supported"; + logerror(msg.c_str()); + } + else + { + // Get the sca_proxy class + PyObject* sca_proxy_class = PyObject_GetAttrString(sca_proxy_module, "sca_proxy_class"); + + PyObject* scaArgs = PyTuple_New(2); + PyTuple_SetItem(scaArgs, 0, pServiceName); + Py_INCREF(Py_True); + PyTuple_SetItem(scaArgs, 1, Py_False); + + // Create the instance of the scaReference class + PyObject* sca_proxy_classInstance = PyInstance_New(sca_proxy_class, scaArgs, NULL); + Py_DECREF(scaArgs); + + return sca_proxy_classInstance; + } + + Py_INCREF(Py_None); + return Py_None; +} + + +static tuscany::sca::python::PythonServiceProxy* getServiceProxy(PyObject *args) +{ + logentry(); + + tuscany::sca::python::PythonServiceProxy* serviceProxy = NULL; + SCARuntime* runtime = SCARuntime::getCurrentRuntime(); + + // The first argument holds the name + string name; + PyObject* pName = PyTuple_GetItem(args, 0); + if(pName && PyString_Check(pName)) + { + name = PyString_AsString(pName); + } + if(name.size() > 0) + { + loginfo("Service/Reference name is %s", name.c_str()); + } + else + { + string msg = "Service/Reference name has not been set"; + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + + // The second argument is a boolean + PyObject* isReference = PyTuple_GetItem(args, 1); + + // Get the serviceProxy from the reference or service name provided + if(PyObject_IsTrue(isReference)) + { + Component* component = runtime->getCurrentComponent(); + Reference* ref = component->findReference(name); + if(!ref) + { + string msg = "Could not find the reference: "+name; + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + + return NULL; + } + + ReferenceBinding* refBinding = ref->getBinding(); + serviceProxy = (tuscany::sca::python::PythonServiceProxy*) refBinding->getServiceProxy(); + } + else + { + Component* component = runtime->getDefaultComponent(); + Composite* composite = (Composite*)component->getType(); + Service* service = composite->findComponentService(name); + + if(!service) + { + string msg = "Could not find service: "+name; + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + + serviceProxy = new tuscany::sca::python::PythonServiceProxy(service); + } + + return serviceProxy; +} + + +static PyObject* sca_invoke(PyObject *self, PyObject *args) +{ + logentry(); + + tuscany::sca::python::PythonServiceProxy* pythonServiceProxy = getServiceProxy(args); + if(!pythonServiceProxy) + { + return NULL; + } + + // Get the component from the reference or service provided + Component* component = NULL; + SCARuntime* runtime = SCARuntime::getCurrentRuntime(); + + PyObject* isReference = PyTuple_GetItem(args, 1); + if(PyObject_IsTrue(isReference)) + { + component = runtime->getCurrentComponent(); + } + else + { + component = runtime->getDefaultComponent(); + } + + // Get the name of the operation to invoke + string operationName; + PyObject* opName = PyTuple_GetItem(args, 2); + if(opName && PyString_Check(opName)) + { + operationName = PyString_AsString(opName); + } + + if(operationName.size() > 0) + { + loginfo("sca_invoke Operation name: %s", operationName.c_str()); + } + else + { + string msg = "Operation name has not been set"; + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + + // Create the Operation object + Operation operation(operationName.c_str()); + + // Load up the xml.etree.ElementTree module for dealing with SDO params and return values + PyObject* elementTreeModuleName = PyString_FromString("xml.etree.ElementTree"); + PyObject* elementTreeModule = PyImport_Import(elementTreeModuleName); + + if(elementTreeModule == NULL) + { + // pre-Python2.5? - try to get an installed elementtree package + elementTreeModuleName = PyString_FromString("elementtree.ElementTree"); + elementTreeModule = PyImport_Import(elementTreeModuleName); + } + if(elementTreeModule == NULL) + { + // Still null - throw a warning but carry on - user may not need XML + logwarning("Could not load Python ElementTree module - is it installed? SDO and XML will not be supported"); + } + + // Parameters are the fourth argument + PyObject* paramTuple = PyTuple_GetItem(args, 3); + unsigned int numberOfArgs = (unsigned int) PyTuple_Size(paramTuple); + loginfo("sca_invoke %d arg parameters supplied", numberOfArgs); + + // Keyword parameters (AKA named arguments) are the fifth argument + PyObject* keywordParamDict = PyTuple_GetItem(args, 4); + loginfo("sca_invoke %d keyword parameters supplied", PyDict_Size(keywordParamDict)); + + PyObject* paramKeys = PyDict_Keys(keywordParamDict); + + // Go through all the supplied parameters (args and keyword args) + for(unsigned int i=0; i < (numberOfArgs + PyList_Size(paramKeys)); i++) + { + string* paramName; + PyObject* param; + + if(i < PyTuple_Size(paramTuple)) + { + param = PyTuple_GetItem(paramTuple, i); + paramName = new string(); + } + else + { + PyObject* key = PyList_GetItem(paramKeys, i-numberOfArgs); + param = PyDict_GetItem(keywordParamDict, key); + paramName = new string(PyString_AsString(key)); + } + + if(PyInt_Check(param)) + { + loginfo("Int param %d %s: %d", i, (*paramName).c_str(), PyInt_AsLong(param)); + long* intData = new long; + *intData = PyInt_AsLong(param); + operation.addParameter(*paramName, intData); + } + else if(PyBool_Check(param)) + { + loginfo("Bool param %d %s: %d", i, (*paramName).c_str(), (param == Py_True)); + bool* boolData = new bool; + *boolData = (param == Py_True); + operation.addParameter(*paramName, boolData); + } + else if(PyLong_Check(param)) + { + loginfo("Long param %d %s: %l", i, (*paramName).c_str(), PyLong_AsLong(param)); + long* longData = new long; + *longData = PyLong_AsLong(param); + operation.addParameter(*paramName, longData); + } + else if(PyFloat_Check(param)) + { + loginfo("Float param %d %s: %f", i, (*paramName).c_str(), PyFloat_AsDouble(param)); + double* doubleData = new double; + *doubleData = PyFloat_AsDouble(param); + operation.addParameter(*paramName, doubleData); + } + else if(PyString_Check(param)) + { + loginfo("String param %d %s: %s", i, (*paramName).c_str(), PyString_AsString(param)); + const char** stringData = new const char*; + *stringData = PyString_AsString(param); + operation.addParameter(*paramName, stringData); + } + else + { + PyObject* pIsElement = Py_False; + if(elementTreeModule != NULL) + { + // Get the xml.etree.ElementTree.iselement function + PyObject* elementTreeIsElementFunc = PyObject_GetAttrString(elementTreeModule, "iselement"); + + // Call the iselement() function with pValue to check it + pIsElement = PyObject_CallFunction(elementTreeIsElementFunc, "O", param); + } + + if(PyObject_IsTrue(pIsElement) == 1) + { + // pValue is an xml.etree.ElementTree.Element - convert to SDO + PyObject* elementTreeToStringFunc = PyObject_GetAttrString(elementTreeModule, "tostring"); + PyObject* pElemString = PyObject_CallFunction(elementTreeToStringFunc, "O", param); + char* data = PyString_AsString(pElemString); + loginfo("SDO param %d %s: %s", i, (*paramName).c_str(), data); + + loginfo("Converting Python ElementTree to SDO DataObject: %s", data); + + Composite* composite = component->getComposite(); + XMLHelper* xmlHelper = composite->getXMLHelper(); + XMLDocumentPtr xmlDoc = xmlHelper->load(data); + + DataObjectPtr* dataObjectData = new DataObjectPtr; + if (xmlDoc != NULL) + { + *dataObjectData = xmlDoc->getRootDataObject(); + } + else + { + *dataObjectData = NULL; + } + if (*dataObjectData != NULL) + { + operation.addParameter(*paramName, dataObjectData); + } + else + { + string msg = "xml.etree.ElementTree.Element could not be converted to a DataObject"; + logerror(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + Py_DECREF(elementTreeToStringFunc); + Py_DECREF(pElemString); + } + else + { + + PyObject* paramRepr = PyObject_Repr(param); + PyObject* paramType = PyObject_Type(param); + PyObject* paramTypeRepr = PyObject_Repr(paramType); + + string msg = "sca_invoke Param "; + msg += i; + msg += "is of unknown type ("; + msg += PyString_AsString(paramTypeRepr); + msg += ") and has repr: "; + msg += PyString_AsString(paramRepr); + + logerror(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + + Py_DECREF(paramTypeRepr); + Py_DECREF(paramType); + Py_DECREF(paramRepr); + + return NULL; + } + } + } + + PyObject* returnValue = NULL; + + try + { + // Invoke the wired service + pythonServiceProxy->invokeService(operation); + } + catch(TuscanyRuntimeException& ex) + { + string msg = "Exception whilst invoking the "; + msg += operationName.c_str(); + msg += " operation on an SCA service/reference: "; + msg += ex.getEClassName(); + msg += ": "; + msg += ex.getMessageText(); + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + catch(...) + { + string msg = "Exception whilst invoking the "; + msg += operationName.c_str(); + msg += " operation on an SCA service/reference"; + + logwarning(msg.c_str()); + PyErr_SetString(scaError, msg.c_str()); + return NULL; + } + + + switch(operation.getReturnType()) + { + case Operation::BOOL: + { + if(*(bool*)operation.getReturnValue()) + { + returnValue = Py_True; + } + else + { + returnValue = Py_False; + } + break; + } + case Operation::SHORT: + { + returnValue = PyInt_FromLong(*(short*)operation.getReturnValue()); + break; + } + case Operation::LONG: + { + returnValue = PyLong_FromLong(*(long*)operation.getReturnValue()); + break; + } + case Operation::USHORT: + { + returnValue = PyInt_FromLong(*(unsigned short*)operation.getReturnValue()); + break; + } + case Operation::ULONG: + { + returnValue = PyLong_FromLong(*(unsigned long*)operation.getReturnValue()); + break; + } + case Operation::FLOAT: + { + returnValue = PyFloat_FromDouble(*(float*)operation.getReturnValue()); + break; + } + case Operation::DOUBLE: + { + returnValue = PyFloat_FromDouble(*(double*)operation.getReturnValue()); + break; + } + case Operation::LONGDOUBLE: + { + returnValue = PyFloat_FromDouble(*(long double*)operation.getReturnValue()); + break; + } + case Operation::CHARS: + { + returnValue = PyString_FromString(*(char**)operation.getReturnValue()); + break; + } + case Operation::STRING: + { + returnValue = PyString_FromString((*(string*)operation.getReturnValue()).c_str()); + break; + } + case Operation::DATAOBJECT: + { + if(elementTreeModule != NULL) + { + DataObjectPtr dob = *(DataObjectPtr*)operation.getReturnValue(); + + // Convert a DataObject to a xml.etree.ElementTree Element object + Composite* composite = component->getComposite(); + XMLHelper* xmlHelper = composite->getXMLHelper(); + char* str = xmlHelper->save( + dob, + dob->getType().getURI(), + dob->getType().getName()); + + loginfo("Converting SDO DataObject to Python ElementTree: %s", str); + + // Get the xml.etree.ElementTree.XML function + PyObject* elementTreeXMLFunc = PyObject_GetAttrString(elementTreeModule, "XML"); + + // Call the XML() function with the XML string + returnValue = PyObject_CallFunction(elementTreeXMLFunc, "s", str); + + Py_DECREF(elementTreeXMLFunc); + } + else + { + logwarning("Could not convert SDO DataObject to Python ElementTree as ElementTree module could not be loaded. Returning NONE"); + Py_INCREF(Py_None); + returnValue = Py_None; + } + break; + } + default: + { + Py_INCREF(Py_None); + returnValue = Py_None; + } + + } + + Py_XDECREF(elementTreeModuleName); + Py_XDECREF(elementTreeModule); + + return returnValue; +} +static PyMethodDef ModuleMethods[] = +{ + {"locateservice", (PyCFunction) sca_locateservice, METH_VARARGS, "Locates an SCA service & returns an sca_proxy_class instance"}, + {"invoke", (PyCFunction) sca_invoke, METH_VARARGS, "Invoke an operation on an SCA service or reference"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC initsca(void) +{ + logentry(); + + // Create a new module + PyObject* module = Py_InitModule("sca", ModuleMethods); + + scaError = PyErr_NewException("sca.error", NULL, NULL); + Py_INCREF(scaError); + PyModule_AddObject(module, "error", scaError); +} diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_proxy.py b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_proxy.py new file mode 100644 index 0000000000..92a224275e --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/src/tuscany/sca/python/sca_proxy.py @@ -0,0 +1,57 @@ +# 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. +# +# +# +# +# This Python code is used in the SCA package and +# provides the proxy objects to a Python SCA component or SCA +# client. +# +# This is done by overloading the __getattr__ method which makes +# calls to myProxy.anyMethod go to __getattr__ which will return +# the invokeFunction defined inside the invoke method + +import sca + +class sca_proxy_class: + + sca_proxy_name = '' + sca_proxy_is_reference = 1 + + def __init__(self, name, isReference): + self.sca_proxy_name = name + self.sca_proxy_is_reference = isReference + return + + def invoke(self, operationName): + + def invokeFunction(*args, **kwargs): + # Pass the args and keywords in to the invoke method as arguments + return sca.invoke(self.sca_proxy_name, self.sca_proxy_is_reference, operationName, args, kwargs) + + return invokeFunction + + def __getattr__(self, operationName): + return self.invoke(operationName) + + def __str__(self): + return '' + + def __repr__(self): + return '' + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-implementation-python.xsd b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-implementation-python.xsd new file mode 100644 index 0000000000..e1c7247992 --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-implementation-python.xsd @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-interface-python.xsd b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-interface-python.xsd new file mode 100644 index 0000000000..dd9075c7fb --- /dev/null +++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/python/xsd/sca-interface-python.xsd @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3