summaryrefslogtreecommitdiffstats
path: root/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest')
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/Makefile.am6
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/deploy.bat45
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/Makefile.am1
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/deploy.bat66
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/Makefile.am25
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.cpp85
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.h76
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/exportinterface.h38
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.cpp51
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.h80
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/Makefile.am1
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/Makefile.am1
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/Makefile.am31
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.cpp89
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.h75
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp1222
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.h90
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.cpp59
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.h76
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/deploy.bat68
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/Makefile.am1
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploy.bat66
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploymod.bat63
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/Makefile.am1
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/Makefile.am44
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp1351
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.cpp86
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.h75
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp559
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.h95
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/export.h38
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.cpp66
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.h90
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-binding-rest.xsd34
-rw-r--r--tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-interface-rest.xsd38
35 files changed, 4792 insertions, 0 deletions
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/Makefile.am
new file mode 100644
index 0000000000..742a8152ad
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = interface reference service
+datadir=$(prefix)/extensions/rest
+
+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/rest/deploy.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/deploy.bat
new file mode 100644
index 0000000000..6ad4ef66ea
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/deploy.bat
@@ -0,0 +1,45 @@
+@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 restextdir=%extdir%\rest
+set srcdir=%rootdir%\runtime\extensions\rest
+
+if not exist %deploydir% mkdir %deploydir%
+if not exist %extdir% mkdir %extdir%
+if not exist %restextdir% mkdir %restextdir%
+if not exist %restextdir%\xsd mkdir %restextdir%\xsd
+
+copy %srcdir%\xsd\*.* %restextdir%\xsd
+
+goto end
+:usage
+echo Usage: deploy <sca-root>
+:end
+
+endlocal
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/Makefile.am
new file mode 100644
index 0000000000..f963effea2
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/deploy.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/deploy.bat
new file mode 100644
index 0000000000..07c74d9e81
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/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 restextdir=%extdir%\rest
+set intfextdir=%restextdir%\interface
+set srcdir=%rootdir%\runtime\extensions\rest\interface\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 %restextdir% mkdir %restextdir%
+if not exist %intfextdir% mkdir %intfextdir%
+if not exist %intfextdir%\module mkdir %intfextdir%\module
+if not exist %intfextdir%\bin mkdir %intfextdir%\bin
+if not exist %intfextdir%\lib mkdir %intfextdir%\lib
+
+set libname=tuscany_sca_rest_interface
+
+del %intfextdir%\bin\%libname%.*
+del %intfextdir%\lib\%libname%.*
+
+copy %inpath%\%libname%.lib %intfextdir%\lib
+copy %inpath%\%libname%.dll %intfextdir%\bin
+copy %inpath%\%libname%.dll %intfextdir%\module
+
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %intfextdir%\bin
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %intfextdir%\module
+
+goto end
+:usage
+echo Usage: deploy <sca-root> <build-output>
+:end
+
+endlocal
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/Makefile.am
new file mode 100644
index 0000000000..8007a89d13
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/Makefile.am
@@ -0,0 +1,25 @@
+libdir=$(prefix)/extensions/rest/interface/lib
+lib_LTLIBRARIES = libtuscany_sca_rest_interface.la
+
+noinst_HEADERS = tuscany/sca/rest/*.h tuscany/sca/rest/model/*.h
+
+libtuscany_sca_rest_interface_la_SOURCES = \
+tuscany/sca/rest/RESTInterfaceExtension.cpp \
+tuscany/sca/rest/model/RESTInterface.cpp
+
+libtuscany_sca_rest_interface_la_LIBADD = \
+ -L${TUSCANY_SDOCPP}/lib -ltuscany_sdo \
+ -L$(top_builddir)/runtime/core/src -ltuscany_sca
+
+INCLUDES = -I$(top_builddir)/runtime/core/src \
+ -I${TUSCANY_SDOCPP}/include
+
+AM_CPPFLAGS = $(CPPFLAGS) -D_DEBUG
+
+moduledir=$(prefix)/extensions/rest/interface/module
+extension = libtuscany_sca_rest_interface$(libsuffix)
+
+install-exec-hook:
+ test -z $(moduledir) || $(mkdir_p) $(moduledir);
+ -rm -f $(moduledir)/$(extension)
+ $(LN_S) $(libdir)/$(extension) $(moduledir)/$(extension) \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.cpp
new file mode 100644
index 0000000000..c69febf39a
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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/rest/RESTInterfaceExtension.h"
+#include "tuscany/sca/rest/model/RESTInterface.h"
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/core/SCARuntime.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_rest_interface_initialize()
+ {
+ tuscany::sca::rest::RESTInterfaceExtension::initialize();
+ }
+}
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ // ===================================================================
+ // Constructor for the RESTInterfaceExtension class.
+ // ===================================================================
+ RESTInterfaceExtension::RESTInterfaceExtension()
+ {
+ logentry();
+ }
+
+ // ===================================================================
+ // Destructor for the RESTInterfaceExtension class.
+ // ===================================================================
+ RESTInterfaceExtension::~RESTInterfaceExtension()
+ {
+ logentry();
+ }
+
+ const string RESTInterfaceExtension::extensionName("rest");
+ const string RESTInterfaceExtension::typeQName("http://www.osoa.org/xmlns/sca/1.0#RESTInterface");
+
+ // ===================================================================
+ // loadModelElement - load the info from interface.rest
+ // ===================================================================
+ tuscany::sca::model::Interface* RESTInterfaceExtension::getInterface(Composite* composite, DataObjectPtr scdlInterface)
+ {
+ logentry();
+
+ return new RESTInterface();
+ }
+
+ void RESTInterfaceExtension::initialize()
+ {
+ logentry();
+ SCARuntime::getCurrentRuntime()->registerInterfaceExtension(new RESTInterfaceExtension());
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.h
new file mode 100644
index 0000000000..de61ee5751
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/RESTInterfaceExtension.h
@@ -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$ */
+
+#ifndef tuscany_sca_rest_restinterfaceextension_h
+#define tuscany_sca_rest_restinterfaceextension_h
+
+#include "tuscany/sca/extension/InterfaceExtension.h"
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ class RESTInterfaceExtension : public InterfaceExtension
+ {
+ public:
+ /**
+ * Default constructor
+ */
+ RESTInterfaceExtension();
+
+ /**
+ * Destructor
+ */
+ virtual ~RESTInterfaceExtension();
+
+ /**
+ * return the name of the extension
+ */
+ virtual const std::string& getExtensionName() {return extensionName;}
+
+ /**
+ * return the QName of schema type for this interface extension
+ * (e.g. "http://www.osoa.org/xmlns/sca/1.0#interface.rest")
+ */
+ virtual const std::string& getExtensionTypeQName() {return typeQName;}
+
+ virtual tuscany::sca::model::Interface* getInterface(
+ tuscany::sca::model::Composite* composite,
+ commonj::sdo::DataObjectPtr scdlInterface);
+
+ static void initialize();
+
+ private:
+ static const std::string extensionName;
+ static const std::string typeQName;
+
+ };
+
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_rest_restinterfaceextension_h
+
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/exportinterface.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/exportinterface.h
new file mode 100644
index 0000000000..f3636f0d39
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/exportinterface.h
@@ -0,0 +1,38 @@
+/*
+ * 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_rest_exportinterface_h
+#define tuscany_sca_rest_exportinterface_h
+
+#if defined(WIN32) || defined (_WINDOWS)
+#pragma warning(disable: 4786)
+
+#ifdef TUSCANY_SCA_REST_INTERFACE_EXPORTS
+#define SCA_REST_INTERFACE_API __declspec(dllexport)
+#else
+#define SCA_REST_INTERFACE_API __declspec(dllimport)
+#endif
+
+#else
+#define SCA_REST_INTERFACE_API
+#endif
+
+#endif // tuscany_sca_rest_exportinterface_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.cpp
new file mode 100644
index 0000000000..34feda2049
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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/util/Utils.h"
+#include "tuscany/sca/rest/model/RESTInterface.h"
+
+using namespace std;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ const string RESTInterface::typeQName("http://www.osoa.org/xmlns/sca/1.0#RESTInterface");
+
+ // Constructor
+ RESTInterface::RESTInterface()
+ : Interface(true, false)
+ {
+ logentry();
+ }
+
+ RESTInterface::~RESTInterface()
+ {
+ logentry();
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.h
new file mode 100644
index 0000000000..88aacecc16
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/interface/src/tuscany/sca/rest/model/RESTInterface.h
@@ -0,0 +1,80 @@
+/*
+ * 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_rest_model_restinterface_h
+#define tuscany_sca_rest_model_restinterface_h
+
+#include <string>
+
+#include "tuscany/sca/model/Interface.h"
+#include "tuscany/sca/rest/exportinterface.h"
+
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ /**
+ * Holds information about a REST interface
+ */
+ class RESTInterface : public tuscany::sca::model::Interface
+ {
+
+ public:
+ /**
+ * Constuctor.
+ * @param header Name of the header file containing the class that
+ * describes the interface.
+ * @param className Name of the class in the header file that
+ * describes the interface.
+ * @param scope The scope of the interface (stateless or composite).
+ * @param remotable True if the interface is remotable.
+ */
+ RESTInterface();
+
+ /**
+ * Destructor.
+ */
+ virtual ~RESTInterface();
+
+ /**
+ * return the QName of the schema type for this interface type
+ * (e.g. "http://www.osoa.org/xmlns/sca/1.0#interface.rest")
+ */
+ virtual const std::string& getInterfaceTypeQName() { return typeQName; };
+
+ /**
+ * The QName of the schema type for this interface type.
+ */
+ SCA_REST_INTERFACE_API static const std::string typeQName;
+
+ private:
+
+ };
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_rest_model_restinterface_h
+
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/Makefile.am
new file mode 100644
index 0000000000..2a0247f16f
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = curl \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/Makefile.am
new file mode 100644
index 0000000000..f963effea2
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/Makefile.am
new file mode 100644
index 0000000000..834853a6cf
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/Makefile.am
@@ -0,0 +1,31 @@
+libdir=$(prefix)/extensions/rest/reference/lib
+lib_LTLIBRARIES = libtuscany_sca_rest_reference.la
+
+noinst_HEADERS = tuscany/sca/rest/*.h tuscany/sca/rest/model/*.h
+
+libtuscany_sca_rest_reference_la_SOURCES = \
+tuscany/sca/rest/RESTServiceBindingExtension.cpp \
+tuscany/sca/rest/model/RESTServiceBinding.cpp \
+tuscany/sca/rest/RESTServiceWrapper.cpp
+
+libtuscany_sca_rest_reference_la_LIBADD = \
+ -L${TUSCANY_SDOCPP}/lib -ltuscany_sdo \
+ -L$(top_builddir)/runtime/core/src -ltuscany_sca \
+ -L$(top_builddir)/runtime/extensions/rest/interface/src -ltuscany_sca_rest_interface \
+ -L${CURL_LIB} -lcurl
+
+INCLUDES = -I$(top_builddir)/runtime/core/src \
+ -I$(top_builddir)/runtime/extensions/rest/interface/src \
+ -I${TUSCANY_SDOCPP}/include \
+ -I${CURL_INCLUDE}
+
+AM_CPPFLAGS = $(CPPFLAGS) -D_DEBUG
+
+
+moduledir=$(prefix)/extensions/rest/reference/module
+extension = libtuscany_sca_rest_reference$(libsuffix)
+
+install-exec-hook:
+ test -z $(moduledir) || $(mkdir_p) $(moduledir);
+ -rm -f $(moduledir)/$(extension)
+ $(LN_S) $(libdir)/$(extension) $(moduledir)/$(extension) \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.cpp
new file mode 100644
index 0000000000..f8eb9ad05c
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.cpp
@@ -0,0 +1,89 @@
+/*
+* 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.
+*/
+
+#include "RESTServiceBindingExtension.h"
+#include "model/RESTServiceBinding.h"
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/util/Utils.h"
+#include "tuscany/sca/core/SCARuntime.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_rest_reference_initialize()
+ {
+ tuscany::sca::rest::RESTServiceBindingExtension::initialize();
+ }
+}
+
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ // ===================================================================
+ // Constructor for the RESTServiceBinding class.
+ // ===================================================================
+ RESTServiceBindingExtension::RESTServiceBindingExtension()
+ {
+ logentry();
+ }
+
+ // ===================================================================
+ // Destructor for the RESTServiceBindingExtension class.
+ // ===================================================================
+ RESTServiceBindingExtension::~RESTServiceBindingExtension()
+ {
+ logentry();
+ }
+
+ const string RESTServiceBindingExtension::extensionName("rest");
+ const string RESTServiceBindingExtension::typeQName("http://www.osoa.org/xmlns/sca/1.0#RESTBinding");
+
+
+ // ===================================================================
+ // loadModelElement - load the info from binding.rest
+ // ===================================================================
+ ServiceBinding* RESTServiceBindingExtension::getServiceBinding(Composite *composite, Service* service, DataObjectPtr scdlBinding)
+ {
+ string uri = scdlBinding->getCString("uri");
+
+ RESTServiceBinding* serviceBinding = new RESTServiceBinding(service, uri);
+
+ return serviceBinding;
+ }
+
+ void RESTServiceBindingExtension::initialize()
+ {
+ logentry();
+ SCARuntime::getCurrentRuntime()->registerServiceBindingExtension(new RESTServiceBindingExtension());
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.h
new file mode 100644
index 0000000000..ad1d861d95
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceBindingExtension.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.
+ */
+
+#ifndef tuscany_sca_extension_rest_restservicebindingextension_h
+#define tuscany_sca_extension_rest_restservicebindingextension_h
+
+#include "tuscany/sca/extension/ServiceBindingExtension.h"
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ class RESTServiceBindingExtension : public ServiceBindingExtension
+ {
+ public:
+ /**
+ * Default constructor
+ */
+ RESTServiceBindingExtension();
+
+ /**
+ * Destructor
+ */
+ virtual ~RESTServiceBindingExtension();
+
+ /**
+ * 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#binding.rest")
+ */
+ virtual const std::string& getExtensionTypeQName() {return typeQName;}
+
+ virtual tuscany::sca::model::ServiceBinding* getServiceBinding(
+ tuscany::sca::model::Composite* composite,
+ tuscany::sca::model::Service* service,
+ commonj::sdo::DataObjectPtr scdlBinding);
+
+ static void initialize();
+
+ private:
+ static const std::string extensionName;
+ static const std::string typeQName;
+
+ };
+
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif //tuscany_sca_extension_rest_restservicebindingextension_h
+
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
new file mode 100644
index 0000000000..424039666f
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.cpp
@@ -0,0 +1,1222 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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$ */
+#if defined(WIN32) || defined (_WINDOWS)
+#pragma warning(disable: 4091)
+#endif
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include "commonj/sdo/SDO.h"
+
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/core/Exceptions.h"
+#include "tuscany/sca/util/Utils.h"
+#include "RESTServiceWrapper.h"
+#include "tuscany/sca/core/Operation.h"
+#include "tuscany/sca/core/SCARuntime.h"
+#include "tuscany/sca/model/Service.h"
+#include "tuscany/sca/model/Component.h"
+#include "tuscany/sca/model/Composite.h"
+#include "tuscany/sca/model/ServiceType.h"
+#include "tuscany/sca/model/CompositeReference.h"
+#include "model/RESTServiceBinding.h"
+#include "tuscany/sca/rest/model/RESTInterface.h"
+
+using namespace std;
+using namespace commonj::sdo;
+using namespace tuscany::sca::model;
+using namespace tuscany::sca::util;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ class ResponseChunk {
+ public:
+ ResponseChunk() : memory(NULL), size(0)
+ {
+ }
+
+ ~ResponseChunk()
+ {
+ if (memory)
+ {
+ free(memory);
+ }
+ }
+
+ char *memory;
+ int size;
+ };
+
+ class RequestChunk {
+ public:
+ RequestChunk() : memory(NULL), size(0), read(0)
+ {
+ }
+
+ ~RequestChunk()
+ {
+ }
+
+ const char *memory;
+ int size;
+ int read;
+ };
+
+ class HeaderChunk {
+ public:
+ HeaderChunk() : location("")
+ {
+ }
+
+ ~HeaderChunk()
+ {
+ }
+
+ string location;
+ };
+
+ size_t write_callback(void *ptr, size_t size, size_t nmemb, void *data)
+ {
+ int realsize = size * nmemb;
+ ResponseChunk *mem = (ResponseChunk *)data;
+
+ if (mem->memory != NULL)
+ {
+ mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
+ }
+ else
+ {
+ mem->memory = (char *)malloc(mem->size + realsize + 1);
+ }
+ memcpy(&(mem->memory[mem->size]), ptr, realsize);
+ mem->size += realsize;
+ mem->memory[mem->size] = 0;
+ return realsize;
+ }
+
+ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data)
+ {
+ int realsize = size * nmemb;
+ RequestChunk *mem = (RequestChunk *)data;
+
+ if (realsize > mem->size - mem->read)
+ {
+ realsize = mem->size - mem->read;
+ }
+ if (realsize != 0)
+ {
+ memcpy(ptr, &(mem->memory[mem->read]), realsize);
+ mem->read += realsize;
+ }
+ return realsize;
+ }
+
+ size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data)
+ {
+ int realsize = size * nmemb;
+ HeaderChunk* mem = (HeaderChunk*)data;
+
+ char* str = new char[realsize + 1];
+ memcpy(str, ptr, realsize);
+ str[realsize] = 0;
+
+ if (strlen(str) > 10 && !strncmp(str, "Location: ", 10))
+ {
+ string s = &str[10];
+ mem->location = s.substr(0,s.find_last_not_of("\r\n")+1);
+ }
+
+ delete str;
+
+ return realsize;
+ }
+
+ bool RESTServiceWrapper::initialized = false;
+
+ RESTServiceWrapper::RESTServiceWrapper(Service* service) : ServiceWrapper(service)
+ {
+ logentry();
+
+ DataFactoryPtr dataFactory = service->getComponent()->getComposite()->getDataFactory();
+ try {
+ const Type& tempType = dataFactory->getType("http://tempuri.org", "RootType");
+ } catch (SDORuntimeException&)
+ {
+ dataFactory->addType("http://tempuri.org", "RootType", false, false, false);
+ dataFactory->addType("http://tempuri.org", "Wrapper", false, true, false);
+ dataFactory->addPropertyToType(
+ "http://tempuri.org", "RootType",
+ "Wrapper",
+ "http://tempuri.org", "Wrapper",
+ false, false, true);
+ dataFactory->addType("http://tempuri.org", "Part", false, true, false);
+ dataFactory->addPropertyToType(
+ "http://tempuri.org", "RootType",
+ "Part",
+ "http://tempuri.org", "Part",
+ false, false, true);
+ }
+
+ if (!initialized)
+ {
+ curl_global_init(CURL_GLOBAL_ALL);
+ initialized = true;
+ }
+ }
+
+ RESTServiceWrapper::~RESTServiceWrapper()
+ {
+ }
+
+ ///
+ /// This method will be called when a service call needs to be made.
+ ///
+ void RESTServiceWrapper::invoke(Operation& operation)
+ {
+ logentry();
+
+ const string& operationName = operation.getName();
+
+ loginfo("Service: %s, operation: %s", getService()->getType()->getName().c_str() , operationName.c_str());
+
+ for (unsigned int i=0; i<operation.getNParms(); i++)
+ {
+ loginfo("Parameter: %p, type %u", operation.getParameterValue(i),(int) operation.getParameterType(i));
+ }
+
+ // Get the service, composite reference and composite
+ Service* service = getService();
+ CompositeReference* compositeReference = (CompositeReference*)service->getComponent();
+ Composite* composite = compositeReference->getComposite();
+ XMLHelper* xmlHelper = composite->getXMLHelper();
+
+ // Get the REST binding
+ RESTServiceBinding* binding = (RESTServiceBinding *)service->getBinding();
+ Interface* iface = service->getType()->getInterface();
+
+ // Init the curl session
+ CURL *curl_handle = curl_easy_init();
+
+ RequestChunk requestChunk;
+ ResponseChunk responseChunk;
+ HeaderChunk headerChunk;
+
+ // Some servers don't like requests that are made without a user-agent
+ curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+
+ // Get the operation name
+ string opName = operation.getName();
+
+ // If we have a REST interface, the operation name translates to an HTTP verb
+ if (iface != NULL && iface->getInterfaceTypeQName() == RESTInterface::typeQName)
+ {
+
+ // HTTP GET
+ if (opName == "retrieve")
+ {
+ // Build the request URL
+ bool firstParm = 0;
+ string uri;
+ if (operation.getNParms() !=0)
+ {
+
+ // If the first parameter is a URI, then we'll use it,
+ // otherwise we'll use the binding URI
+ ostringstream s0;
+ writeParameter(xmlHelper, s0, operation.getParameter(0));
+ string p0 = s0.str();
+ if (p0.find("://") != string::npos)
+ {
+ firstParm = 1;
+ uri = p0;
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ // Add the parameters to the end of the URI
+ ostringstream os;
+ if (uri[uri.length()-1] == '?')
+ {
+ // If the URI ends with a "?" then we use the query
+ // form param=value&
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms(); i++)
+ {
+ Operation::Parameter param = operation.getParameter(i);
+
+ if(param.hasName())
+ {
+ os << param.getName() << "=";
+ }
+ else
+ {
+ // No name - use "param1", etc
+ os << "param" << (i + 1) << "=";
+ }
+ writeParameter(xmlHelper, os, param);
+ if (i < operation.getNParms()-1)
+ os << "&";
+ }
+ }
+ else
+ {
+ // Add the parameters in the form
+ // value1 / value2 / value3
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms(); i++)
+ {
+ os << "/";
+ writeParameter(xmlHelper, os, operation.getParameter(i));
+ }
+ }
+
+ string url = os.str();
+ //loginfo("RESTServiceWrapper: HTTP GET %s", url.c_str());
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+
+ // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&responseChunk);
+
+ // Send all headers to this function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&headerChunk);
+
+ // Perform the HTTP GET
+ CURLcode rc = curl_easy_perform(curl_handle);
+
+ if (rc)
+ {
+ throwException(ServiceInvocationException, curl_easy_strerror(rc));
+ }
+
+ // Get the output data out of the returned document
+ long httprc;
+ curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &httprc);
+
+ string responsePayload = "";
+ if (responseChunk.memory)
+ {
+ responsePayload = string((const char*)responseChunk.memory, responseChunk.size);
+ }
+
+ if (httprc == 200)
+ {
+ if (responsePayload != "")
+ {
+ //TODO Remove this workaround once SDO supports loading of open top level content
+ // The workaround is to wrap the open content in a wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", responsePayload, xmldecl, xml);
+ string part = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ part += "<Part xmlns=\"http://tempuri.org\" xmlns:tns=\"http://tempuri.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ part += xml;
+ part += "\n</Part>";
+
+ setReturn(xmlHelper, part, operation);
+ }
+ else
+ {
+ throwException(ServiceInvocationException, "Failed to retrieve resource, empty response");
+ }
+ }
+ else
+ {
+ ostringstream msg;
+ msg << "Failed to retrieve REST resource, HTTP code: " << httprc;
+ if (responsePayload != "")
+ {
+ msg << ", payload: " << responsePayload;
+ }
+ throwException(ServiceInvocationException, msg.str().c_str());
+ }
+ }
+ else if (opName == "create")
+ {
+ // HTTP POST
+
+ // Set the target URL
+ string url = getBindingURI();
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+
+ // Create the input payload
+ ostringstream spayload;
+ writeParameter(xmlHelper, spayload, operation.getParameter(0));
+ const string& requestPayload = spayload.str();
+ requestChunk.memory = requestPayload.c_str();
+ requestChunk.size = requestPayload.size();
+
+ curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, requestChunk.size);
+
+ // Read all data using this function
+ curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_READDATA, (void *)&requestChunk);
+
+ // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&responseChunk);
+
+ // Send all headers to this function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&headerChunk);
+
+ // Configure headers
+ curl_slist *requestHeaders = NULL;
+ requestHeaders = curl_slist_append(requestHeaders, "Expect:");
+ requestHeaders = curl_slist_append(requestHeaders, "Content-Type: text/xml");
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, requestHeaders);
+
+ // Perform the HTTP POST
+ curl_easy_setopt(curl_handle, CURLOPT_POST, true);
+ CURLcode rc = curl_easy_perform(curl_handle);
+
+ curl_slist_free_all(requestHeaders);
+
+ if (rc)
+ {
+ throwException(ServiceInvocationException, curl_easy_strerror(rc));
+ }
+
+ // Get the output and location of the created resource
+ string responsePayload = "";
+ if (responseChunk.memory)
+ {
+ responsePayload = string((const char*)responseChunk.memory, responseChunk.size);
+ }
+
+ long httprc;
+ curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &httprc);
+ if (httprc == 201)
+ {
+ string* location = new string;
+ *location = headerChunk.location;
+ operation.setReturnValue(location);
+ }
+ else
+ {
+ ostringstream msg;
+ msg << "Failed to create REST resource, HTTP code: " << httprc;
+ if (responsePayload != "")
+ {
+ msg << ", payload: " << responsePayload;
+ }
+ throwException(ServiceInvocationException, msg.str().c_str());
+ }
+ }
+ else if (opName == "update")
+ {
+ // HTTP PUT
+
+ // Build the request URL
+ bool firstParm = 0;
+ string uri;
+ if (operation.getNParms() > 1)
+ {
+
+ // If the first parameter is a URI, then we'll use it,
+ // otherwise we'll use the binding URI
+ ostringstream s0;
+ writeParameter(xmlHelper, s0, operation.getParameter(0));
+ string p0 = s0.str();
+ if (p0.find("://") != string::npos)
+ {
+ firstParm = 1;
+ uri = p0;
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ // Add the parameters to the end of the URI
+ ostringstream os;
+ if (uri[uri.length()-1] == '?')
+ {
+ // If the URI ends with a "?" then we use the query
+ // form param=value&
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms()-1; i++)
+ {
+ Operation::Parameter param = operation.getParameter(i);
+ if(param.hasName())
+ {
+ os << param.getName() << "=";
+ }
+ else
+ {
+ // No name - use "param1", etc
+ os << "param" << (i + 1) << "=";
+ }
+ writeParameter(xmlHelper, os, param);
+ if (i < operation.getNParms()-1)
+ os << "&";
+ }
+ }
+ else
+ {
+ // Add the parameters in the form
+ // value1 / value2 / value3
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms()-1; i++)
+ {
+ os << "/";
+ writeParameter(xmlHelper, os, operation.getParameter(i));
+ }
+ }
+
+ string url = os.str();
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+
+ // Create the input payload
+ ostringstream spayload;
+ writeParameter(xmlHelper, spayload, operation.getParameter(operation.getNParms()-1));
+ const string& requestPayload = spayload.str();
+ requestChunk.memory = requestPayload.c_str();
+ requestChunk.size = requestPayload.size();
+
+ // Read all data using this function
+ curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_READDATA, (void *)&requestChunk);
+
+ // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&responseChunk);
+
+ // Send all headers to this function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&headerChunk);
+
+ // Configure headers
+ curl_slist *requestHeaders = NULL;
+ requestHeaders = curl_slist_append(requestHeaders, "Expect:");
+ requestHeaders = curl_slist_append(requestHeaders, "Content-Type: text/xml");
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, requestHeaders);
+
+ // Perform the HTTP PUT
+ curl_easy_setopt(curl_handle, CURLOPT_PUT, true);
+ curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, true) ;
+ long size = (long)requestChunk.size;
+ curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE, size);
+
+ CURLcode rc = curl_easy_perform(curl_handle);
+
+ curl_slist_free_all(requestHeaders);
+
+ if (rc)
+ {
+ throwException(ServiceInvocationException, curl_easy_strerror(rc));
+ }
+
+ // Get the output and location of the created resource
+ string responsePayload = "";
+ if (responseChunk.memory)
+ {
+ responsePayload = string((const char*)responseChunk.memory, responseChunk.size);
+ }
+
+ long httprc;
+ curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &httprc);
+ if (httprc != 200)
+ {
+ ostringstream msg;
+ msg << "Failed to update REST resource, HTTP code: " << httprc;
+ if (responsePayload != "")
+ {
+ msg << ", payload: " << responsePayload;
+ }
+ throwException(ServiceInvocationException, msg.str().c_str());
+ }
+ }
+ else if (opName == "delete")
+ {
+ // HTTP DELETE
+
+ // Build the request URL
+ bool firstParm = 0;
+ string uri;
+ if (operation.getNParms() !=0)
+ {
+
+ // If the first parameter is a URI, then we'll use it,
+ // otherwise we'll use the binding URI
+ ostringstream s0;
+ writeParameter(xmlHelper, s0, operation.getParameter(0));
+ string p0 = s0.str();
+ if (p0.find("://") != string::npos)
+ {
+ firstParm = 1;
+ uri = p0;
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ }
+ else
+ {
+ uri = getBindingURI();
+ }
+ // Add the parameters to the end of the URI
+ ostringstream os;
+ if (uri[uri.length()-1] == '?')
+ {
+ // If the URI ends with a "?" then we use the query
+ // form param=value&
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms(); i++)
+ {
+ Operation::Parameter param = operation.getParameter(i);
+
+ if(param.hasName())
+ {
+ os << param.getName() << "=";
+ }
+ else
+ {
+ // No name - use "param1", etc
+ os << "param" << (i + 1) << "=";
+ }
+ writeParameter(xmlHelper, os, param);
+ if (i < operation.getNParms()-1)
+ os << "&";
+ }
+ }
+ else
+ {
+ // Add the parameters in the form
+ // value1 / value2 / value3
+ os << uri;
+ for (unsigned int i = firstParm; i < operation.getNParms(); i++)
+ {
+ os << "/";
+ writeParameter(xmlHelper, os, operation.getParameter(i));
+ }
+ }
+
+ string url = os.str();
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+
+ // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&responseChunk);
+
+ // Send all headers to this function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&headerChunk);
+
+ // Perform the HTTP DELETE
+ curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE");
+ CURLcode rc = curl_easy_perform(curl_handle);
+ if (rc)
+ {
+ throwException(ServiceInvocationException, curl_easy_strerror(rc));
+ }
+
+ // Get the output data out of the returned document
+ string responsePayload = "";
+ if (responseChunk.memory)
+ {
+ responsePayload = string((const char*)responseChunk.memory, responseChunk.size);
+ }
+
+ long httprc;
+ curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &httprc);
+ if (httprc != 200)
+ {
+ ostringstream msg;
+ msg << "Failed to delete REST resource, HTTP code: " << httprc;
+ if (responsePayload != "")
+ {
+ msg << ", payload: " << responsePayload;
+ }
+ throwException(ServiceInvocationException, msg.str().c_str());
+ }
+ }
+ else
+ {
+ string msg = "Unknown REST verb: " + opName;
+ throwException(ServiceInvocationException, msg.c_str());
+ }
+ }
+ else
+ {
+ // Not a REST interface, XML / HTTP command style
+ curl_slist *requestHeaders = NULL;
+ struct curl_httppost *formpost = NULL;
+ ostringstream spayload;
+ string requestPayload;
+ string url;
+
+ // If the request contains complex content then we'll use
+ // a POST, otherwise we use a GET with a query string
+ bool complexContent = false;
+ for (unsigned int i=0; i<operation.getNParms(); i++)
+ {
+ if (operation.getParameter(i).getType() == Operation::DATAOBJECT)
+ {
+ complexContent = true;
+ break;
+ }
+ }
+
+ if (complexContent)
+ {
+ // Set the target URL
+ string uri = getBindingURI();
+ ostringstream os;
+ os << uri << "/" << opName;
+ url = os.str();
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+
+ // Disable the 100 continue handshake
+ requestHeaders = curl_slist_append(requestHeaders, "Expect:");
+
+ if (operation.getNParms() == 1)
+ {
+ // Single parameter, send it as the body of the POST
+
+ // Create the input payload
+ writeParameter(xmlHelper, spayload, operation.getParameter(0));
+ requestPayload = spayload.str();
+ requestChunk.memory = requestPayload.c_str();
+ requestChunk.size = requestPayload.size();
+
+ curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, requestChunk.size);
+
+ // Read all data using this function
+ curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_READDATA, (void *)&requestChunk);
+
+ // Set the content type
+ requestHeaders = curl_slist_append(requestHeaders, "Content-Type: text/xml");
+
+ // This will be a POST
+ curl_easy_setopt(curl_handle, CURLOPT_POST, true);
+ }
+ else
+ {
+
+ // Multiple parameters, use a form type POST
+ struct curl_httppost *lastptr = NULL;
+ for (unsigned int i=0; i<operation.getNParms(); i++)
+ {
+ ostringstream pname;
+ Operation::Parameter param = operation.getParameter(i);
+
+ if(param.hasName())
+ {
+ pname << param.getName();
+ }
+ else
+ {
+ // No name - use "param1", etc
+ pname << "param" << (i+1);
+ }
+
+ const char* ctype;
+ if (param.getType() == Operation::DATAOBJECT)
+ {
+ ctype ="text/xml";
+ }
+ else
+ {
+ ctype = "text/plain";
+ }
+
+ ostringstream pvalue;
+ writeParameter(xmlHelper, pvalue, param);
+
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_CONTENTTYPE, ctype,
+ CURLFORM_COPYNAME, pname.str().c_str(),
+ CURLFORM_COPYCONTENTS, pvalue.str().c_str(),
+ CURLFORM_END);
+ }
+
+ // Set the form into the request
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, formpost);
+ }
+ }
+ else
+ {
+
+ // Build the request URL, uri / opName ? params
+ string uri = getBindingURI();
+ ostringstream os;
+ os << uri << "/" << opName;
+
+ // Add the parameters to the end of the URL in the form
+ // param=value&
+ for (unsigned int i=0; i<operation.getNParms(); i++)
+ {
+ if (i == 0)
+ os << "?";
+
+ Operation::Parameter param = operation.getParameter(i);
+ if(param.hasName())
+ {
+ os << param.getName() << "=";
+ }
+ else
+ {
+ // No name - use "param1", etc
+ os << "param" << (i + 1) << "=";
+ }
+ writeParameter(xmlHelper, os, param);
+ if (i < operation.getNParms()-1)
+ os << "&";
+ }
+
+ url = os.str();
+ loginfo("RESTServiceWrapper: HTTP GET %s", url.c_str());
+
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
+ }
+
+ // Send all data to this function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
+
+ // Pass our 'chunk' struct to the callback function
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&responseChunk);
+
+ // Configure the headers
+ if (requestHeaders)
+ {
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, requestHeaders);
+ }
+
+ loginfo("RESTServiceWrapper: Performing HTTP request");
+ // Perform the HTTP request
+ CURLcode rc = curl_easy_perform(curl_handle);
+
+ loginfo("RESTServiceWrapper: Completed HTTP request");
+ // Free any headers
+ if (requestHeaders)
+ {
+ curl_slist_free_all(requestHeaders);
+ }
+
+ // Cleanup the form
+ if (complexContent)
+ {
+ curl_formfree(formpost);
+ }
+
+ if (rc)
+ {
+ throwException(ServiceInvocationException, curl_easy_strerror(rc));
+ }
+
+ if (responseChunk.memory)
+ {
+ string responsePayload((const char*)responseChunk.memory, responseChunk.size);
+
+
+ loginfo("RESTServiceWrapper: responsePayload: %s", responsePayload.c_str());
+
+ //TODO Remove this workaround once SDO supports loading of open top level content
+ // The workaround is to wrap the open content in a wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", responsePayload, xmldecl, xml);
+ string part = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ part += "<Part xmlns=\"http://tempuri.org\" xmlns:tns=\"http://tempuri.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ part += xml;
+ part += "\n</Part>";
+
+ setReturn(xmlHelper, part, operation);
+ }
+ }
+
+ // Cleanup curl session
+ curl_easy_cleanup(curl_handle);
+ }
+
+
+ const string RESTServiceWrapper::getBindingURI()
+ {
+ string bindingURI = "";
+
+ // Get the binding URI configured on the top level component
+ Service* service = getService();
+ CompositeReference* compositeReference = (CompositeReference*)service->getComponent();
+ SCARuntime* runtime = SCARuntime::getCurrentRuntime();
+ Component* component = runtime->getDefaultComponent();
+ Reference* reference = component->findReference(compositeReference->getName());
+ if (reference != NULL)
+ {
+ ReferenceBinding* binding = reference->getBinding();
+ if (binding != NULL && binding->getURI() != "")
+ {
+ bindingURI = binding->getURI();
+ }
+ }
+ if (bindingURI == "")
+ {
+ // Get the binding URI configured on the binding
+ RESTServiceBinding* binding = (RESTServiceBinding *)service->getBinding();
+ bindingURI = binding->getURI();
+ }
+ if (bindingURI != "")
+ {
+
+ // Prepend the default base URI if the URI is not absolute
+ if (bindingURI.find("://") == string::npos)
+ {
+ bindingURI = runtime->getDefaultBaseURI() + string("/rest/") + bindingURI;
+ }
+ }
+ return bindingURI;
+ }
+
+
+ void RESTServiceWrapper::writeParameter(XMLHelper* xmlHelper, ostringstream& os, const Operation::Parameter& parm)
+ {
+ logentry();
+
+ switch(parm.getType())
+ {
+ case Operation::BOOL:
+ {
+ os << *(bool*)parm.getValue();
+ break;
+ }
+ case Operation::SHORT:
+ {
+ os << *(short*)parm.getValue();
+ break;
+ }
+ case Operation::INT:
+ {
+ os << *(long*)parm.getValue();
+ break;
+ }
+ case Operation::LONG:
+ {
+ os << *(long*)parm.getValue();
+ break;
+ }
+ case Operation::USHORT:
+ {
+ os << *(short*)parm.getValue();
+ break;
+ }
+ case Operation::UINT:
+ {
+ os << *(long*)parm.getValue();
+ break;
+ }
+ case Operation::ULONG:
+ {
+ os << *(long*)parm.getValue();
+ break;
+ }
+ case Operation::FLOAT:
+ {
+ os << *(float*)parm.getValue();
+ break;
+ }
+ case Operation::DOUBLE:
+ {
+ os << *(long double*)parm.getValue();
+ break;
+ }
+ case Operation::LONGDOUBLE:
+ {
+ os << *(long double*)parm.getValue();
+ break;
+ }
+ case Operation::CHARS:
+ {
+ os << *(char**)parm.getValue();
+ break;
+ }
+ case Operation::STRING:
+ {
+ os << (*(string*)parm.getValue()).c_str();
+ break;
+ }
+ case Operation::DATAOBJECT:
+ {
+ DataObjectPtr dob = *(DataObjectPtr*)parm.getValue();
+ XMLDocumentPtr doc = xmlHelper->createDocument(dob, NULL, NULL);
+ xmlHelper->save(doc, os);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ void RESTServiceWrapper::setReturn(XMLHelper* xmlHelper, string& payload,
+ Operation& operation)
+ {
+ logentry();
+
+ //TODO Remove this workaround once SDO supports loading of open top level content
+ // The workaround is to wrap the open content in a wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", payload, xmldecl, xml);
+ string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ body += "<Wrapper xmlns=\"http://tempuri.org\" xmlns:tns=\"http://tempuri.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ body += xml;
+ body += "\n</Wrapper>";
+
+ // Convert the body to an SDO DataObject
+ DataObjectPtr outputWrapperDataObject = NULL;
+ XMLDocumentPtr theXMLDocument = xmlHelper->load(body.c_str(), NULL);
+ if (theXMLDocument != 0)
+ {
+ outputWrapperDataObject = theXMLDocument->getRootDataObject();
+ }
+ if(!outputWrapperDataObject)
+ {
+ ostringstream msg;
+ msg << "Could not convert received document to SDO: " << body;
+ throwException(ServiceDataException, msg.str().c_str());
+ }
+
+ // Get the body part
+ DataObjectPtr outputDataObject = NULL;
+ PropertyList bpl = outputWrapperDataObject->getInstanceProperties();
+ if (bpl.size()!=0)
+ {
+ if (bpl[0].isMany())
+ {
+ DataObjectList& parts = outputWrapperDataObject->getList((unsigned int)0);
+ outputDataObject = parts[0];
+ }
+ else
+ {
+ outputDataObject = outputWrapperDataObject->getDataObject(bpl[0]);
+ }
+ }
+ if (outputDataObject == NULL)
+ {
+ ostringstream msg;
+ msg << "Could not convert body part to SDO: " << body;
+ throwException(ServiceDataException, msg.str().c_str());
+ }
+
+ PropertyList pl = outputDataObject->getInstanceProperties();
+ unsigned int i = 0;
+
+ switch(pl[i].getTypeEnum())
+ {
+ case Type::BooleanType:
+ {
+ bool* boolData = new bool;
+ *boolData = outputDataObject->getBoolean(pl[i]);
+ operation.setReturnValue(boolData);
+ }
+ break;
+ case Type::ByteType:
+ {
+ char* byteData = new char;
+ *byteData = outputDataObject->getByte(pl[i]);
+ operation.setReturnValue(byteData);
+ }
+ break;
+ case Type::BytesType:
+ {
+ int len = outputDataObject->getLength(pl[i]);
+ char* bytesData = new char[len+1];
+ int bytesWritten = outputDataObject->getBytes(pl[i], bytesData, len);
+ // Ensure the bytes end with the null char. Not sure if this is neccessary
+ if(bytesWritten <= len)
+ {
+ bytesData[bytesWritten] = 0;
+ }
+ else
+ {
+ bytesData[len] = 0;
+ }
+ operation.setReturnValue(&bytesData);
+ }
+ break;
+ case Type::CharacterType:
+ {
+ // This code should work but won't be used as there is no mapping from an XSD type to the SDO CharacterType
+ wchar_t* charData = new wchar_t;
+ *charData = outputDataObject->getCharacter(pl[i]);
+ operation.setReturnValue(charData);
+ }
+ break;
+ case Type::DoubleType:
+ {
+ long double* doubleData = new long double;
+ *doubleData = outputDataObject->getDouble(pl[i]);
+ operation.setReturnValue(doubleData);
+ }
+ break;
+ case Type::FloatType:
+ {
+ float* floatData = new float;
+ *floatData = outputDataObject->getFloat(pl[i]);
+ operation.setReturnValue(floatData);
+ }
+ break;
+ case Type::IntegerType:
+ {
+ long* intData = new long;
+ *intData = outputDataObject->getInteger(pl[i]);
+ operation.setReturnValue(intData);
+ }
+ break;
+ case Type::ShortType:
+ {
+ short* shortData = new short;
+ *shortData = outputDataObject->getShort(pl[i]);
+ operation.setReturnValue(shortData);
+ }
+ break;
+ case Type::StringType:
+ {
+ string* str = new string(outputDataObject->getCString(pl[i]));
+ operation.setReturnValue(str);
+ }
+ break;
+ case Type::DataObjectType:
+ {
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ *dataObjectData = outputDataObject->getDataObject(pl[i]);
+ if(!*dataObjectData)
+ {
+ loginfo("Null SDO DataObject return value");
+ }
+ else
+ {
+ (*dataObjectData)->detach();
+ }
+ operation.setReturnValue(dataObjectData);
+ }
+ break;
+ case Type::OpenDataObjectType:
+ {
+ /*
+ * This code deals with xsd:any element parameters
+ * Get each element as a DataObject and add in to the parameter list
+ */
+ DataObjectList& dataObjectList = outputDataObject->getList(pl[i]);
+
+ for(unsigned int j=0; j<dataObjectList.size(); j++)
+ {
+ DataObjectPtr dob = dataObjectList[j];
+ if(!dob)
+ {
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ *dataObjectData = NULL;
+ operation.setReturnValue(dataObjectData);
+ loginfo("Null OpenDataObject return value");
+ }
+ else
+ {
+
+ SequencePtr sequence = dob->getSequence();
+ if (sequence->size()!=0)
+ {
+ // Return a text element
+ if (sequence->isText(0))
+ {
+ string* stringData = new string(sequence->getCStringValue(0));
+ operation.setReturnValue(stringData);
+ }
+ else
+ {
+ // Return a DataObject representing a complex element
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ *dataObjectData = sequence->getDataObjectValue(0);
+ if(!*dataObjectData)
+ {
+ loginfo("Null DataObject return value");
+ }
+ else
+ {
+ (*dataObjectData)->detach();
+ }
+ operation.setReturnValue(dataObjectData);
+ }
+ }
+ else
+ {
+ // Empty content, add an empty string
+ loginfo("Null OpenDataObject return value");
+ string *stringData = new string("");
+ operation.setReturnValue(stringData);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ ostringstream msg;
+ msg << "Unsupported result type: " << pl[i].getTypeEnum();
+ throwException(ServiceDataException, msg.str().c_str());
+ }
+ }
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.h
new file mode 100644
index 0000000000..af2fbcfc94
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/RESTServiceWrapper.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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_extension_rest_restservicewrapper_h
+#define tuscany_sca_extension_rest_restservicewrapper_h
+
+#include <sstream>
+
+#include "commonj/sdo/SDO.h"
+
+#include "tuscany/sca/core/ServiceWrapper.h"
+#include "tuscany/sca/core/Operation.h"
+#include "tuscany/sca/model/Service.h"
+
+
+namespace tuscany
+{
+ namespace sca
+ {
+
+ namespace rest
+ {
+
+ class RESTServiceWrapper : public ServiceWrapper
+ {
+ public:
+
+ /**
+ * Constructor.
+ * @param target The service wrapper represents a Web service.
+ */
+ RESTServiceWrapper(tuscany::sca::model::Service* service);
+
+ /**
+ * Destructor
+ */
+ virtual ~RESTServiceWrapper();
+
+ /**
+ * All business method calls on the target service are performed through
+ * this invoke method.
+ * @param operation The details of the method, paramaters and return value for the
+ * business method to be called on the target service.
+ */
+ virtual void invoke(Operation& operation);
+
+ private:
+
+ /**
+ * Used to track initialization of the CURL library
+ */
+ static bool initialized;
+
+ /**
+ * Get the configured binding URI
+ */
+ const std::string getBindingURI();
+
+ /**
+ * Write a parameter into a URL
+ */
+ void writeParameter(commonj::sdo::XMLHelper* xmlHelper, std::ostringstream& os, const Operation::Parameter& parm);
+
+ /**
+ * Set the return value on the given operation
+ */
+ void setReturn(commonj::sdo::XMLHelper* xmlHelper, std::string& payload, Operation& operation);
+
+ };
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_rest_restservicewrapper_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.cpp
new file mode 100644
index 0000000000..72701bfa65
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.cpp
@@ -0,0 +1,59 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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/rest/model/RESTServiceBinding.h"
+#include "tuscany/sca/core/ServiceWrapper.h"
+#include "tuscany/sca/rest/RESTServiceWrapper.h"
+
+using namespace std;
+using namespace tuscany::sca::model;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ // Constructor
+ RESTServiceBinding::RESTServiceBinding(Service* service, const string& uri)
+ : ServiceBinding(service, uri)
+ {
+ logentry();
+
+ serviceWrapper = new RESTServiceWrapper(service);
+ }
+
+ // Destructor
+ RESTServiceBinding::~RESTServiceBinding()
+ {
+ logentry();
+ }
+
+ ServiceWrapper* RESTServiceBinding::getServiceWrapper()
+ {
+ logentry();
+
+ return serviceWrapper;
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.h
new file mode 100644
index 0000000000..d19bcdacf5
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/curl/src/tuscany/sca/rest/model/RESTServiceBinding.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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_extension_rest_model_restservicebinding_h
+#define tuscany_sca_extension_rest_model_restservicebinding_h
+
+#include <string>
+
+#include "tuscany/sca/model/ServiceBinding.h"
+#include "tuscany/sca/model/Service.h"
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ /**
+ * Information about a REST binding for a service or a reference.
+ */
+ class RESTServiceBinding : public tuscany::sca::model::ServiceBinding
+ {
+ public:
+
+ /**
+ * Constructor.
+ * @param uri The uri of the binding.
+ */
+ RESTServiceBinding(tuscany::sca::model::Service* service, const std::string& uri);
+
+ /**
+ * Destructor.
+ */
+ virtual ~RESTServiceBinding();
+
+ /**
+ * Returns the type of binding.
+ */
+ virtual std::string getType() { return "http://www.osoa.org/xmlns/sca/1.0#RESTBinding"; };
+
+ /**
+ * 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 rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_extension_rest_model_restservicebinding_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/deploy.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/deploy.bat
new file mode 100644
index 0000000000..6717749990
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/reference/deploy.bat
@@ -0,0 +1,68 @@
+@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 restextdir=%extdir%\rest
+set refextdir=%restextdir%\reference
+set srcdir=%rootdir%\runtime\extensions\rest\reference
+
+if . == .%2 (
+echo input directory not specified
+goto usage
+)
+set inpath=%2
+echo %inpath%
+
+call %srcdir%\..\deploy.bat %rootdir%
+
+if not exist %deploydir% mkdir %deploydir%
+if not exist %extdir% mkdir %extdir%
+if not exist %restextdir% mkdir %restextdir%
+if not exist %refextdir% mkdir %refextdir%
+if not exist %refextdir%\module mkdir %refextdir%\module
+if not exist %refextdir%\bin mkdir %refextdir%\bin
+if not exist %refextdir%\lib mkdir %refextdir%\lib
+
+set libname=tuscany_sca_rest_reference
+
+del %refextdir%\bin\%libname%.*
+del %refextdir%\lib\%libname%.*
+
+copy %inpath%\%libname%.lib %refextdir%\lib
+copy %inpath%\%libname%.dll %refextdir%\bin
+copy %inpath%\%libname%.dll %refextdir%\module
+
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %refextdir%\bin
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %refextdir%\module
+
+goto end
+:usage
+echo Usage: deploy <sca-root> <build-output>
+:end
+
+endlocal
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/Makefile.am
new file mode 100644
index 0000000000..2ecfda6c6c
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = httpd \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploy.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploy.bat
new file mode 100644
index 0000000000..bea89aa81d
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/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 restextdir=%extdir%\rest
+set svcextdir=%restextdir%\service
+set srcdir=%rootdir%\runtime\extensions\rest\service\httpd\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 %restextdir% mkdir %restextdir%
+if not exist %svcextdir% mkdir %svcextdir%
+if not exist %svcextdir%\module mkdir %svcextdir%\module
+if not exist %svcextdir%\bin mkdir %svcextdir%\bin
+if not exist %svcextdir%\lib mkdir %svcextdir%\lib
+
+set libname=tuscany_sca_rest_service
+
+del %svcextdir%\bin\%libname%.*
+del %svcextdir%\lib\%libname%.*
+
+copy %inpath%\%libname%.lib %svcextdir%\lib
+copy %inpath%\%libname%.dll %svcextdir%\bin
+copy %inpath%\%libname%.dll %svcextdir%\module
+
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %svcextdir%\bin
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %svcextdir%\module
+
+goto end
+:usage
+echo Usage: deploy <sca-root> <build-output>
+:end
+
+endlocal
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploymod.bat b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploymod.bat
new file mode 100644
index 0000000000..b10b15d5c1
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/deploymod.bat
@@ -0,0 +1,63 @@
+@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 restextdir=%extdir%\rest
+set svcextdir=%restextdir%\service
+set srcdir=%rootdir%\runtime\extensions\rest\service\httpd\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 %restextdir% mkdir %restextdir%
+if not exist %svcextdir% mkdir %svcextdir%
+if not exist %svcextdir%\bin mkdir %svcextdir%\bin
+if not exist %svcextdir%\lib mkdir %svcextdir%\lib
+
+set libname=tuscany_sca_mod_rest
+
+del %svcextdir%\bin\%libname%.*
+del %svcextdir%\lib\%libname%.*
+
+copy %inpath%\%libname%.lib %svcextdir%\lib
+copy %inpath%\%libname%.dll %svcextdir%\bin
+
+if exist %inpath%\%libname%.pdb copy %inpath%\%libname%.pdb %svcextdir%\bin
+
+goto end
+:usage
+echo Usage: deploy <sca-root> <build-output>
+:end
+
+endlocal
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/Makefile.am
new file mode 100644
index 0000000000..f963effea2
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/Makefile.am b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/Makefile.am
new file mode 100644
index 0000000000..49d11faee3
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/Makefile.am
@@ -0,0 +1,44 @@
+libdir=$(prefix)/extensions/rest/service/lib
+lib_LTLIBRARIES = \
+libtuscany_sca_rest_service.la \
+libtuscany_sca_mod_rest.la
+
+noinst_HEADERS = \
+tuscany/sca/rest/*.h \
+tuscany/sca/rest/model/*.h
+
+libtuscany_sca_rest_service_la_SOURCES = \
+tuscany/sca/rest/RESTReferenceBindingExtension.cpp \
+tuscany/sca/rest/model/RESTReferenceBinding.cpp \
+tuscany/sca/rest/RESTServiceProxy.cpp
+
+libtuscany_sca_rest_service_la_LIBADD = \
+ -L${TUSCANY_SDOCPP}/lib -ltuscany_sdo \
+ -L$(top_builddir)/runtime/core/src -ltuscany_sca \
+ -L$(top_builddir)/runtime/extensions/rest/interface/src -ltuscany_sca_rest_interface
+
+rootdir=$(prefix)/extensions/rest/service
+
+libtuscany_sca_mod_rest_la_SOURCES = \
+tuscany/sca/rest/ModREST.cpp
+
+libtuscany_sca_mod_rest_la_LIBADD = \
+ -L${TUSCANY_SDOCPP}/lib -ltuscany_sdo \
+ -L$(top_builddir)/runtime/core/src -ltuscany_sca \
+ -L$(top_builddir)/runtime/extensions/rest/service/httpd/src -ltuscany_sca_rest_service \
+ -L$(top_builddir)/runtime/extensions/rest/interface/src -ltuscany_sca_rest_interface
+
+INCLUDES = -I$(top_builddir)/runtime/core/src \
+ -I$(top_builddir)/runtime/extensions/rest/interface/src \
+ -I${TUSCANY_SDOCPP}/include \
+ -I${HTTPD_INCLUDE} -I${APR_INCLUDE}
+
+AM_CPPFLAGS = $(CPPFLAGS) -D_DEBUG
+
+moduledir=$(prefix)/extensions/rest/service/module
+extension = libtuscany_sca_rest_service$(libsuffix)
+
+install-exec-hook:
+ test -z $(moduledir) || $(mkdir_p) $(moduledir);
+ -rm -f $(moduledir)/$(extension)
+ $(LN_S) $(libdir)/$(extension) $(moduledir)/$(extension) \ No newline at end of file
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
new file mode 100644
index 0000000000..eb3ac60e01
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/ModREST.cpp
@@ -0,0 +1,1351 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+#include <sstream>
+
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#include "apr_lib.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "ap_config.h"
+#include "httpd.h"
+
+// This section removes the windows/httpd build error "strtoul_is_not_a_portable_function_use_strtol_instead"
+#if defined(WIN32) || defined (_WINDOWS)
+#ifdef strtoul
+#undef strtoul
+#endif
+#define strtoul strtoul
+#endif
+
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+#include "util_md5.h"
+
+#include "mod_core.h"
+
+#include "commonj/sdo/SDO.h"
+
+#include "tuscany/sca/core/Exceptions.h"
+#include "tuscany/sca/util/Logging.h"
+#include "RESTServiceProxy.h"
+#include "model/RESTReferenceBinding.h"
+#include "tuscany/sca/rest/model/RESTInterface.h"
+#include "tuscany/sca/model/Composite.h"
+#include "tuscany/sca/model/CompositeService.h"
+#include "tuscany/sca/model/Component.h"
+#include "tuscany/sca/model/Reference.h"
+#include "tuscany/sca/model/ReferenceType.h"
+#include "tuscany/sca/model/WSDLDefinition.h"
+#include "tuscany/sca/model/WSDLOperation.h"
+#include "tuscany/sca/model/WSDLInterface.h"
+#include "tuscany/sca/model/Interface.h"
+#include "tuscany/sca/core/SCARuntime.h"
+#include "tuscany/sca/util/Utils.h"
+
+using namespace std;
+using namespace commonj::sdo;
+using namespace tuscany::sca;
+using namespace tuscany::sca::model;
+using namespace tuscany::sca::util;
+
+
+extern "C"
+{
+ extern module AP_MODULE_DECLARE_DATA sca_rest_module;
+}
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ typedef struct rest_server_config_rec
+ {
+ char * home;
+ } rest_server_config_rec_t;
+
+ typedef struct rest_dir_config_rec
+ {
+ char * root;
+ char * path;
+ char * base_uri;
+ char * component;
+ } rest_dir_config_rec_t;
+
+ CompositeService* initializeSCARuntime(const char* home, const char* root,
+ const char* path, const char* baseURI, const char *component, const char* service);
+
+ DataObjectPtr createPayload(DataFactoryPtr dataFactory,
+ Operation& operation, const WSDLOperation& wsdlOperation);
+
+ void addPart(XMLHelper* xmlHelper, string& payload, Operation& operation);
+
+ int logHeaders(void* request, const char* key, const char* value);
+
+ /**
+ * Initialize the SCA runtime
+ */
+ CompositeService* initializeSCARuntime(const char* home, const char* root,
+ const char* path, const char* baseURI, const char *component, const char* service)
+ {
+ logentry();
+ loginfo("Home: %s", home);
+ loginfo("Root: %s", root);
+ loginfo("Path: %s", path);
+ loginfo("Base URI: %s", baseURI);
+ loginfo("Component: %s", component);
+ loginfo("Service: %s", service);
+
+ try
+ {
+ SCARuntime* runtime = SCARuntime::initializeSharedRuntime(home, root, path, baseURI);
+
+ string componentName;
+ if (strlen(component))
+ {
+ componentName = component;
+ }
+ else
+ {
+ componentName = runtime->getDefaultComponentName();
+ }
+ string serviceName = service;
+
+ loginfo("Resolving composite: %s, service: %s", componentName.c_str(), serviceName.c_str());
+ Component* compositeComponent = runtime->getSystem()->findComponent(componentName);
+ if (compositeComponent == NULL)
+ {
+ string msg = "Component not found " + componentName;
+ throwException(SystemConfigurationException, msg.c_str());
+ }
+ runtime->setDefaultComponent(compositeComponent);
+
+ Composite* composite = (Composite*)compositeComponent->getType();
+ CompositeService* compositeService = (CompositeService*)composite->findComponent(serviceName);
+ if (compositeService == NULL)
+ {
+ string msg = "Composite service not found " + serviceName;
+ throwException(SystemConfigurationException, msg.c_str());
+ }
+
+ return compositeService;
+ }
+ catch(TuscanyRuntimeException &ex)
+ {
+ ostringstream msg;
+ msg << ex;
+ logerror("Failed to initialize SCA runtime: %s", msg.str().c_str());
+ throw;
+ }
+ }
+
+ bool printRequest = false;
+
+ int logHeaders(void* request, const char* key, const char* value)
+ {
+ loginfo("Header key: %s, value: %s", key, value);
+ if (printRequest)
+ {
+ ap_rprintf((request_rec*)request, "<br>Header key: %s, value: %s", key, value);
+ }
+ return 1;
+ }
+
+ int rest_handler(request_rec *request)
+ {
+ logentry();
+
+ if (strcmp(request->handler, "sca_rest_module"))
+ {
+ return DECLINED;
+ }
+
+ try {
+
+ // Set up the read policy
+ int rc = ap_setup_client_block(request, REQUEST_CHUNKED_DECHUNK);
+ if (rc != OK)
+ {
+ return rc;
+ }
+ ap_should_client_block(request);
+ if (request->read_chunked == true && request->remaining == 0)
+ {
+ request->chunked = true;
+ }
+
+ apr_table_setn(request->headers_out, "Connection", "close");
+
+ if (printRequest)
+ {
+ // Set the content type
+ ap_set_content_type(request, "text/html");
+
+ // Send the response document
+ ap_rputs("<html><body><p>Tuscany Mod_rest works!", request);
+ }
+
+ rest_server_config_rec_t* server_conf = (rest_server_config_rec_t*)ap_get_module_config(request->server->module_config, &sca_rest_module);
+ loginfo("Tuscany home: %s", server_conf->home);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Tuscany home: %s", server_conf->home);
+ }
+
+ rest_dir_config_rec_t* dir_conf = (rest_dir_config_rec_t*)ap_get_module_config(request->per_dir_config, &sca_rest_module);
+ loginfo("Tuscany root: %s", dir_conf->root);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Tuscany root: %s", dir_conf->root);
+ }
+ loginfo("Tuscany path: %s", dir_conf->path);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Tuscany path: %s", dir_conf->path);
+ }
+ loginfo("SCA component: %s", dir_conf->component);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>SCA component: %s", dir_conf->component);
+ }
+
+ if (request->protocol)
+ {
+ loginfo("Protocol: %s", request->protocol);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Protocol: %s", request->protocol);
+ }
+ }
+
+ if (request->method)
+ {
+ loginfo("HTTP method: %s", request->method);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>HTTP method: %s", request->method);
+ }
+ }
+
+ loginfo("HTTP method number: %d", request->method_number);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>HTTP method number: %d", request->method_number);
+ }
+
+ const char* content_type = apr_table_get(request->headers_in, "Content-Type");
+ if (content_type)
+ {
+ loginfo("Content type: %s", content_type);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Content type: %s", content_type);
+ }
+ }
+ else
+ {
+ content_type = "text/plain";
+ }
+
+ if (request->content_encoding)
+ {
+ loginfo("Content encoding: %s", request->content_encoding);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Content encoding: %s", request->content_encoding);
+ }
+ }
+
+ if (printRequest)
+ {
+ ap_rputs("<p>", request);
+ }
+ apr_table_do(logHeaders, request, request->headers_in, NULL);
+
+ if (request->uri)
+ {
+ loginfo("URI: %s", request->uri);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>URI: %s", request->uri);
+ }
+ }
+
+ if (request->path_info)
+ {
+ loginfo("Path info: %s", request->path_info);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Path info: %s", request->path_info);
+ }
+ }
+
+ if (request->args)
+ {
+ loginfo("Args: %s", request->args);
+ if (printRequest)
+ {
+ ap_rprintf(request, "<p>Args: %s", request->args);
+ }
+ }
+
+ if (printRequest)
+ {
+ ap_rputs("</body></html>", request);
+ }
+
+ // Extract the service and component names from the HTTP URI path
+ string path;
+ if (strlen(request->path_info) != 0 && *(request->path_info) == '/')
+ {
+ path = request->path_info + 1;
+ }
+ else
+ {
+ path = request->path_info;
+ }
+ string uri;
+
+ string component;
+ string service;
+ if (strlen(dir_conf->component))
+ {
+ // The path only specifies the service, the component name
+ // is configured in the directory/location configured
+ component = dir_conf->component;
+ Utils::tokeniseString("/", path, service, uri);
+ }
+ else
+ {
+ // The path must be in the form component / service
+ string path2;
+ Utils::tokeniseString("/", path, component, path2);
+ Utils::tokeniseString("/", path2, service, uri);
+ }
+
+ loginfo("Component name: %s", component.c_str());
+ loginfo("Service name: %s", service.c_str());
+
+ // Initialize the SCA runtime
+ CompositeService* compositeService = initializeSCARuntime(
+ server_conf->home, dir_conf->root, dir_conf->path, dir_conf->base_uri, component.c_str(), service.c_str());
+
+ if(!compositeService)
+ {
+ throwException(SystemConfigurationException,
+ "Failed to initialize SCA runtime, could not initialize CompositeService");
+ }
+
+ Composite* composite = compositeService->getComposite();
+ DataFactoryPtr dataFactory = composite->getDataFactory();
+ if (dataFactory == 0)
+ {
+ throwException(SystemConfigurationException,
+ "Failed to initialize SCA runtime, could not get DataFactory");
+ }
+ XMLHelper* xmlHelper = composite->getXMLHelper();
+
+ // Get the REST binding
+ Reference* reference = compositeService->getReference();
+ RESTReferenceBinding* binding = (RESTReferenceBinding*)reference->getBinding();
+
+ // Get the REST proxy
+ RESTServiceProxy* proxy = (RESTServiceProxy*)binding->getServiceProxy();
+
+ // Get the component interface
+ Interface* iface = reference->getType()->getInterface();
+
+ if (request->method_number == M_GET)
+ {
+ // Handle an HTTP GET
+
+ // Determine the operation to invoke
+ WSDLOperation wsdlOperation;
+ string wsdlNamespace = "";
+ string op_name = "";
+ string uriArgs = "";
+ if (iface != NULL)
+ {
+ // If we have a REST interface, the operation name is "retrieve"
+ if (iface->getInterfaceTypeQName() == RESTInterface::typeQName)
+ {
+ op_name = "retrieve";
+ uriArgs = uri;
+ }
+ else if (iface->getInterfaceTypeQName() == WSDLInterface::typeQName)
+ {
+ // we have a WSDL interface, the operation name is part of the URI
+ Utils::tokeniseString("/", uri, op_name, uriArgs);
+
+ // look for the WSDL operation definition
+ WSDLInterface* wsdlInterface = (WSDLInterface*)iface;
+ wsdlNamespace = wsdlInterface->getNamespaceURI();
+
+ if (wsdlNamespace != "")
+ {
+ WSDLDefinition* wsdl = composite->findWSDLDefinition(wsdlNamespace);
+ if (wsdl == 0)
+ {
+ string msg = "WSDL not found for: " + wsdlNamespace;
+ throwException(SystemConfigurationException, msg.c_str());
+ }
+ try
+ {
+ wsdlOperation = wsdl->findOperation(wsdlInterface->getName(), op_name.c_str());
+ }
+ catch(SystemConfigurationException&)
+ {
+ throw;
+ }
+
+ if (!wsdlOperation.isDocumentStyle() || !wsdlOperation.isWrappedStyle())
+ {
+ throwException(ServiceInvocationException,
+ "Only wrapped document style WSDL operations are currentlysupported");
+ }
+ }
+ }
+ }
+ else
+ {
+ Utils::tokeniseString("/", uri, op_name, uriArgs);
+ }
+
+ // Create a default document literal wrapped WSDL operation
+ if (wsdlNamespace == "")
+ {
+ wsdlNamespace = compositeService->getName();
+ wsdlOperation = WSDLOperation();
+ wsdlOperation.setOperationName(op_name.c_str());
+ wsdlOperation.setSoapAction(wsdlNamespace+ "#" +op_name);
+ wsdlOperation.setEndpoint("");
+ wsdlOperation.setSoapVersion(WSDLOperation::SOAP11);
+ wsdlOperation.setDocumentStyle(true);
+ wsdlOperation.setWrappedStyle(true);
+ wsdlOperation.setEncoded(false);
+ wsdlOperation.setInputType(string("http://tempuri.org") + "#" + op_name);
+ wsdlOperation.setOutputType(string("http://tempuri.org") + "#" + op_name + "Response");
+ }
+
+ // Create the input DataObject
+ Operation operation(op_name.c_str());
+
+ // Parse the args part of the URI
+ if (uriArgs != "")
+ {
+ string args = uriArgs;
+ for (; args != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("/", args, param, next);
+ if (param != "")
+ {
+ string* data = new string;
+ *data = param;
+ operation.addParameter(data);
+ }
+ args = next;
+ }
+ }
+
+ // Parse the query string
+ if (request->args)
+ {
+ string query = request->args;
+ for (; query != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("&", query, param, next);
+ if (param != "")
+ {
+ string n;
+ string* data = new string;
+ Utils::tokeniseString("=", param, n, *data);
+ operation.addParameter(data);
+ }
+ query = next;
+ }
+ }
+ DataObjectPtr inputDataObject = createPayload(dataFactory, operation, wsdlOperation);
+
+ // Dispatch to the REST proxy
+ DataObjectPtr outputDataObject = proxy->invoke(wsdlOperation, inputDataObject);
+
+ // Send the output DataObject
+ if (iface!=NULL &&
+ iface->getInterfaceTypeQName() == RESTInterface::typeQName)
+ {
+ if (outputDataObject == NULL)
+ {
+ throwException(ServiceInvocationException, "Null output from REST create operation");
+ }
+ else
+ {
+
+ // Pure REST, send the response document
+ XMLHelperPtr xm = HelperProvider::getXMLHelper(dataFactory);
+ DataObjectList& l = outputDataObject->getList("return");
+ if (l.size() != 0)
+ {
+ DataObjectPtr resourceDataObject = l[0];
+ XMLDocumentPtr doc = xm->createDocument(
+ resourceDataObject,
+ resourceDataObject->getType().getURI(),
+ resourceDataObject->getType().getName());
+ char* str = xm->save(doc);
+
+ // Calculate an Etag hash for the response
+ char* etag = ap_md5(request->pool, (const unsigned char*)str);
+
+ // Handle a conditional GET, if the etag matches the etag
+ // sent by the client, we don't need to send the whole response
+ const char* match = apr_table_get(request->headers_in, "If-None-Match");
+ if (match != NULL && !strcmp(etag, match))
+ {
+ loginfo("REST resource matches ETag, sending HTTP 304 response code");
+ request->status = HTTP_NOT_MODIFIED;
+ }
+ else
+ {
+ loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
+ apr_table_setn(request->headers_out, "ETag", etag);
+
+ // Send an Etag header to allow caching and
+ // conditional gets
+ apr_table_setn(request->headers_out, "ETag", etag);
+
+ ap_rputs(str, request);
+ }
+ }
+ else
+ {
+ loginfo("REST resource not found, sending HTTP 404 response code");
+ request->status = HTTP_NOT_FOUND;
+
+ return OK;
+ }
+ }
+ }
+ else
+ {
+ // Command style, send the response wrapper element
+
+ if (outputDataObject == NULL)
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
+ else
+ {
+ XMLHelperPtr xm = HelperProvider::getXMLHelper(dataFactory);
+ DataObjectList& l = outputDataObject->getList("return");
+ if (l.size() != 0)
+ {
+ DataObjectPtr resultDataObject = l[0];
+ XMLDocumentPtr doc = xm->createDocument(
+ resultDataObject,
+ resultDataObject->getType().getURI(),
+ resultDataObject->getType().getName());
+ char* str = xm->save(doc);
+
+ loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
+ ap_rputs(str, request);
+ }
+ else
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
+ }
+ }
+
+ return OK;
+ }
+ else if (request->method_number == M_POST)
+ {
+ // Handle an HTTP POST
+
+ // Determine the operation to invoke
+ WSDLOperation wsdlOperation;
+ string wsdlNamespace = "";
+ string op_name = "";
+ string uriArgs = "";
+ if (iface != NULL)
+ {
+ // If we have a REST interface, the operation name is "create"
+ if (iface->getInterfaceTypeQName() == RESTInterface::typeQName)
+ {
+ op_name = "create";
+ }
+ else if (iface->getInterfaceTypeQName() == WSDLInterface::typeQName)
+ {
+ // we have a WSDL interface, the operation name is part of the URI
+ Utils::tokeniseString("/", uri, op_name, uriArgs);
+
+ // look for the WSDL operation definition
+ WSDLInterface* wsdlInterface = (WSDLInterface*)iface;
+ wsdlNamespace = wsdlInterface->getNamespaceURI();
+
+ if (wsdlNamespace != "")
+ {
+ WSDLDefinition* wsdl = composite->findWSDLDefinition(wsdlNamespace);
+ if (wsdl == 0)
+ {
+ string msg = "WSDL not found for: " + wsdlNamespace;
+ throwException(SystemConfigurationException, msg.c_str());
+ }
+ try
+ {
+ wsdlOperation = wsdl->findOperation(wsdlInterface->getName(), op_name.c_str());
+ }
+ catch(SystemConfigurationException&)
+ {
+ throw;
+ }
+
+ if (!wsdlOperation.isDocumentStyle() || !wsdlOperation.isWrappedStyle())
+ {
+ throwException(ServiceInvocationException,
+ "Only wrapped document style WSDL operations are currentlysupported");
+ }
+ }
+ }
+ }
+ else
+ {
+ Utils::tokeniseString("/", uri, op_name, uriArgs);
+ }
+
+ // Create a default document literal wrapped WSDL operation
+ if (wsdlNamespace == "")
+ {
+ wsdlNamespace = compositeService->getName();
+ wsdlOperation = WSDLOperation();
+ wsdlOperation.setOperationName(op_name.c_str());
+ wsdlOperation.setSoapAction(wsdlNamespace+ "#" +op_name);
+ wsdlOperation.setEndpoint("");
+ wsdlOperation.setSoapVersion(WSDLOperation::SOAP11);
+ wsdlOperation.setDocumentStyle(true);
+ wsdlOperation.setWrappedStyle(true);
+ wsdlOperation.setEncoded(false);
+ wsdlOperation.setInputType(string("http://tempuri.org") + "#" + op_name);
+ wsdlOperation.setOutputType(string("http://tempuri.org") + "#" + op_name + "Response");
+ }
+
+ // Create the input DataObject
+ Operation operation(op_name.c_str());
+
+ // Parse the args part of the URI
+ if (uriArgs != "")
+ {
+ string args = uriArgs;
+ for (; args != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("/", args, param, next);
+ if (param != "")
+ {
+ string* data = new string;
+ *data = param;
+ operation.addParameter(data);
+ }
+ args = next;
+ }
+ }
+
+ // Parse the query string
+ if (request->args)
+ {
+ string query = request->args;
+ for (; query != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("&", query, param, next);
+ if (param != "")
+ {
+ string n;
+ string* data = new string;
+ Utils::tokeniseString("=", param, n, *data);
+ operation.addParameter(data);
+ }
+ query = next;
+ }
+ }
+
+ // Read the POST input
+ ostringstream sinput;
+ char buffer[2049];
+ for ( ; ; )
+ {
+ int size = ap_get_client_block(request, buffer, 2048);
+ if (size > 0)
+ {
+ buffer[size] = '\0';
+ sinput << buffer;
+ }
+ else if (size == 0)
+ {
+ break;
+ }
+ else if (size < 0)
+ {
+ throwException(ServiceInvocationException, "Error reading POST input");
+ }
+ }
+ string input = sinput.str();
+
+ string contentType = content_type;
+ if (contentType.find("multipart/form-data") == 0)
+ {
+ // This is a multipart POST, extract each part from the
+ // POST body
+ string begin;
+ string boundary;
+ Utils::tokeniseString("boundary=", contentType, begin, boundary);
+
+ for (;;)
+ {
+ // Read each part
+ string part;
+ string next;
+ Utils::tokeniseString(boundary, input, part, next);
+ input = next;
+
+ // Skip first and last empty parts
+ if (part.length() == 0 || part == "--")
+ continue;
+
+ // Read headers
+ bool xml = false;
+ int empty = -1;
+ for (;;)
+ {
+ string header;
+ Utils::tokeniseString("\r\n", part, header, next);
+ part = next;
+ if (header == "")
+ {
+ // Two empty lines signal the beginning of the content
+ empty++;
+ if (empty == 1)
+ break;
+ }
+ else
+ {
+ empty = 0;
+
+ // Detect XML content
+ if (header == "Content-Type: text/xml")
+ xml = true;
+ }
+ }
+
+ // Read the part content
+ if (part.length())
+ {
+ // Strip the trailer
+ string value;
+ Utils::tokeniseString("\r\n--", part, value, next);
+
+ if (xml)
+ {
+ // Add an XML parameter to the operation
+ addPart(xmlHelper, value, operation);
+ }
+ else
+ {
+ // Add a text parameter to the operation
+ string* stringData = new string;
+ *stringData = value;
+ operation.addParameter(stringData);
+ }
+ }
+
+ // Read till the end of the POST body
+ if (input.length() == 0)
+ break;
+ }
+ }
+ else
+ {
+ // The POST body represents a single part
+ addPart(xmlHelper, input, operation);
+ }
+
+ DataObjectPtr inputDataObject = createPayload(dataFactory, operation, wsdlOperation);
+
+ // Dispatch to the REST proxy
+ DataObjectPtr outputDataObject = proxy->invoke(wsdlOperation, inputDataObject);
+
+ // Send the response back to the client
+ if (iface!=NULL &&
+ iface->getInterfaceTypeQName() == RESTInterface::typeQName)
+ {
+ // Pure REST, send the location of the created resource
+
+ if (outputDataObject == NULL)
+ {
+ throwException(ServiceInvocationException, "Null output from REST create operation");
+ }
+
+ string location = "";
+
+ DataObjectList& l = outputDataObject->getList("return");
+ if (l.size())
+ {
+ location = l.getCString(0);
+ }
+
+ if (location == "")
+ {
+ loginfo("No resource location, sending HTTP 400 response code");
+ request->status = HTTP_BAD_REQUEST;
+
+ return OK;
+ }
+
+ string locuri = request->uri;
+ locuri += '/';
+ locuri += location;
+
+ const char* loc = ap_construct_url(request->pool, locuri.c_str(), request);
+ loginfo("Sending resource location: %s", loc);
+ apr_table_setn(request->headers_out, "Location", loc);
+ apr_table_setn(request->headers_out, "Content-Location", loc);
+ request->status = HTTP_CREATED;
+
+ // Send the created resource entity back to the client
+ ap_set_content_type(request, "text/xml");
+ ap_rputs(input.c_str(), request);
+
+ }
+ else
+ {
+ // Command style, send the response element
+
+ if (outputDataObject == NULL)
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
+ else
+ {
+ XMLHelperPtr xm = HelperProvider::getXMLHelper(dataFactory);
+ DataObjectList& l = outputDataObject->getList("return");
+ if (l.size() != 0)
+ {
+ DataObjectPtr resultDataObject = l[0];
+ XMLDocumentPtr doc = xm->createDocument(
+ resultDataObject,
+ resultDataObject->getType().getURI(),
+ resultDataObject->getType().getName());
+ char* str = xm->save(doc);
+
+ loginfo("Sending response: %s", str);
+ ap_set_content_type(request, "text/xml");
+ ap_rputs(str, request);
+ }
+ else
+ {
+ loginfo("Sending empty response");
+ //request->status = HTTP_NO_CONTENT;
+ }
+ }
+ }
+
+ return OK;
+ }
+ else if (request->method_number == M_PUT)
+ {
+
+ // Handle an HTTP PUT
+
+ // Determine the operation to invoke
+ WSDLOperation wsdlOperation;
+ string wsdlNamespace = "";
+ string op_name = "update";
+ string uriArgs = uri;
+
+ // Create a default document literal wrapped WSDL operation
+ wsdlNamespace = compositeService->getName();
+ wsdlOperation = WSDLOperation();
+ wsdlOperation.setOperationName(op_name.c_str());
+ wsdlOperation.setSoapAction(wsdlNamespace+ "#" +op_name);
+ wsdlOperation.setEndpoint("");
+ wsdlOperation.setSoapVersion(WSDLOperation::SOAP11);
+ wsdlOperation.setDocumentStyle(true);
+ wsdlOperation.setWrappedStyle(true);
+ wsdlOperation.setEncoded(false);
+ wsdlOperation.setInputType(string("http://tempuri.org") + "#" + op_name);
+ wsdlOperation.setOutputType(string("http://tempuri.org") + "#" + op_name + "Response");
+
+ // Create the input DataObject
+ Operation operation(op_name.c_str());
+
+ // Parse the args part of the URI
+ if (uriArgs != "")
+ {
+ string args = uriArgs;
+ for (; args != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("/", args, param, next);
+ if (param != "")
+ {
+ string* data = new string;
+ *data = param;
+ operation.addParameter(data);
+ }
+ args = next;
+ }
+ }
+
+ // Parse the query string
+ if (request->args)
+ {
+ string query = request->args;
+ for (; query != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("&", query, param, next);
+ if (param != "")
+ {
+ string n;
+ string* data = new string;
+ Utils::tokeniseString("=", param, n, *data);
+ operation.addParameter(data);
+ }
+ query = next;
+ }
+ }
+
+ // Read the PUT input
+ ostringstream sinput;
+ char buffer[2049];
+ for ( ; ; )
+ {
+ int size = ap_get_client_block(request, buffer, 2048);
+ if (size > 0)
+ {
+ buffer[size] = '\0';
+ sinput << buffer;
+ }
+ else if (size == 0)
+ {
+ break;
+ }
+ else if (size < 0)
+ {
+ throwException(ServiceInvocationException, "Error reading PUT input");
+ }
+ }
+ string input = sinput.str();
+ addPart(xmlHelper, input, operation);
+
+ DataObjectPtr inputDataObject = createPayload(dataFactory, operation, wsdlOperation);
+
+ // Dispatch to the REST proxy
+ DataObjectPtr outputDataObject = proxy->invoke(wsdlOperation, inputDataObject);
+
+ // Empty response
+ //request->status = HTTP_NO_CONTENT;
+ return OK;
+ }
+ else if (request->method_number == M_DELETE)
+ {
+
+ // Determine the operation to invoke
+ WSDLOperation wsdlOperation;
+ string wsdlNamespace = "";
+ string op_name = "delete";
+ string uriArgs = uri;
+
+ // Create a default document literal wrapped WSDL operation
+ wsdlNamespace = compositeService->getName();
+ wsdlOperation = WSDLOperation();
+ wsdlOperation.setOperationName(op_name.c_str());
+ wsdlOperation.setSoapAction(wsdlNamespace+ "#" +op_name);
+ wsdlOperation.setEndpoint("");
+ wsdlOperation.setSoapVersion(WSDLOperation::SOAP11);
+ wsdlOperation.setDocumentStyle(true);
+ wsdlOperation.setWrappedStyle(true);
+ wsdlOperation.setEncoded(false);
+ wsdlOperation.setInputType(string("http://tempuri.org") + "#" + op_name);
+ wsdlOperation.setOutputType(string("http://tempuri.org") + "#" + op_name + "Response");
+
+ // Create the input DataObject
+ Operation operation(op_name.c_str());
+
+ // Parse the args part of the URI
+ if (uriArgs != "")
+ {
+ string args = uriArgs;
+ for (; args != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("/", args, param, next);
+ if (param != "")
+ {
+ string* data = new string;
+ *data = param;
+ operation.addParameter(data);
+ }
+ args = next;
+ }
+ }
+
+ // Parse the query string
+ if (request->args)
+ {
+ string query = request->args;
+ for (; query != ""; )
+ {
+ string param;
+ string next;
+ Utils::tokeniseString("&", query, param, next);
+ if (param != "")
+ {
+ string n;
+ string* data = new string;
+ Utils::tokeniseString("=", param, n, *data);
+ operation.addParameter(data);
+ }
+ query = next;
+ }
+ }
+
+ DataObjectPtr inputDataObject = createPayload(dataFactory, operation, wsdlOperation);
+
+ // Dispatch to the REST proxy
+ DataObjectPtr outputDataObject = proxy->invoke(wsdlOperation, inputDataObject);
+
+ // Empty response
+ //request->status = HTTP_NO_CONTENT;
+ return OK;
+ }
+ else
+ {
+ if (request->method)
+ {
+ logerror("Unsupported HTTP method: %s", request->method);
+ }
+ else
+ {
+ logerror("Unsupported HTTP method: %d", request->method_number);
+ }
+ return HTTP_NOT_IMPLEMENTED;
+ }
+ }
+ catch(TuscanyRuntimeException& ex)
+ {
+ ostringstream msg;
+ msg << ex;
+ logerror("Failed to process REST request: %s", msg.str().c_str());
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+
+ DataObjectPtr createPayload(DataFactoryPtr dataFactory, Operation& operation, const WSDLOperation& wsdlOperation)
+ {
+ logentry();
+
+ DataObjectPtr inputDataObject;
+ try
+ {
+
+ // Create the input wrapper
+ const Type& rootType = dataFactory->getType(wsdlOperation.getInputTypeUri().c_str(), "RootType");
+ const Property& prop = rootType.getProperty(wsdlOperation.getInputTypeName().c_str());
+ const Type& inputType = prop.getType();
+ inputDataObject = dataFactory->create(inputType);
+ }
+ catch (SDORuntimeException&)
+ {
+ try
+ {
+ // Create the input wrapper
+ const Type& inputType = dataFactory->getType(wsdlOperation.getInputTypeUri().c_str(),
+ wsdlOperation.getInputTypeName().c_str());
+ inputDataObject = dataFactory->create(inputType);
+ }
+ catch (SDORuntimeException&)
+ {
+
+ // The input wrapper type is not known, create an open DataObject
+ inputDataObject = dataFactory->create("http://tempuri.org", "Wrapper");
+ }
+ }
+
+ // Go through data object to set the input parameters
+ PropertyList pl = inputDataObject->getType().getProperties();
+
+ if(pl.size() == 0)
+ {
+ if(inputDataObject->getType().isOpenType() && inputDataObject->getType().isDataObjectType())
+ {
+ /*
+ * This code deals with sending xsd:any elements
+ */
+ for (int i=0; i<operation.getNParms(); i++)
+ {
+ ostringstream pname;
+ pname << "param" << (i+1);
+ DataObjectList& l = inputDataObject->getList(pname.str());
+
+ const Operation::Parameter& parm = operation.getParameter(i);
+ switch(parm.getType())
+ {
+ case Operation::STRING:
+ {
+ l.append((*(string*)parm.getValue()).c_str());
+ break;
+ }
+ case Operation::DATAOBJECT:
+ {
+ l.append(*(DataObjectPtr*)parm.getValue());
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else {
+
+ // Each parameter in the operation should be a property on the request dataobject
+ for (unsigned int i=0; i<operation.getNParms(); i++)
+ {
+ const Operation::Parameter& parm = operation.getParameter(i);
+ switch(parm.getType())
+ {
+ case Operation::STRING:
+ {
+ inputDataObject->setCString(i, (*(string*)parm.getValue()).c_str());
+ break;
+ }
+ case Operation::DATAOBJECT:
+ {
+ inputDataObject->setDataObject(i, *(DataObjectPtr*)parm.getValue());
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return inputDataObject;
+ }
+
+ void addPart(XMLHelper* xmlHelper, string& payload, Operation& operation)
+ {
+ logentry();
+
+
+ //TODO Remove this workaround once SDO supports loading of open top level content
+ // The workaround is to wrap the open content in a wrapper element
+ string xmldecl;
+ string xml;
+ Utils::rTokeniseString("?>", payload, xmldecl, xml);
+ string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ body += "<Wrapper xmlns=\"http://tempuri.org\" xmlns:tns=\"http://tempuri.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
+ body += xml;
+ body += "\n</Wrapper>";
+
+ // Convert the body to an SDO DataObject
+ DataObjectPtr inputWrapperDataObject = NULL;
+ XMLDocumentPtr theXMLDocument = xmlHelper->load(body.c_str(), NULL);
+ if (theXMLDocument != 0)
+ {
+ inputWrapperDataObject = theXMLDocument->getRootDataObject();
+ }
+ if(!inputWrapperDataObject)
+ {
+ ostringstream msg;
+ msg << "Could not convert received document to SDO: " << body;
+ throwException(ServiceDataException, msg.str().c_str());
+ }
+
+ // Get the body part
+ DataObjectPtr inputDataObject = NULL;
+ PropertyList bpl = inputWrapperDataObject->getInstanceProperties();
+ if (bpl.size()!=0)
+ {
+ if (bpl[0].isMany())
+ {
+ DataObjectList& parts = inputWrapperDataObject->getList((unsigned int)0);
+ inputDataObject = parts[0];
+ }
+ else
+ {
+ inputDataObject = inputWrapperDataObject->getDataObject(bpl[0]);
+ }
+ }
+ if (inputDataObject == NULL)
+ {
+ ostringstream msg;
+ msg << "Could not convert received document to SDO: " << body;
+ throwException(ServiceDataException, msg.str().c_str());
+ }
+
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ *dataObjectData = inputDataObject;
+ (*dataObjectData)->detach();
+ operation.addParameter(dataObjectData);
+ }
+
+ const char *rest_set_home(cmd_parms *cmd, void *dummy,
+ const char *arg)
+ {
+ rest_server_config_rec_t *conf = (rest_server_config_rec_t*)ap_get_module_config(
+ cmd->server->module_config, &sca_rest_module);
+ conf->home = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ const char *rest_set_path(cmd_parms *cmd, void *c,
+ const char *arg)
+ {
+ rest_dir_config_rec_t *conf = (rest_dir_config_rec_t*)c;
+ conf->path = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ const char *rest_set_root(cmd_parms *cmd, void *c,
+ const char *arg)
+ {
+ rest_dir_config_rec_t *conf = (rest_dir_config_rec_t*)c;
+ conf->root = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ const char *rest_set_base_uri(cmd_parms *cmd, void *c,
+ const char *arg)
+ {
+ rest_dir_config_rec_t *conf = (rest_dir_config_rec_t*)c;
+ conf->base_uri = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ const char *rest_set_component(cmd_parms *cmd, void *c,
+ const char *arg)
+ {
+ rest_dir_config_rec_t *conf = (rest_dir_config_rec_t*)c;
+ conf->component = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+ }
+
+ const command_rec rest_module_cmds[] =
+ {
+ AP_INIT_TAKE1("TuscanyHome", (const char*(*)())tuscany::sca::rest::rest_set_home, NULL, RSRC_CONF,
+ "Tuscany home directory"),
+ AP_INIT_TAKE1("TuscanyPath", (const char*(*)())tuscany::sca::rest::rest_set_path, NULL, ACCESS_CONF,
+ "Tuscany SCA composite search path"),
+ AP_INIT_TAKE1("TuscanyRoot", (const char*(*)())tuscany::sca::rest::rest_set_root, NULL, ACCESS_CONF,
+ "Tuscany root SCA configuration path"),
+ AP_INIT_TAKE1("TuscanyBaseURI", (const char*(*)())tuscany::sca::rest::rest_set_base_uri, NULL, ACCESS_CONF,
+ "Tuscany SCA system base URI"),
+ AP_INIT_TAKE1("TuscanyComponent", (const char*(*)())tuscany::sca::rest::rest_set_component, NULL, ACCESS_CONF,
+ "SCA component name"),
+ {NULL}
+ };
+
+ int rest_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
+ server_rec *s)
+ {
+ return OK;
+ }
+
+ void rest_child_init(apr_pool_t* p, server_rec* svr_rec)
+ {
+ rest_server_config_rec_t *conf = (rest_server_config_rec_t*)ap_get_module_config(
+ svr_rec->module_config, &sca_rest_module);
+
+ if(false)
+ {
+ fprintf(stderr, "[Tuscany] Due to one or more errors mod_rest loading"
+ " failed. Causing apache2 to stop loading\n");
+ exit(APEXIT_CHILDFATAL);
+ }
+ }
+
+ void register_hooks(apr_pool_t *p)
+ {
+ ap_hook_handler(rest_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(rest_init, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(rest_child_init, NULL, NULL, APR_HOOK_MIDDLE);
+ }
+
+ void *rest_create_dir_config(apr_pool_t *p, char *dirspec)
+ {
+ rest_dir_config_rec_t* conf = (rest_dir_config_rec_t* )apr_palloc(p, sizeof(*conf));
+ conf->path = "";
+ conf->root = "";
+ conf->base_uri = "";
+ conf->component = "";
+ return conf;
+ }
+
+ void* rest_create_server_config(apr_pool_t *p, server_rec *s)
+ {
+ rest_server_config_rec_t* conf = (rest_server_config_rec_t* )apr_palloc(p, sizeof(*conf));
+ conf->home = "";
+ return conf;
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+extern "C"
+{
+
+ module AP_MODULE_DECLARE_DATA sca_rest_module =
+ {
+ STANDARD20_MODULE_STUFF,
+ tuscany::sca::rest::rest_create_dir_config, /* dir config */
+ NULL, /* dir merger --- default is to override */
+ tuscany::sca::rest::rest_create_server_config, /* server config */
+ NULL, /* merge server config */
+ tuscany::sca::rest::rest_module_cmds, /* command table */
+ tuscany::sca::rest::register_hooks /* register_hooks */
+ };
+
+}
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.cpp
new file mode 100644
index 0000000000..18720f42f5
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.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.
+*/
+
+#include "RESTReferenceBindingExtension.h"
+#include "model/RESTReferenceBinding.h"
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/util/Utils.h"
+#include "tuscany/sca/core/SCARuntime.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_rest_service_initialize()
+ {
+ tuscany::sca::rest::RESTReferenceBindingExtension::initialize();
+ }
+}
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ // ===================================================================
+ // Constructor for the RESTReferenceBinding class.
+ // ===================================================================
+ RESTReferenceBindingExtension::RESTReferenceBindingExtension()
+ {
+ logentry();
+ }
+
+ // ===================================================================
+ // Destructor for the RESTReferenceBindingExtension class.
+ // ===================================================================
+ RESTReferenceBindingExtension::~RESTReferenceBindingExtension()
+ {
+ logentry();
+ }
+
+ const string RESTReferenceBindingExtension::extensionName("rest");
+ const string RESTReferenceBindingExtension::typeQName("http://www.osoa.org/xmlns/sca/1.0#RESTBinding");
+
+ // ===================================================================
+ // loadModelElement - load the info from binding.rest
+ // ===================================================================
+ ReferenceBinding* RESTReferenceBindingExtension::getReferenceBinding(Composite *composite, Reference* reference, DataObjectPtr scdlBinding)
+ {
+ string uri = scdlBinding->getCString("uri");
+
+ RESTReferenceBinding* referenceBinding = new RESTReferenceBinding(reference, uri);
+
+ return referenceBinding;
+ }
+
+ void RESTReferenceBindingExtension::initialize()
+ {
+ logentry();
+ SCARuntime::getCurrentRuntime()->registerReferenceBindingExtension(new RESTReferenceBindingExtension());
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.h
new file mode 100644
index 0000000000..0d9e41841b
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTReferenceBindingExtension.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.
+ */
+
+#ifndef tuscany_sca_extension_rest_restreferencebindingextension_h
+#define tuscany_sca_extension_rest_restreferencebindingextension_h
+
+#include "tuscany/sca/extension/ReferenceBindingExtension.h"
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ class RESTReferenceBindingExtension : public ReferenceBindingExtension
+ {
+ public:
+ /**
+ * Default constructor
+ */
+ RESTReferenceBindingExtension();
+
+ /**
+ * Destructor
+ */
+ virtual ~RESTReferenceBindingExtension();
+
+ /**
+ * 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#binding.rest")
+ */
+ virtual const std::string& getExtensionTypeQName() {return typeQName;}
+
+ virtual tuscany::sca::model::ReferenceBinding* getReferenceBinding(
+ tuscany::sca::model::Composite* composite,
+ tuscany::sca::model::Reference *reference,
+ commonj::sdo::DataObjectPtr scdlBinding);
+
+ static void initialize();
+
+ private:
+ static const std::string extensionName;
+ static const std::string typeQName;
+
+ };
+
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_extension_rest_restreferencebindingextension_h
+
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
new file mode 100644
index 0000000000..5806c83773
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.cpp
@@ -0,0 +1,559 @@
+/*
+ * 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 <sstream>
+
+#include "commonj/sdo/SDO.h"
+
+#include "RESTServiceProxy.h"
+#include "tuscany/sca/util/Logging.h"
+#include "tuscany/sca/core/Exceptions.h"
+#include "tuscany/sca/util/Utils.h"
+#include "tuscany/sca/core/SCARuntime.h"
+#include "tuscany/sca/model/Reference.h"
+#include "tuscany/sca/model/ReferenceType.h"
+#include "tuscany/sca/model/Service.h"
+#include "tuscany/sca/model/ServiceType.h"
+#include "tuscany/sca/model/Component.h"
+#include "tuscany/sca/model/ComponentType.h"
+#include "tuscany/sca/core/ServiceWrapper.h"
+#include "tuscany/sca/model/Composite.h"
+#include "tuscany/sca/model/ServiceBinding.h"
+#include "tuscany/sca/model/WSDLDefinition.h"
+#include "tuscany/sca/model/WSDLInterface.h"
+#include "tuscany/sca/model/WSDLOperation.h"
+#include "model/RESTReferenceBinding.h"
+
+using namespace std;
+using namespace commonj::sdo;
+using namespace tuscany::sca::model;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ // ============================
+ // Constructor: Create a proxy
+ // ============================
+ RESTServiceProxy::RESTServiceProxy(Reference* reference)
+ : ServiceProxy(reference)
+ {
+ logentry();
+
+ // Get the target service wrapper
+ RESTReferenceBinding* referenceBinding = (RESTReferenceBinding*)reference->getBinding();
+ serviceWrapper = referenceBinding->getTargetServiceBinding()->getServiceWrapper();
+
+ DataFactoryPtr dataFactory = reference->getComponent()->getComposite()->getDataFactory();
+ try {
+ const Type& tempType = dataFactory->getType("http://tempuri.org", "RootType");
+ } catch (SDORuntimeException&)
+ {
+ dataFactory->addType("http://tempuri.org", "RootType", false, false, false);
+ dataFactory->addType("http://tempuri.org", "Wrapper", false, true, false);
+ dataFactory->addPropertyToType(
+ "http://tempuri.org", "RootType",
+ "Wrapper",
+ "http://tempuri.org", "Wrapper",
+ false, false, true);
+ dataFactory->addType("http://tempuri.org", "Part", false, true, false);
+ dataFactory->addPropertyToType(
+ "http://tempuri.org", "RootType",
+ "Part",
+ "http://tempuri.org", "Part",
+ false, false, true);
+ }
+ }
+
+ // ==========
+ // Destructor
+ // ==========
+ RESTServiceProxy::~RESTServiceProxy()
+ {
+ logentry();
+ }
+
+ ///
+ /// This method will be called to process an operation invocation.
+ ///
+ DataObjectPtr RESTServiceProxy::invoke(const WSDLOperation& wsdlOperation, DataObjectPtr inputDataObject)
+ {
+ logentry();
+
+ Reference* reference = getReference();
+ Component* component = reference->getComponent();
+ Composite* composite = component ->getComposite();
+
+ RESTReferenceBinding* referenceBinding = (RESTReferenceBinding*)reference->getBinding();
+ DataFactoryPtr dataFactoryPtr = reference->getComponent()->getComposite()->getDataFactory();
+
+ const char* outputTypeURI = wsdlOperation.getOutputTypeUri().c_str();
+ const char* outputTypeName = wsdlOperation.getOutputTypeName().c_str();
+
+ loginfo("WSDLOperation inputType: %s#%s",
+ wsdlOperation.getInputTypeUri().c_str(),
+ wsdlOperation.getInputTypeName().c_str());
+ loginfo("WSDLOperation outputType: %s#%s",
+ outputTypeURI,
+ outputTypeName);
+
+ // Create new Operation object and set parameters and return value
+ Operation operation(wsdlOperation.getOperationName().c_str());
+
+ try
+ {
+
+ // Go through the input data object to set the operation parameters
+ PropertyList pl = inputDataObject->getInstanceProperties();
+
+ for(int i=0; i<pl.size(); i++)
+ {
+ const char* name = pl[i].getName();
+
+ switch (pl[i].getTypeEnum())
+ {
+ case Type::BooleanType:
+ {
+ bool* boolData = new bool;
+ *boolData = inputDataObject->getBoolean(pl[i]);
+ operation.addParameter(boolData);
+ }
+ break;
+ case Type::ByteType:
+ {
+ char* byteData = new char;
+ *byteData = inputDataObject->getByte(pl[i]);
+ operation.addParameter(byteData);
+ }
+ break;
+ case Type::BytesType:
+ {
+ int len = inputDataObject->getLength(pl[i]);
+ char** bytesData = new char*;
+ *bytesData = new char[len+1];
+ int bytesWritten = inputDataObject->getBytes(pl[i], *bytesData, len);
+ // Ensure the bytes end with the null char. Not sure if this is neccessary
+ if(bytesWritten <= len)
+ {
+ (*bytesData)[bytesWritten] = 0;
+ }
+ else
+ {
+ (*bytesData)[len] = 0;
+ }
+ operation.addParameter(bytesData);
+ }
+ break;
+ case Type::CharacterType:
+ {
+ // This code should work but won't be used as there is no mapping from an XSD type to the SDO CharacterType
+ wchar_t* charData = new wchar_t;
+ *charData = inputDataObject->getCharacter(pl[i]);
+ operation.addParameter(charData);
+ }
+ break;
+ case Type::DoubleType:
+ {
+ long double* doubleData = new long double;
+ *doubleData = inputDataObject->getDouble(pl[i]);
+ operation.addParameter(doubleData);
+ }
+ break;
+ case Type::FloatType:
+ {
+ float* floatData = new float;
+ *floatData = inputDataObject->getFloat(pl[i]);
+ operation.addParameter(floatData);
+ }
+ break;
+ case Type::IntegerType:
+ {
+ long* intData = new long;
+ *intData = inputDataObject->getInteger(pl[i]);
+ operation.addParameter(intData);
+ }
+ break;
+ case Type::ShortType:
+ {
+ short* shortData = new short;
+ *shortData = inputDataObject->getShort(pl[i]);
+ operation.addParameter(shortData);
+ }
+ break;
+ case Type::StringType:
+ {
+ string* stringData;
+ if (pl[i].isMany())
+ {
+ DataObjectList& l = inputDataObject->getList(pl[i]);
+ stringData = new string(l.getCString(0));
+ }
+ else
+ {
+ if(inputDataObject->isSet(pl[i]))
+ {
+ stringData = new string(inputDataObject->getCString(pl[i]));
+ }
+ else
+ {
+ // The data is not set, so pass an empty string as the parameter
+ stringData = new string();
+ }
+ }
+ operation.addParameter(stringData);
+ }
+ break;
+ case Type::DataObjectType:
+ {
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ if (pl[i].isMany())
+ {
+ DataObjectList& l = inputDataObject->getList((unsigned int)i);
+ *dataObjectData = l[0];
+ }
+ else
+ {
+ *dataObjectData = inputDataObject->getDataObject(pl[i]);
+ }
+ if(!*dataObjectData)
+ {
+ loginfo("Null DataObject parameter named %s", name);
+ }
+ else
+ {
+ (*dataObjectData)->detach();
+ }
+ operation.addParameter(dataObjectData);
+ }
+ break;
+ case Type::OpenDataObjectType:
+ {
+ /*
+ * This code deals with xsd:any element parameters
+ * Get each element as a DataObject and add in to the parameter list
+ */
+
+ DataObjectList& dataObjectList = inputDataObject->getList(pl[i]);
+
+ for(int j=0; j<dataObjectList.size(); j++)
+ {
+ DataObjectPtr dob = dataObjectList[j];
+ if(!dob)
+ {
+
+ // Add a null DataObject ptr
+ DataObjectPtr* dataObjectData = new DataObjectPtr;
+ *dataObjectData = NULL;
+ loginfo("Null OpenDataObject parameter named %s[%d]", name, j);
+ operation.addParameter(dataObjectData);
+ }
+ else
+ {
+
+ SequencePtr sequence = dob->getSequence();
+ if (sequence->size()!=0)
+ {
+ // Add a text element
+ if (sequence->isText(0))
+ {
+ string* stringData = new string(sequence->getCStringValue(0));
+ operation.addParameter(stringData);
+ }
+ else
+ {
+ // Add a complex element DataObject
+ DataObjectPtr* dataObjectData =new DataObjectPtr;
+ *dataObjectData = sequence->getDataObjectValue(0);
+ if(!*dataObjectData)
+ {
+ loginfo("Null DataObject parameter named %s", name);
+ }
+ else
+ {
+ (*dataObjectData)->detach();
+ }
+ operation.addParameter(dataObjectData);
+ }
+ }
+ else
+ {
+ // Empty content, add an empty string
+ loginfo("Empty OpenDataObject parameter named %s[%d]", name, j);
+ string* stringData = new string("");
+ operation.addParameter(stringData);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ ostringstream msg;
+ msg << "Unsupported param type: " << pl[i].getTypeEnum();
+ throwException(SystemConfigurationException, msg.str().c_str());
+ }
+ }
+ }
+
+ // Call into the target service wrapper
+ serviceWrapper->invoke(operation);
+
+ // Set the data in the outputDataObject to be returned
+ DataObjectPtr outputDataObject;
+ try {
+
+ // Create the output wrapper
+ const Type& rootType = dataFactoryPtr->getType(outputTypeURI, "RootType");
+ const Property& prop = rootType.getProperty(outputTypeName);
+ const Type& outputType = prop.getType();
+ outputDataObject = dataFactoryPtr->create(outputType);
+ }
+ catch (SDORuntimeException&)
+ {
+ try
+ {
+
+ // Create the output wrapper
+ const Type& outputType = dataFactoryPtr->getType(outputTypeURI, outputTypeName);
+ outputDataObject = dataFactoryPtr->create(outputType);
+ }
+ catch (SDORuntimeException&)
+ {
+ // The output wrapper type is not known, create an open DataObject
+ outputDataObject = dataFactoryPtr->create("http://tempuri.org", "Wrapper");
+ }
+ }
+
+ setOutputData(operation, outputDataObject, dataFactoryPtr);
+
+ return outputDataObject;
+ }
+ catch(SDORuntimeException& ex)
+ {
+ throwException(ServiceInvocationException, ex);
+ }
+ catch(TuscanyRuntimeException& ex)
+ {
+ throw;
+ }
+ }
+
+
+ void RESTServiceProxy::setOutputData(Operation& operation, DataObjectPtr outputDataObject, DataFactoryPtr dataFactoryPtr)
+ {
+ logentry();
+
+ // Go through data object to set the return value
+ PropertyList pl = outputDataObject->getType().getProperties();
+
+ if(pl.size() == 0)
+ {
+ if(outputDataObject->getType().isOpenType() && outputDataObject->getType().isDataObjectType())
+ {
+ /*
+ * This code deals with returning xsd:any elements
+ */
+ DataObjectList& l = outputDataObject->getList("return");
+ Operation::ParameterType resultType = operation.getReturnType();
+ switch(resultType)
+ {
+ case Operation::BOOL:
+ {
+ l.append(*(bool*)operation.getReturnValue());
+ break;
+ }
+ case Operation::SHORT:
+ {
+ l.append(*(short*)operation.getReturnValue());
+ break;
+ }
+ case Operation::INT:
+ {
+ l.append(*(long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::LONG:
+ {
+ l.append(*(long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::USHORT:
+ {
+ l.append(*(short*)operation.getReturnValue());
+ break;
+ }
+ case Operation::UINT:
+ {
+ l.append(*(long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::ULONG:
+ {
+ l.append(*(long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::FLOAT:
+ {
+ l.append(*(float*)operation.getReturnValue());
+ break;
+ }
+ case Operation::DOUBLE:
+ {
+ l.append(*(long double*)operation.getReturnValue());
+ break;
+ }
+ case Operation::LONGDOUBLE:
+ {
+ l.append(*(long double*)operation.getReturnValue());
+ break;
+ }
+ case Operation::CHARS:
+ {
+ l.append(*(char**)operation.getReturnValue());
+ break;
+ }
+ case Operation::STRING:
+ {
+ l.append((*(string*)operation.getReturnValue()).c_str());
+ break;
+ }
+ case Operation::DATAOBJECT:
+ {
+ l.append(*(DataObjectPtr*)operation.getReturnValue());
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ loginfo("No return values defined");
+ }
+ }
+ else {
+
+ // Should only be one return value.. This goes through all return values
+ for(int i=0; i<pl.size(); i++)
+ {
+ const char* name = pl[i].getName();
+
+ Operation::ParameterType resultType = operation.getReturnType();
+ switch(resultType)
+ {
+ case Operation::BOOL:
+ {
+ outputDataObject->setBoolean(pl[i], *(bool*)operation.getReturnValue());
+ break;
+ }
+ case Operation::SHORT:
+ {
+ outputDataObject->setShort(pl[i], *(short*)operation.getReturnValue());
+ break;
+ }
+ case Operation::INT:
+ {
+ outputDataObject->setInteger(pl[i], *(int*)operation.getReturnValue());
+ break;
+ }
+ case Operation::LONG:
+ {
+ outputDataObject->setInteger(pl[i], *(long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::USHORT:
+ {
+ outputDataObject->setInteger(pl[i], *(unsigned short*)operation.getReturnValue());
+ break;
+ }
+ case Operation::UINT:
+ {
+ outputDataObject->setInteger(pl[i], *(unsigned int*)operation.getReturnValue());
+ break;
+ }
+ case Operation::ULONG:
+ {
+ outputDataObject->setInteger(pl[i], *(unsigned long*)operation.getReturnValue());
+ break;
+ }
+ case Operation::FLOAT:
+ {
+ outputDataObject->setFloat(pl[i], *(float*)operation.getReturnValue());
+ break;
+ }
+ case Operation::DOUBLE:
+ {
+ outputDataObject->setDouble(pl[i], *(double*)operation.getReturnValue());
+ break;
+ }
+ case Operation::LONGDOUBLE:
+ {
+ outputDataObject->setDouble(pl[i], *(long double*)operation.getReturnValue());
+ break;
+ }
+ case Operation::CHARS:
+ {
+ if(*(char**)operation.getReturnValue() != NULL)
+ {
+ outputDataObject->setCString(pl[i], *(char**)operation.getReturnValue());
+ }
+ else
+ {
+ loginfo("Null return value, leaving property %s unset", pl[i].getName());
+ }
+ break;
+ }
+ case Operation::STRING:
+ {
+ outputDataObject->setCString(pl[i], (*(string*)operation.getReturnValue()).c_str());
+ break;
+ }
+ case Operation::DATAOBJECT:
+ {
+
+ if(*(DataObjectPtr*)operation.getReturnValue() != NULL)
+ {
+ outputDataObject->setDataObject(pl[i], *(DataObjectPtr*)operation.getReturnValue());
+ }
+ else
+ {
+ loginfo("Null return value, leaving property %s unset", pl[i].getName());
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.h
new file mode 100644
index 0000000000..387add3f35
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/RESTServiceProxy.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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_extension_rest_restserviceproxy_h
+#define tuscany_sca_extension_rest_restserviceproxy_h
+
+#include "commonj/sdo/SDO.h"
+
+#include "export.h"
+#include "tuscany/sca/core/ServiceProxy.h"
+#include "tuscany/sca/core/ServiceWrapper.h"
+#include "tuscany/sca/model/Component.h"
+#include "tuscany/sca/model/Reference.h"
+#include "tuscany/sca/model/Service.h"
+#include "tuscany/sca/model/WSDLOperation.h"
+#include "model/RESTReferenceBinding.h"
+
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ /**
+ * Holds a proxy for a given component and reference.
+ * The proxy which is held inside a ServiceProxy will be specific to the programming
+ * interface expected by the client. In this particular case the client is an Axis2
+ * Web service skeleton.
+ */
+ class RESTServiceProxy : 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.
+ * @param target The wrapper of the service which is wired to this reference.
+ */
+ RESTServiceProxy(tuscany::sca::model::Reference* reference);
+
+ /**
+ * Create a new service proxy for a service. The proxy will contain a pointer to
+ * the target ServiceWrapper.
+ * @param reference The service on the target component.
+ * @param target The wrapper of the target service.
+ */
+ RESTServiceProxy(tuscany::sca::model::Service* service);
+
+ /**
+ * Destructor.
+ */
+ virtual ~RESTServiceProxy();
+
+ /**
+ * Invoke the specified operation
+ */
+ SCA_REST_SERVICE_API commonj::sdo::DataObjectPtr invoke(
+ const tuscany::sca::model::WSDLOperation& wsdlOperation,
+ commonj::sdo::DataObjectPtr inputDataObject);
+
+ private:
+
+ void setOutputData(Operation& operation,
+ commonj::sdo::DataObjectPtr outputDataObject, commonj::sdo::DataFactoryPtr dataFactoryPtr);
+
+ /**
+ * The target service wrapper
+ */
+ ServiceWrapper* serviceWrapper;
+
+ };
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_extension_rest_restserviceproxy_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/export.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/export.h
new file mode 100644
index 0000000000..802218a2fe
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/export.h
@@ -0,0 +1,38 @@
+/*
+ * 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_rest_service_export_h
+#define tuscany_sca_rest_service_export_h
+
+#if defined(WIN32) || defined (_WINDOWS)
+#pragma warning(disable: 4786)
+
+#ifdef TUSCANY_SCA_REST_SERVICE_EXPORTS
+#define SCA_REST_SERVICE_API __declspec(dllexport)
+#else
+#define SCA_REST_SERVICE_API __declspec(dllimport)
+#endif
+
+#else
+#define SCA_REST_SERVICE_API
+#endif
+
+#endif // tuscany_sca_rest_service_export_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.cpp b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.cpp
new file mode 100644
index 0000000000..1b4b2d3403
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.cpp
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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/rest/model/RESTReferenceBinding.h"
+#include "tuscany/sca/core/ServiceProxy.h"
+#include "tuscany/sca/rest/RESTServiceProxy.h"
+
+using namespace std;
+using namespace tuscany::sca::model;
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+
+ // Constructor
+ RESTReferenceBinding::RESTReferenceBinding(Reference* reference, const string& uri)
+ : ReferenceBinding(reference, uri)
+ {
+ logentry();
+ }
+
+ // Destructor
+ RESTReferenceBinding::~RESTReferenceBinding()
+ {
+ logentry();
+ }
+
+ void RESTReferenceBinding::configure(ServiceBinding *binding)
+ {
+ logentry();
+
+ targetServiceBinding = binding;
+
+ serviceProxy = new RESTServiceProxy(getReference());
+ }
+
+ ServiceProxy* RESTReferenceBinding::getServiceProxy()
+ {
+ logentry();
+
+ return serviceProxy;
+ }
+
+ } // End namespace rest
+ } // End namespace sca
+} // End namespace tuscany
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.h b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.h
new file mode 100644
index 0000000000..d19f3926a1
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/service/httpd/src/tuscany/sca/rest/model/RESTReferenceBinding.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed 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_extension_rest_model_restreferencebinding_h
+#define tuscany_sca_extension_rest_model_restreferencebinding_h
+
+#include <string>
+
+#include "tuscany/sca/model/ReferenceBinding.h"
+
+namespace tuscany
+{
+ namespace sca
+ {
+ namespace rest
+ {
+ /**
+ * Information about a web service binding for service or a reference.
+ */
+ class RESTReferenceBinding : public tuscany::sca::model::ReferenceBinding
+ {
+ public:
+
+ /**
+ * Constructor.
+ * @param uri The uri of the binding.
+ */
+ RESTReferenceBinding(tuscany::sca::model::Reference* reference, const std::string& uri);
+
+ /**
+ * Destructor.
+ */
+ virtual ~RESTReferenceBinding();
+
+ /**
+ * Returns the type of binding.
+ */
+ virtual std::string getType() { return "http://www.osoa.org/xmlns/sca/1.0#RESTBinding"; };
+
+ /**
+ * Configure this binding from a service binding.
+ */
+ virtual void configure(tuscany::sca::model::ServiceBinding* serviceBinding);
+
+ /**
+ * Create a proxy representing the reference to the
+ * client component.
+ */
+ virtual ServiceProxy* getServiceProxy();
+
+ /**
+ * 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 rest
+ } // End namespace sca
+} // End namespace tuscany
+
+#endif // tuscany_sca_extension_rest_model_restreferencebinding_h
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-binding-rest.xsd b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-binding-rest.xsd
new file mode 100644
index 0000000000..a2fd41121c
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-binding-rest.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+ Licensed 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.
+ -->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:sca="http://www.osoa.org/xmlns/sca/1.0"
+ elementFormDefault="qualified">
+
+ <element name="binding.rest" type="sca:RESTBinding" substitutionGroup="sca:binding"/>
+ <complexType name="RESTBinding">
+ <complexContent>
+ <extension base="sca:Binding">
+ <sequence>
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
+ </sequence>
+ <anyAttribute namespace="##any" processContents="lax" />
+ </extension>
+ </complexContent>
+ </complexType>
+
+</schema>
diff --git a/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-interface-rest.xsd b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-interface-rest.xsd
new file mode 100644
index 0000000000..3f1aca6ecd
--- /dev/null
+++ b/tags/native-sca-1.0.incubating-M3-RC1/runtime/extensions/rest/xsd/sca-interface-rest.xsd
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:sca="http://www.osoa.org/xmlns/sca/1.0"
+ elementFormDefault="qualified">
+
+ <element name="interface.rest" type="sca:RESTInterface" substitutionGroup="sca:interface"/>
+ <complexType name="RESTInterface">
+ <complexContent>
+ <extension base="sca:Interface">
+ <sequence>
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
+ </sequence>
+ <anyAttribute namespace="##any" processContents="lax" />
+ </extension>
+ </complexContent>
+ </complexType>
+
+</schema>