summaryrefslogtreecommitdiff
path: root/binaryurp
diff options
context:
space:
mode:
Diffstat (limited to 'binaryurp')
-rw-r--r--binaryurp/prj/build.lst3
-rw-r--r--binaryurp/prj/d.lst4
-rw-r--r--binaryurp/qa/makefile.mk77
-rw-r--r--binaryurp/qa/test-cache.cxx84
-rw-r--r--binaryurp/qa/test-unmarshal.cxx112
-rw-r--r--binaryurp/qa/version.map34
-rw-r--r--binaryurp/source/binaryany.cxx98
-rw-r--r--binaryurp/source/binaryany.hxx73
-rw-r--r--binaryurp/source/binaryurp.component34
-rw-r--r--binaryurp/source/bridge.cxx978
-rw-r--r--binaryurp/source/bridge.hxx287
-rw-r--r--binaryurp/source/bridgefactory.cxx232
-rw-r--r--binaryurp/source/bridgefactory.hxx144
-rw-r--r--binaryurp/source/cache.hxx134
-rw-r--r--binaryurp/source/currentcontext.cxx80
-rw-r--r--binaryurp/source/currentcontext.hxx49
-rw-r--r--binaryurp/source/incomingreply.hxx58
-rw-r--r--binaryurp/source/incomingrequest.cxx300
-rw-r--r--binaryurp/source/incomingrequest.hxx86
-rw-r--r--binaryurp/source/lessoperators.cxx71
-rw-r--r--binaryurp/source/lessoperators.hxx50
-rw-r--r--binaryurp/source/makefile.mk69
-rw-r--r--binaryurp/source/marshal.cxx314
-rw-r--r--binaryurp/source/marshal.hxx95
-rw-r--r--binaryurp/source/outgoingrequest.hxx55
-rw-r--r--binaryurp/source/outgoingrequests.cxx80
-rw-r--r--binaryurp/source/outgoingrequests.hxx65
-rw-r--r--binaryurp/source/proxy.cxx260
-rw-r--r--binaryurp/source/proxy.hxx92
-rw-r--r--binaryurp/source/reader.cxx553
-rw-r--r--binaryurp/source/reader.hxx89
-rw-r--r--binaryurp/source/readerstate.hxx52
-rw-r--r--binaryurp/source/specialfunctionids.hxx49
-rw-r--r--binaryurp/source/unmarshal.cxx563
-rw-r--r--binaryurp/source/unmarshal.hxx106
-rw-r--r--binaryurp/source/writer.cxx476
-rw-r--r--binaryurp/source/writer.hxx185
-rw-r--r--binaryurp/source/writerstate.hxx55
38 files changed, 6146 insertions, 0 deletions
diff --git a/binaryurp/prj/build.lst b/binaryurp/prj/build.lst
new file mode 100644
index 000000000000..230b323f0a35
--- /dev/null
+++ b/binaryurp/prj/build.lst
@@ -0,0 +1,3 @@
+bu binaryurp : BOOST:boost LIBXSLT:libxslt cppu cppuhelper offuh sal salhelper stlport NULL
+bu binaryurp\source nmake - all bu_source NULL
+bu binaryurp\qa nmake - all bu_qa bu_source NULL
diff --git a/binaryurp/prj/d.lst b/binaryurp/prj/d.lst
new file mode 100644
index 000000000000..48ebd3be806f
--- /dev/null
+++ b/binaryurp/prj/d.lst
@@ -0,0 +1,4 @@
+..\%__SRC%\bin\binaryurp.uno.dll %_DEST%\bin%_EXT%\binaryurp.uno.dll
+..\%__SRC%\lib\binaryurp.uno.dylib %_DEST%\lib%_EXT%\binaryurp.uno.dylib
+..\%__SRC%\lib\binaryurp.uno.so %_DEST%\lib%_EXT%\binaryurp.uno.so
+..\%__SRC%\misc\binaryurp.component %_DEST%\xml%_EXT%\binaryurp.component
diff --git a/binaryurp/qa/makefile.mk b/binaryurp/qa/makefile.mk
new file mode 100644
index 000000000000..14b80c86cfaf
--- /dev/null
+++ b/binaryurp/qa/makefile.mk
@@ -0,0 +1,77 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#***********************************************************************/
+
+PRJ = ..
+PRJNAME = binaryurp
+TARGET = qa
+
+ENABLE_EXCEPTIONS = TRUE
+
+.INCLUDE: settings.mk
+
+CFLAGSCXX += $(CPPUNIT_CFLAGS)
+
+DLLPRE =
+
+SLOFILES = $(SLO)/test-cache.obj $(SLO)/test-unmarshal.obj
+
+SHL1IMPLIB = i$(SHL1TARGET)
+SHL1OBJS = $(SLO)/test-cache.obj
+SHL1RPATH = NONE
+SHL1STDLIBS = $(CPPUNITLIB) $(SALLIB)
+SHL1TARGET = test-cache
+SHL1VERSIONMAP = version.map
+DEF1NAME = $(SHL1TARGET)
+
+SHL2IMPLIB = i$(SHL2TARGET)
+SHL2OBJS = \
+ $(SLO)/test-unmarshal.obj \
+ $(SLO)/binaryany.obj \
+ $(SLO)/bridge.obj \
+ $(SLO)/bridgefactory.obj \
+ $(SLO)/currentcontext.obj \
+ $(SLO)/incomingrequest.obj \
+ $(SLO)/lessoperators.obj \
+ $(SLO)/marshal.obj \
+ $(SLO)/outgoingrequests.obj \
+ $(SLO)/proxy.obj \
+ $(SLO)/reader.obj \
+ $(SLO)/unmarshal.obj \
+ $(SLO)/writer.obj
+SHL2RPATH = NONE
+SHL2STDLIBS = \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(CPPUNITLIB) \
+ $(SALHELPERLIB) \
+ $(SALLIB)
+SHL2TARGET = test-unmarshal
+SHL2VERSIONMAP = version.map
+DEF2NAME = $(SHL2TARGET)
+
+.INCLUDE: target.mk
+.INCLUDE: _cppunit.mk
diff --git a/binaryurp/qa/test-cache.cxx b/binaryurp/qa/test-cache.cxx
new file mode 100644
index 000000000000..f9a3946c0df9
--- /dev/null
+++ b/binaryurp/qa/test-cache.cxx
@@ -0,0 +1,84 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+
+#include "../source/cache.hxx"
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testNothingLostFromLruList);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testNothingLostFromLruList();
+};
+
+// cf. jurt/test/com/sun/star/lib/uno/protocols/urp/Cache_Test.java:
+void Test::testNothingLostFromLruList() {
+ int a[8];
+ for (int i = 0; i != sizeof a / sizeof a[0]; ++i) {
+ for (int j = 0; j != i; ++j) {
+ a[j] = 0;
+ }
+ for (;;) {
+ binaryurp::Cache< int > c(4);
+ for (int k = 0; k != i; ++k) {
+ bool f;
+ c.add(a[k], &f);
+ }
+ bool f;
+ CPPUNIT_ASSERT_EQUAL(
+ 6,
+ c.add(-1, &f) + c.add(-2, &f) + c.add(-3, &f) + c.add(-4, &f));
+ int j = i - 1;
+ while (j >= 0 && a[j] == 3) {
+ --j;
+ }
+ if (j < 0) {
+ break;
+ }
+ ++a[j];
+ for (int k = j + 1; k != i; ++k) {
+ a[k] = 0;
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/binaryurp/qa/test-unmarshal.cxx b/binaryurp/qa/test-unmarshal.cxx
new file mode 100644
index 000000000000..3d3c1795a724
--- /dev/null
+++ b/binaryurp/qa/test-unmarshal.cxx
@@ -0,0 +1,112 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include "com/sun/star/io/IOException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "cppu/unotype.hxx"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.h"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+
+#include "../source/bridge.hxx"
+#include "../source/cache.hxx"
+#include "../source/readerstate.hxx"
+#include "../source/unmarshal.hxx"
+
+namespace {
+
+namespace css = com::sun::star;
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testTypeOfBooleanSequence);
+ CPPUNIT_TEST(testTypeOfVoidSequence);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testTypeOfBooleanSequence();
+
+ void testTypeOfVoidSequence();
+};
+
+void Test::testTypeOfBooleanSequence() {
+ binaryurp::ReaderState state;
+ css::uno::Sequence< sal_Int8 > buf(13);
+ buf[0] = static_cast< sal_Int8 >(20 | 0x80); // sequence type | cache flag
+ buf[1] = static_cast< sal_Int8 >(binaryurp::cache::ignore >> 8);
+ buf[2] = static_cast< sal_Int8 >(binaryurp::cache::ignore & 0xFF);
+ buf[3] = RTL_CONSTASCII_LENGTH("[]boolean");
+ buf[4] = '[';
+ buf[5] = ']';
+ buf[6] = 'b';
+ buf[7] = 'o';
+ buf[8] = 'o';
+ buf[9] = 'l';
+ buf[10] = 'e';
+ buf[11] = 'a';
+ buf[12] = 'n';
+ binaryurp::Unmarshal m(rtl::Reference< binaryurp::Bridge >(), state, buf);
+ css::uno::TypeDescription t(m.readType());
+ CPPUNIT_ASSERT(
+ t.equals(
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Sequence< bool > >::get())));
+ m.done();
+}
+
+void Test::testTypeOfVoidSequence() {
+ binaryurp::ReaderState state;
+ css::uno::Sequence< sal_Int8 > buf(10);
+ buf[0] = static_cast< sal_Int8 >(20 | 0x80); // sequence type | cache flag
+ buf[1] = static_cast< sal_Int8 >(binaryurp::cache::ignore >> 8);
+ buf[2] = static_cast< sal_Int8 >(binaryurp::cache::ignore & 0xFF);
+ buf[3] = RTL_CONSTASCII_LENGTH("[]void");
+ buf[4] = '[';
+ buf[5] = ']';
+ buf[6] = 'v';
+ buf[7] = 'o';
+ buf[8] = 'i';
+ buf[9] = 'd';
+ binaryurp::Unmarshal m(rtl::Reference< binaryurp::Bridge >(), state, buf);
+ try {
+ m.readType();
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::io::IOException &) {}
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/binaryurp/qa/version.map b/binaryurp/qa/version.map
new file mode 100644
index 000000000000..ef2ab497cb5e
--- /dev/null
+++ b/binaryurp/qa/version.map
@@ -0,0 +1,34 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#***********************************************************************/
+
+UDK_3_0_0 {
+ global:
+ cppunitTestPlugIn;
+
+ local:
+ *;
+};
diff --git a/binaryurp/source/binaryany.cxx b/binaryurp/source/binaryany.cxx
new file mode 100644
index 000000000000..c5b8b1a3cb3d
--- /dev/null
+++ b/binaryurp/source/binaryany.cxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include "osl/diagnose.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.hxx"
+#include "uno/any2.h"
+
+#include "binaryany.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+BinaryAny::BinaryAny() throw () {
+ uno_any_construct(&data_, 0, 0, 0);
+}
+
+BinaryAny::BinaryAny(css::uno::TypeDescription const & type, void * value)
+ throw ()
+{
+ OSL_ASSERT(type.is());
+ uno_any_construct(&data_, value, type.get(), 0);
+}
+
+BinaryAny::BinaryAny(uno_Any const & raw) throw () {
+ OSL_ASSERT(raw.pType != 0);
+ data_.pType = raw.pType;
+ typelib_typedescriptionreference_acquire(data_.pType);
+ data_.pData = raw.pData == &raw.pReserved ? &data_.pReserved : raw.pData;
+ data_.pReserved = raw.pReserved;
+}
+
+BinaryAny::BinaryAny(BinaryAny const & other) throw () {
+ uno_type_any_construct(&data_, other.data_.pData, other.data_.pType, 0);
+}
+
+BinaryAny::~BinaryAny() throw () {
+ uno_any_destruct(&data_, 0);
+}
+
+BinaryAny & BinaryAny::operator =(BinaryAny const & other) throw () {
+ if (&other != this) {
+ uno_type_any_assign(&data_, other.data_.pData, other.data_.pType, 0, 0);
+ }
+ return *this;
+}
+
+uno_Any * BinaryAny::get() throw () {
+ return &data_;
+}
+
+css::uno::TypeDescription BinaryAny::getType() const throw () {
+ return css::uno::TypeDescription(data_.pType);
+}
+
+void * BinaryAny::getValue(css::uno::TypeDescription const & type) const
+ throw ()
+{
+ OSL_ASSERT(
+ type.is() &&
+ (type.get()->eTypeClass == typelib_TypeClass_ANY ||
+ type.equals(css::uno::TypeDescription(data_.pType))));
+ return type.get()->eTypeClass == typelib_TypeClass_ANY
+ ? &data_ : data_.pData;
+}
+
+}
diff --git a/binaryurp/source/binaryany.hxx b/binaryurp/source/binaryany.hxx
new file mode 100644
index 000000000000..4dd6112b5c57
--- /dev/null
+++ b/binaryurp/source/binaryany.hxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_BINARYANY_HXX
+#define INCLUDED_BINARYURP_SOURCE_BINARYANY_HXX
+
+#include "sal/config.h"
+
+#include "uno/any2.h"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class TypeDescription;
+} } } }
+
+namespace binaryurp {
+
+class BinaryAny {
+public:
+ BinaryAny() throw ();
+
+ BinaryAny(com::sun::star::uno::TypeDescription const & type, void * value)
+ throw ();
+
+ explicit BinaryAny(uno_Any const & raw) throw ();
+ // takes over raw.pData (but copies raw.pType); raw must not be passed
+ // to uno_any_destruct
+
+ BinaryAny(BinaryAny const & other) throw ();
+
+ ~BinaryAny() throw ();
+
+ BinaryAny & operator =(BinaryAny const & other) throw ();
+
+ uno_Any * get() throw ();
+
+ com::sun::star::uno::TypeDescription getType() const throw ();
+
+ void * getValue(com::sun::star::uno::TypeDescription const & type) const
+ throw ();
+
+private:
+ mutable uno_Any data_;
+ // mutable so that getValue() can return a non-const void *, as in turn
+ // required at various places in binary UNO
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/binaryurp.component b/binaryurp/source/binaryurp.component
new file mode 100644
index 000000000000..19554bcc088b
--- /dev/null
+++ b/binaryurp/source/binaryurp.component
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--**********************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+**********************************************************************-->
+
+<component loader="com.sun.star.loader.SharedLibrary"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.bridge.BridgeFactory">
+ <service name="com.sun.star.bridge.BridgeFactory"/>
+ </implementation>
+</component>
diff --git a/binaryurp/source/bridge.cxx b/binaryurp/source/bridge.cxx
new file mode 100644
index 000000000000..dcf77662c56d
--- /dev/null
+++ b/binaryurp/source/bridge.cxx
@@ -0,0 +1,978 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
+#include "com/sun/star/bridge/XBridge.hpp"
+#include "com/sun/star/bridge/XInstanceProvider.hpp"
+#include "com/sun/star/bridge/XProtocolProperties.hpp"
+#include "com/sun/star/connection/XConnection.hpp"
+#include "com/sun/star/io/IOException.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/lang/EventObject.hpp"
+#include "com/sun/star/lang/XEventListener.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppuhelper/exc_hlp.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "osl/thread.hxx"
+#include "rtl/byteseq.hxx"
+#include "rtl/random.h"
+#include "rtl/ref.hxx"
+#include "rtl/textenc.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/dispatcher.hxx"
+#include "uno/environment.hxx"
+#include "uno/lbnames.h"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "bridgefactory.hxx"
+#include "incomingreply.hxx"
+#include "lessoperators.hxx"
+#include "outgoingrequest.hxx"
+#include "outgoingrequests.hxx"
+#include "proxy.hxx"
+#include "reader.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+sal_Int32 random() {
+ sal_Int32 n;
+ rtlRandomPool pool = rtl_random_createPool();
+ rtl_random_getBytes(pool, &n, sizeof n);
+ rtl_random_destroyPool(pool);
+ return n;
+}
+
+extern "C" void SAL_CALL freeProxyCallback(uno_ExtEnvironment *, void * pProxy)
+{
+ OSL_ASSERT(pProxy != 0);
+ static_cast< Proxy * >(pProxy)->do_free();
+}
+
+void joinThread(osl::Thread * thread) {
+ OSL_ASSERT(thread != 0);
+ if (thread->getIdentifier() != osl::Thread::getCurrentIdentifier()) {
+ thread->join();
+ }
+}
+
+class AttachThread: private boost::noncopyable {
+public:
+ explicit AttachThread(uno_ThreadPool threadPool);
+
+ ~AttachThread();
+
+ rtl::ByteSequence getTid() throw ();
+
+private:
+ uno_ThreadPool threadPool_;
+ rtl::ByteSequence tid_;
+};
+
+AttachThread::AttachThread(uno_ThreadPool threadPool): threadPool_(threadPool) {
+ sal_Sequence * s = 0;
+ uno_getIdOfCurrentThread(&s);
+ tid_ = rtl::ByteSequence(s, rtl::BYTESEQ_NOACQUIRE);
+ uno_threadpool_attach(threadPool_);
+}
+
+AttachThread::~AttachThread() {
+ uno_threadpool_detach(threadPool_);
+ uno_releaseIdFromCurrentThread();
+}
+
+rtl::ByteSequence AttachThread::getTid() throw () {
+ return tid_;
+}
+
+class PopOutgoingRequest: private boost::noncopyable {
+public:
+ PopOutgoingRequest(
+ OutgoingRequests & requests, rtl::ByteSequence const & tid,
+ OutgoingRequest const & request);
+
+ ~PopOutgoingRequest();
+
+ void clear();
+
+private:
+ OutgoingRequests & requests_;
+ rtl::ByteSequence tid_;
+ bool cleared_;
+};
+
+PopOutgoingRequest::PopOutgoingRequest(
+ OutgoingRequests & requests, rtl::ByteSequence const & tid,
+ OutgoingRequest const & request):
+ requests_(requests), tid_(tid), cleared_(false)
+{
+ requests_.push(tid_, request);
+}
+
+PopOutgoingRequest::~PopOutgoingRequest() {
+ if (!cleared_) {
+ requests_.pop(tid_);
+ }
+}
+
+void PopOutgoingRequest::clear() {
+ cleared_ = true;
+}
+
+}
+
+struct Bridge::SubStub {
+ com::sun::star::uno::UnoInterfaceReference object;
+
+ sal_uInt32 references;
+};
+
+Bridge::Bridge(
+ rtl::Reference< BridgeFactory > const & factory, rtl::OUString const & name,
+ css::uno::Reference< css::connection::XConnection > const & connection,
+ css::uno::Reference< css::bridge::XInstanceProvider > const & provider):
+ factory_(factory), name_(name), connection_(connection),
+ provider_(provider),
+ binaryUno_(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
+ cppToBinaryMapping_(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)),
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
+ binaryToCppMapping_(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)),
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME))),
+ protPropTid_(
+ reinterpret_cast< sal_Int8 const * >(".UrpProtocolPropertiesTid"),
+ RTL_CONSTASCII_LENGTH(".UrpProtocolPropertiesTid")),
+ protPropOid_(RTL_CONSTASCII_USTRINGPARAM("UrpProtocolProperties")),
+ protPropType_(
+ cppu::UnoType<
+ css::uno::Reference< css::bridge::XProtocolProperties > >::get()),
+ protPropRequest_(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.bridge.XProtocolProperties::requestChange"))),
+ protPropCommit_(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.bridge.XProtocolProperties::commitChange"))),
+ threadPool_(0), currentContextMode_(false), proxies_(0), calls_(0),
+ normalCall_(false), activeCalls_(0), terminated_(false),
+ mode_(MODE_REQUESTED)
+{
+ OSL_ASSERT(factory.is() && connection.is());
+ if (!binaryUno_.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URP: no binary UNO environment")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (!(cppToBinaryMapping_.is() && binaryToCppMapping_.is())) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URP: no C++ UNO mapping")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ passive_.set();
+}
+
+void Bridge::start() {
+ OSL_ASSERT(threadPool_ == 0 && !writer_.is() && !reader_.is());
+ threadPool_ = uno_threadpool_create();
+ OSL_ASSERT(threadPool_ != 0);
+ writer_.set(new Writer(this));
+ writer_->create();
+ reader_.set(new Reader(this));
+ reader_->create();
+}
+
+void Bridge::terminate() {
+ rtl::Reference< Reader > r;
+ rtl::Reference< Writer > w;
+ Listeners ls;
+ {
+ osl::MutexGuard g(mutex_);
+ if (terminated_) {
+ return;
+ }
+ std::swap(reader_, r);
+ std::swap(writer_, w);
+ ls.swap(listeners_);
+ terminated_ = true;
+ }
+ try {
+ connection_->close();
+ } catch (css::io::IOException & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught IO exception '%s'",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ OSL_ASSERT(w.is());
+ w->stop();
+ joinThread(r.get());
+ joinThread(w.get());
+ OSL_ASSERT(threadPool_ != 0);
+ uno_threadpool_dispose(threadPool_);
+ Stubs s;
+ {
+ osl::MutexGuard g(mutex_);
+ s.swap(stubs_);
+ }
+ for (Stubs::iterator i(s.begin()); i != s.end(); ++i) {
+ for (Stub::iterator j(i->second.begin()); j != i->second.end(); ++j) {
+ binaryUno_.get()->pExtEnv->revokeInterface(
+ binaryUno_.get()->pExtEnv, j->second.object.get());
+ }
+ }
+ factory_->removeBridge(this);
+ for (Listeners::iterator i(ls.begin()); i != ls.end(); ++i) {
+ try {
+ (*i)->disposing(
+ css::lang::EventObject(
+ static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::uno::RuntimeException & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught runtime exception '%s'",
+ rtl::OUStringToOString(
+ e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+}
+
+css::uno::Reference< css::connection::XConnection > Bridge::getConnection()
+ const
+{
+ return connection_;
+}
+
+css::uno::Reference< css::bridge::XInstanceProvider > Bridge::getProvider()
+ const
+{
+ return provider_;
+}
+
+css::uno::Mapping & Bridge::getCppToBinaryMapping() {
+ return cppToBinaryMapping_;
+}
+
+BinaryAny Bridge::mapCppToBinaryAny(css::uno::Any const & cppAny) {
+ css::uno::Any in(cppAny);
+ BinaryAny out;
+ out.~BinaryAny();
+ uno_copyAndConvertData(
+ out.get(), &in,
+ css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
+ cppToBinaryMapping_.get());
+ return out;
+}
+
+uno_ThreadPool Bridge::getThreadPool() const {
+ OSL_ASSERT(threadPool_ != 0);
+ return threadPool_;
+}
+
+rtl::Reference< Writer > Bridge::getWriter() {
+ osl::MutexGuard g(mutex_);
+ if (terminated_) {
+ throw css::lang::DisposedException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "Binary URP bridge already disposed")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ OSL_ASSERT(writer_.is());
+ return writer_;
+}
+
+css::uno::UnoInterfaceReference Bridge::registerIncomingInterface(
+ rtl::OUString const & oid, css::uno::TypeDescription const & type)
+{
+ OSL_ASSERT(type.is());
+ if (oid.getLength() == 0) {
+ return css::uno::UnoInterfaceReference();
+ }
+ css::uno::UnoInterfaceReference obj(findStub(oid, type));
+ if (!obj.is()) {
+ binaryUno_.get()->pExtEnv->getRegisteredInterface(
+ binaryUno_.get()->pExtEnv,
+ reinterpret_cast< void ** >(&obj.m_pUnoI), oid.pData,
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(type.get()));
+ if (obj.is()) {
+ makeReleaseCall(oid, type);
+ } else {
+ obj.set(new Proxy(this, oid, type), SAL_NO_ACQUIRE);
+ {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(
+ proxies_ < std::numeric_limits< std::size_t >::max());
+ ++proxies_;
+ }
+ binaryUno_.get()->pExtEnv->registerProxyInterface(
+ binaryUno_.get()->pExtEnv,
+ reinterpret_cast< void ** >(&obj.m_pUnoI), &freeProxyCallback,
+ oid.pData,
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ type.get()));
+ }
+ }
+ return obj;
+}
+
+rtl::OUString Bridge::registerOutgoingInterface(
+ css::uno::UnoInterfaceReference const & object,
+ css::uno::TypeDescription const & type)
+{
+ OSL_ASSERT(type.is());
+ if (!object.is()) {
+ return rtl::OUString();
+ }
+ rtl::OUString oid;
+ if (!Proxy::isProxy(this, object, &oid)) {
+ binaryUno_.get()->pExtEnv->getObjectIdentifier(
+ binaryUno_.get()->pExtEnv, &oid.pData, object.get());
+ osl::MutexGuard g(mutex_);
+ Stubs::iterator i(stubs_.find(oid));
+ Stub newStub;
+ Stub * stub = i == stubs_.end() ? &newStub : &i->second;
+ Stub::iterator j(stub->find(type));
+ //TODO: Release sub-stub if it is not successfully sent to remote side
+ // (otherwise, stub will leak until terminate()):
+ if (j == stub->end()) {
+ j = stub->insert(Stub::value_type(type, SubStub())).first;
+ if (stub == &newStub) {
+ i = stubs_.insert(Stubs::value_type(oid, Stub())).first;
+ std::swap(i->second, newStub);
+ j = i->second.find(type);
+ OSL_ASSERT(j != i->second.end());
+ }
+ j->second.object = object;
+ j->second.references = 1;
+ binaryUno_.get()->pExtEnv->registerInterface(
+ binaryUno_.get()->pExtEnv,
+ reinterpret_cast< void ** >(&j->second.object.m_pUnoI),
+ oid.pData,
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ type.get()));
+ } else {
+ OSL_ASSERT(stub != &newStub);
+ if (j->second.references == SAL_MAX_UINT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: stub reference count overflow")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ ++j->second.references;
+ }
+ }
+ return oid;
+}
+
+css::uno::UnoInterfaceReference Bridge::findStub(
+ rtl::OUString const & oid, css::uno::TypeDescription const & type)
+{
+ OSL_ASSERT(oid.getLength() != 0 && type.is());
+ osl::MutexGuard g(mutex_);
+ Stubs::iterator i(stubs_.find(oid));
+ if (i != stubs_.end()) {
+ Stub::iterator j(i->second.find(type));
+ if (j != i->second.end()) {
+ return j->second.object;
+ }
+ for (j = i->second.begin(); j != i->second.end(); ++j) {
+ if (typelib_typedescription_isAssignableFrom(
+ type.get(), j->first.get()))
+ {
+ return j->second.object;
+ }
+ }
+ }
+ return css::uno::UnoInterfaceReference();
+}
+
+void Bridge::releaseStub(
+ rtl::OUString const & oid, css::uno::TypeDescription const & type)
+{
+ OSL_ASSERT(oid.getLength() != 0 && type.is());
+ css::uno::UnoInterfaceReference obj;
+ bool unused;
+ {
+ osl::MutexGuard g(mutex_);
+ Stubs::iterator i(stubs_.find(oid));
+ if (i == stubs_.end()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ Stub::iterator j(i->second.find(type));
+ if (j == i->second.end()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OSL_ASSERT(j->second.references > 0);
+ --j->second.references;
+ if (j->second.references == 0) {
+ obj = j->second.object;
+ i->second.erase(j);
+ if (i->second.empty()) {
+ stubs_.erase(i);
+ }
+ }
+ unused = becameUnused();
+ }
+ if (obj.is()) {
+ binaryUno_.get()->pExtEnv->revokeInterface(
+ binaryUno_.get()->pExtEnv, obj.get());
+ }
+ terminateWhenUnused(unused);
+}
+
+void Bridge::resurrectProxy(Proxy & proxy) {
+ uno_Interface * p = &proxy;
+ binaryUno_.get()->pExtEnv->registerProxyInterface(
+ binaryUno_.get()->pExtEnv,
+ reinterpret_cast< void ** >(&p), &freeProxyCallback,
+ proxy.getOid().pData,
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ proxy.getType().get()));
+ OSL_ASSERT(p == &proxy);
+}
+
+void Bridge::revokeProxy(Proxy & proxy) {
+ binaryUno_.get()->pExtEnv->revokeInterface(
+ binaryUno_.get()->pExtEnv, &proxy);
+}
+
+void Bridge::freeProxy(Proxy & proxy) {
+ try {
+ makeReleaseCall(proxy.getOid(), proxy.getType());
+ } catch (css::uno::RuntimeException & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught runtime exception '%s'",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ } catch (std::exception & e) {
+ OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
+ }
+ bool unused;
+ {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(proxies_ > 0);
+ --proxies_;
+ unused = becameUnused();
+ }
+ terminateWhenUnused(unused);
+}
+
+void Bridge::incrementCalls(bool normalCall) throw () {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(calls_ < std::numeric_limits< std::size_t >::max());
+ ++calls_;
+ normalCall_ |= normalCall;
+}
+
+void Bridge::decrementCalls() {
+ bool unused;
+ {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(calls_ > 0);
+ --calls_;
+ unused = becameUnused();
+ }
+ terminateWhenUnused(unused);
+}
+
+void Bridge::incrementActiveCalls() throw () {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(
+ activeCalls_ <= calls_ &&
+ activeCalls_ < std::numeric_limits< std::size_t >::max());
+ ++activeCalls_;
+ passive_.reset();
+}
+
+void Bridge::decrementActiveCalls() throw () {
+ osl::MutexGuard g(mutex_);
+ OSL_ASSERT(activeCalls_ <= calls_ && activeCalls_ > 0);
+ --activeCalls_;
+ if (activeCalls_ == 0) {
+ passive_.set();
+ }
+}
+
+bool Bridge::makeCall(
+ rtl::OUString const & oid, css::uno::TypeDescription const & member,
+ bool setter, std::vector< BinaryAny > const & inArguments,
+ BinaryAny * returnValue, std::vector< BinaryAny > * outArguments)
+{
+ std::auto_ptr< IncomingReply > resp;
+ {
+ AttachThread att(threadPool_);
+ PopOutgoingRequest pop(
+ outgoingRequests_, att.getTid(),
+ OutgoingRequest(OutgoingRequest::KIND_NORMAL, member, setter));
+ sendRequest(
+ att.getTid(), oid, css::uno::TypeDescription(), member,
+ inArguments);
+ pop.clear();
+ incrementCalls(true);
+ incrementActiveCalls();
+ void * job;
+ uno_threadpool_enter(threadPool_, &job);
+ resp.reset(static_cast< IncomingReply * >(job));
+ decrementActiveCalls();
+ decrementCalls();
+ }
+ if (resp.get() == 0) {
+ throw css::lang::DisposedException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "Binary URP bridge disposed during call")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ *returnValue = resp->returnValue;
+ if (!resp->exception) {
+ *outArguments = resp->outArguments;
+ }
+ return resp->exception;
+}
+
+void Bridge::sendRequestChangeRequest() {
+ OSL_ASSERT(mode_ == MODE_REQUESTED);
+ random_ = random();
+ std::vector< BinaryAny > a;
+ a.push_back(
+ BinaryAny(
+ css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get()),
+ &random_));
+ sendProtPropRequest(OutgoingRequest::KIND_REQUEST_CHANGE, a);
+}
+
+void Bridge::handleRequestChangeReply(
+ bool exception, BinaryAny const & returnValue)
+{
+ throwException(exception, returnValue);
+ sal_Int32 n = *static_cast< sal_Int32 * >(
+ returnValue.getValue(
+ css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get())));
+ sal_Int32 exp = 0;
+ switch (mode_) {
+ case MODE_REQUESTED:
+ case MODE_REPLY_1:
+ exp = 1;
+ break;
+ case MODE_REPLY_MINUS1:
+ exp = -1;
+ mode_ = MODE_REQUESTED;
+ break;
+ case MODE_REPLY_0:
+ exp = 0;
+ mode_ = MODE_WAIT;
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ if (n != exp) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: requestChange reply with unexpected return value"
+ " received")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ decrementCalls();
+ switch (exp) {
+ case -1:
+ sendRequestChangeRequest();
+ break;
+ case 0:
+ break;
+ case 1:
+ sendCommitChangeRequest();
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+}
+
+void Bridge::handleCommitChangeReply(
+ bool exception, BinaryAny const & returnValue)
+{
+ bool ccMode = true;
+ try {
+ throwException(exception, returnValue);
+ } catch (css::bridge::InvalidProtocolChangeException &) {
+ ccMode = false;
+ }
+ if (ccMode) {
+ setCurrentContextMode();
+ }
+ OSL_ASSERT(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
+ mode_ = MODE_NORMAL;
+ getWriter()->unblock();
+ decrementCalls();
+}
+
+void Bridge::handleRequestChangeRequest(
+ rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
+{
+ OSL_ASSERT(inArguments.size() == 1);
+ switch (mode_) {
+ case MODE_REQUESTED:
+ {
+ sal_Int32 n2 = *static_cast< sal_Int32 * >(
+ inArguments[0].getValue(
+ css::uno::TypeDescription(
+ cppu::UnoType< sal_Int32 >::get())));
+ sal_Int32 ret;
+ if (n2 > random_) {
+ ret = 1;
+ mode_ = MODE_REPLY_0;
+ } else if (n2 == random_) {
+ ret = -1;
+ mode_ = MODE_REPLY_MINUS1;
+ } else {
+ ret = 0;
+ mode_ = MODE_REPLY_1;
+ }
+ getWriter()->sendDirectReply(
+ tid, protPropRequest_, false,
+ BinaryAny(
+ css::uno::TypeDescription(
+ cppu::UnoType< sal_Int32 >::get()),
+ &ret),
+ std::vector< BinaryAny >());
+ break;
+ }
+ case MODE_NORMAL:
+ {
+ mode_ = MODE_NORMAL_WAIT;
+ sal_Int32 ret = 1;
+ getWriter()->queueReply(
+ tid, protPropRequest_, false, false,
+ BinaryAny(
+ css::uno::TypeDescription(
+ cppu::UnoType< sal_Int32 >::get()),
+ &ret),
+ std::vector< BinaryAny >(), false);
+ break;
+ }
+ default:
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: unexpected requestChange request received")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+void Bridge::handleCommitChangeRequest(
+ rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
+{
+ bool ccMode = false;
+ bool exc = false;
+ BinaryAny ret;
+ OSL_ASSERT(inArguments.size() == 1);
+ css::uno::Sequence< css::bridge::ProtocolProperty > s;
+ OSL_VERIFY(mapBinaryToCppAny(inArguments[0]) >>= s);
+ for (sal_Int32 i = 0; i != s.getLength(); ++i) {
+ if (s[i].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("CurrentContext")))
+ {
+ ccMode = true;
+ } else {
+ ccMode = false;
+ exc = true;
+ ret = mapCppToBinaryAny(
+ css::uno::makeAny(
+ css::bridge::InvalidProtocolChangeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "InvalidProtocolChangeException")),
+ css::uno::Reference< css::uno::XInterface >(), s[i],
+ 1)));
+ break;
+ }
+ }
+ switch (mode_) {
+ case MODE_WAIT:
+ getWriter()->sendDirectReply(
+ tid, protPropCommit_, exc, ret, std::vector< BinaryAny >());
+ if (ccMode) {
+ setCurrentContextMode();
+ mode_ = MODE_NORMAL;
+ getWriter()->unblock();
+ } else {
+ mode_ = MODE_REQUESTED;
+ sendRequestChangeRequest();
+ }
+ break;
+ case MODE_NORMAL_WAIT:
+ getWriter()->queueReply(
+ tid, protPropCommit_, false, false, ret, std::vector< BinaryAny >(),
+ ccMode);
+ mode_ = MODE_NORMAL;
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: unexpected commitChange request received")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+OutgoingRequest Bridge::lastOutgoingRequest(rtl::ByteSequence const & tid) {
+ OutgoingRequest req(outgoingRequests_.top(tid));
+ outgoingRequests_.pop(tid);
+ return req;
+}
+
+bool Bridge::isProtocolPropertiesRequest(
+ rtl::OUString const & oid, css::uno::TypeDescription const & type) const
+{
+ return oid == protPropOid_ && type.equals(protPropType_);
+}
+
+void Bridge::setCurrentContextMode() {
+ osl::MutexGuard g(mutex_);
+ currentContextMode_ = true;
+}
+
+bool Bridge::isCurrentContextMode() {
+ osl::MutexGuard g(mutex_);
+ return currentContextMode_;
+}
+
+Bridge::~Bridge() {
+ if (threadPool_ != 0) {
+ uno_threadpool_destroy(threadPool_);
+ }
+}
+
+css::uno::Reference< css::uno::XInterface > Bridge::getInstance(
+ rtl::OUString const & sInstanceName) throw (css::uno::RuntimeException)
+{
+ if (sInstanceName.getLength() == 0) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "XBridge::getInstance sInstanceName must be non-empty")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (sal_Int32 i = 0; i != sInstanceName.getLength(); ++i) {
+ if (sInstanceName[i] > 0x7F) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "XBridge::getInstance sInstanceName contains non-ASCII"
+ " character")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ css::uno::TypeDescription ifc(
+ cppu::UnoType< css::uno::Reference< css::uno::XInterface > >::get());
+ typelib_TypeDescription * p = ifc.get();
+ std::vector< BinaryAny > inArgs;
+ inArgs.push_back(
+ BinaryAny(
+ css::uno::TypeDescription(cppu::UnoType< css::uno::Type >::get()),
+ &p));
+ BinaryAny ret;
+ std::vector< BinaryAny> outArgs;
+ bool exc = makeCall(
+ sInstanceName,
+ css::uno::TypeDescription(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.uno.XInterface::queryInterface"))),
+ false, inArgs, &ret, &outArgs);
+ throwException(exc, ret);
+ return css::uno::Reference< css::uno::XInterface >(
+ static_cast< css::uno::XInterface * >(
+ binaryToCppMapping_.mapInterface(
+ *static_cast< uno_Interface ** >(ret.getValue(ifc)),
+ ifc.get())),
+ css::uno::UNO_REF_NO_ACQUIRE);
+}
+
+rtl::OUString Bridge::getName() throw (css::uno::RuntimeException) {
+ return name_;
+}
+
+rtl::OUString Bridge::getDescription() throw (css::uno::RuntimeException) {
+ rtl::OUStringBuffer b(name_);
+ b.append(sal_Unicode(':'));
+ b.append(connection_->getDescription());
+ return b.makeStringAndClear();
+}
+
+void Bridge::dispose() throw (css::uno::RuntimeException) {
+ terminate();
+ // OOo expects dispose to not return while there are still remote calls in
+ // progress; an external protocol must ensure that dispose is not called
+ // from within an incoming or outgoing remote call, as passive_.wait() would
+ // otherwise deadlock:
+ passive_.wait();
+}
+
+void Bridge::addEventListener(
+ css::uno::Reference< css::lang::XEventListener > const & xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(xListener.is());
+ {
+ osl::MutexGuard g(mutex_);
+ if (!terminated_) {
+ listeners_.push_back(xListener);
+ return;
+ }
+ }
+ xListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+}
+
+void Bridge::removeEventListener(
+ css::uno::Reference< css::lang::XEventListener > const & aListener)
+ throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard g(mutex_);
+ Listeners::iterator i(
+ std::find(listeners_.begin(), listeners_.end(), aListener));
+ if (i != listeners_.end()) {
+ listeners_.erase(i);
+ }
+}
+
+void Bridge::sendCommitChangeRequest() {
+ OSL_ASSERT(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
+ css::uno::Sequence< css::bridge::ProtocolProperty > s(1);
+ s[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CurrentContext"));
+ std::vector< BinaryAny > a;
+ a.push_back(mapCppToBinaryAny(css::uno::makeAny(s)));
+ sendProtPropRequest(OutgoingRequest::KIND_COMMIT_CHANGE, a);
+}
+
+void Bridge::sendProtPropRequest(
+ OutgoingRequest::Kind kind, std::vector< BinaryAny > const & inArguments)
+{
+ OSL_ASSERT(
+ kind == OutgoingRequest::KIND_REQUEST_CHANGE ||
+ kind == OutgoingRequest::KIND_COMMIT_CHANGE);
+ incrementCalls(false);
+ css::uno::TypeDescription member(
+ kind == OutgoingRequest::KIND_REQUEST_CHANGE
+ ? protPropRequest_ : protPropCommit_);
+ PopOutgoingRequest pop(
+ outgoingRequests_, protPropTid_, OutgoingRequest(kind, member, false));
+ getWriter()->sendDirectRequest(
+ protPropTid_, protPropOid_, protPropType_, member, inArguments);
+ pop.clear();
+}
+
+void Bridge::makeReleaseCall(
+ rtl::OUString const & oid, css::uno::TypeDescription const & type)
+{
+ AttachThread att(threadPool_);
+ sendRequest(
+ att.getTid(), oid, type,
+ css::uno::TypeDescription(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.uno.XInterface::release"))),
+ std::vector< BinaryAny >());
+}
+
+void Bridge::sendRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ css::uno::TypeDescription const & type,
+ css::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments)
+{
+ getWriter()->queueRequest(tid, oid, type, member, inArguments);
+}
+
+void Bridge::throwException(bool exception, BinaryAny const & value) {
+ if (exception) {
+ cppu::throwException(mapBinaryToCppAny(value));
+ }
+}
+
+css::uno::Any Bridge::mapBinaryToCppAny(BinaryAny const & binaryAny) {
+ BinaryAny in(binaryAny);
+ css::uno::Any out;
+ out.~Any();
+ uno_copyAndConvertData(
+ &out, in.get(),
+ css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
+ binaryToCppMapping_.get());
+ return out;
+}
+
+bool Bridge::becameUnused() const {
+ return stubs_.empty() && proxies_ == 0 && calls_ == 0 && normalCall_;
+}
+
+void Bridge::terminateWhenUnused(bool unused) {
+ if (unused) {
+ // That the current thread considers the bridge unused implies that it
+ // is not within an incoming or outgoing remote call (so calling
+ // terminate cannot lead to deadlock):
+ terminate();
+ }
+}
+
+}
diff --git a/binaryurp/source/bridge.hxx b/binaryurp/source/bridge.hxx
new file mode 100644
index 000000000000..73e32aac0cac
--- /dev/null
+++ b/binaryurp/source/bridge.hxx
@@ -0,0 +1,287 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_BRIDGE_HXX
+#define INCLUDED_BINARYURP_SOURCE_BRIDGE_HXX
+
+#include "sal/config.h"
+
+#include <cstddef>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/bridge/XBridge.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "cppuhelper/implbase2.hxx"
+#include "osl/conditn.hxx"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "uno/environment.hxx"
+#include "uno/mapping.hxx"
+#include "uno/threadpool.h"
+
+#include "outgoingrequest.hxx"
+#include "outgoingrequests.hxx"
+#include "writer.hxx"
+
+namespace binaryurp {
+ class BinaryAny;
+ class BridgeFactory;
+ class Proxy;
+ class Reader;
+}
+namespace com { namespace sun { namespace star {
+ namespace bridge { class XInstanceProvider; }
+ namespace connection { class XConnection; }
+ namespace lang { class XEventListener; }
+ namespace uno {
+ class Any;
+ class TypeDescription;
+ class UnoInterfaceReference;
+ class XInterface;
+ }
+} } }
+namespace rtl { class ByteSequence; }
+
+namespace binaryurp {
+
+class Bridge:
+ public cppu::WeakImplHelper2<
+ com::sun::star::bridge::XBridge, com::sun::star::lang::XComponent >,
+ private boost::noncopyable
+{
+public:
+ Bridge(
+ rtl::Reference< BridgeFactory > const & factory,
+ rtl::OUString const & name,
+ com::sun::star::uno::Reference<
+ com::sun::star::connection::XConnection > const & connection,
+ com::sun::star::uno::Reference<
+ com::sun::star::bridge::XInstanceProvider > const & provider);
+
+ void start();
+
+ // Internally waits for all incoming and outgoing remote calls to terminate,
+ // so must not be called from within such a call:
+ void terminate();
+
+ com::sun::star::uno::Reference< com::sun::star::connection::XConnection >
+ getConnection() const;
+
+ com::sun::star::uno::Reference< com::sun::star::bridge::XInstanceProvider >
+ getProvider() const;
+
+ com::sun::star::uno::Mapping & getCppToBinaryMapping();
+
+ BinaryAny mapCppToBinaryAny(com::sun::star::uno::Any const & cppAny);
+
+ uno_ThreadPool getThreadPool() const;
+
+ rtl::Reference< Writer > getWriter();
+
+ com::sun::star::uno::UnoInterfaceReference registerIncomingInterface(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type);
+
+ rtl::OUString registerOutgoingInterface(
+ com::sun::star::uno::UnoInterfaceReference const & object,
+ com::sun::star::uno::TypeDescription const & type);
+
+ com::sun::star::uno::UnoInterfaceReference findStub(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type);
+
+ void releaseStub(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type);
+
+ void resurrectProxy(Proxy & proxy);
+
+ void revokeProxy(Proxy & proxy);
+
+ void freeProxy(Proxy & proxy);
+
+ void incrementCalls(bool normalCall) throw ();
+
+ void decrementCalls();
+
+ void incrementActiveCalls() throw ();
+
+ void decrementActiveCalls() throw ();
+
+ bool makeCall(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ std::vector< BinaryAny > const & inArguments, BinaryAny * returnValue,
+ std::vector< BinaryAny > * outArguments);
+
+ // Only called from reader_ thread:
+ void sendRequestChangeRequest();
+
+ // Only called from reader_ thread:
+ void handleRequestChangeReply(
+ bool exception, BinaryAny const & returnValue);
+
+ // Only called from reader_ thread:
+ void handleCommitChangeReply(bool exception, BinaryAny const & returnValue);
+
+ // Only called from reader_ thread:
+ void handleRequestChangeRequest(
+ rtl::ByteSequence const & tid,
+ std::vector< BinaryAny > const & inArguments);
+
+ // Only called from reader_ thread:
+ void handleCommitChangeRequest(
+ rtl::ByteSequence const & tid,
+ std::vector< BinaryAny > const & inArguments);
+
+ OutgoingRequest lastOutgoingRequest(rtl::ByteSequence const & tid);
+
+ bool isProtocolPropertiesRequest(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type) const;
+
+ void setCurrentContextMode();
+
+ bool isCurrentContextMode();
+
+private:
+ virtual ~Bridge();
+
+ virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ SAL_CALL getInstance(rtl::OUString const & sInstanceName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getName()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getDescription()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL dispose()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addEventListener(
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ const & xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removeEventListener(
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ const & aListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ // Only called from reader_ thread:
+ void sendCommitChangeRequest();
+
+ // Only called from reader_ thread:
+ void sendProtPropRequest(
+ OutgoingRequest::Kind kind,
+ std::vector< BinaryAny > const & inArguments);
+
+ void makeReleaseCall(
+ rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type);
+
+ void sendRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type,
+ com::sun::star::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments);
+
+ void throwException(bool exception, BinaryAny const & value);
+
+ com::sun::star::uno::Any mapBinaryToCppAny(BinaryAny const & binaryAny);
+
+ bool becameUnused() const;
+
+ void terminateWhenUnused(bool unused);
+
+ typedef
+ std::list<
+ com::sun::star::uno::Reference<
+ com::sun::star::lang::XEventListener > >
+ Listeners;
+
+ struct SubStub;
+
+ typedef std::map< com::sun::star::uno::TypeDescription, SubStub > Stub;
+
+ typedef std::map< rtl::OUString, Stub > Stubs;
+
+ enum Mode {
+ MODE_REQUESTED, MODE_REPLY_MINUS1, MODE_REPLY_0, MODE_REPLY_1,
+ MODE_WAIT, MODE_NORMAL, MODE_NORMAL_WAIT };
+
+ rtl::Reference< BridgeFactory > factory_;
+ rtl::OUString name_;
+ com::sun::star::uno::Reference< com::sun::star::connection::XConnection >
+ connection_;
+ com::sun::star::uno::Reference< com::sun::star::bridge::XInstanceProvider >
+ provider_;
+ com::sun::star::uno::Environment binaryUno_;
+ com::sun::star::uno::Mapping cppToBinaryMapping_;
+ com::sun::star::uno::Mapping binaryToCppMapping_;
+ rtl::ByteSequence protPropTid_;
+ rtl::OUString protPropOid_;
+ com::sun::star::uno::TypeDescription protPropType_;
+ com::sun::star::uno::TypeDescription protPropRequest_;
+ com::sun::star::uno::TypeDescription protPropCommit_;
+ uno_ThreadPool threadPool_;
+ OutgoingRequests outgoingRequests_;
+
+ osl::Mutex mutex_;
+ Listeners listeners_;
+ rtl::Reference< Writer > writer_;
+ rtl::Reference< Reader > reader_;
+ bool currentContextMode_;
+ Stubs stubs_;
+ std::size_t proxies_;
+ std::size_t calls_;
+ bool normalCall_;
+ std::size_t activeCalls_;
+ osl::Condition passive_;
+ // to guarantee that passive_ is eventually set (to avoid deadlock, see
+ // dispose), activeCalls_ only counts those calls for which it can be
+ // guaranteed that incrementActiveCalls is indeed followed by
+ // decrementActiveCalls, without an intervening exception
+ bool terminated_;
+
+ // Only accessed from reader_ thread:
+ Mode mode_;
+ sal_Int32 random_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/bridgefactory.cxx b/binaryurp/source/bridgefactory.cxx
new file mode 100644
index 000000000000..16bd9cf1b6f3
--- /dev/null
+++ b/binaryurp/source/bridgefactory.cxx
@@ -0,0 +1,232 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <algorithm>
+
+#include "com/sun/star/connection/XConnection.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implementationentry.hxx"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+#include "uno/lbnames.h"
+
+#include "bridge.hxx"
+#include "bridgefactory.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+css::uno::Reference< css::uno::XInterface > BridgeFactory::static_create(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext)
+ SAL_THROW((css::uno::Exception))
+{
+ return static_cast< cppu::OWeakObject * >(new BridgeFactory(xContext));
+}
+
+rtl::OUString BridgeFactory::static_getImplementationName() {
+ return rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.bridge.BridgeFactory"));
+}
+
+css::uno::Sequence< rtl::OUString >
+BridgeFactory::static_getSupportedServiceNames() {
+ rtl::OUString name(
+ RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory"));
+ return css::uno::Sequence< rtl::OUString >(&name, 1);
+}
+
+void BridgeFactory::removeBridge(
+ css::uno::Reference< css::bridge::XBridge > const & bridge)
+{
+ OSL_ASSERT(bridge.is());
+ rtl::OUString n(bridge->getName());
+ osl::MutexGuard g(*this);
+ if (n.getLength() == 0) {
+ BridgeList::iterator i(
+ std::find(unnamed_.begin(), unnamed_.end(), bridge));
+ if (i != unnamed_.end()) {
+ unnamed_.erase(i);
+ }
+ } else {
+ BridgeMap::iterator i(named_.find(n));
+ if (i != named_.end() && i->second == bridge) {
+ named_.erase(i);
+ }
+ }
+}
+
+BridgeFactory::BridgeFactory(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ BridgeFactoryBase(*static_cast< osl::Mutex * >(this)), context_(context)
+{
+ OSL_ASSERT(context.is());
+}
+
+BridgeFactory::~BridgeFactory() {}
+
+rtl::OUString BridgeFactory::getImplementationName()
+ throw (css::uno::RuntimeException)
+{
+ return static_getImplementationName();
+}
+
+sal_Bool BridgeFactory::supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< rtl::OUString > s(getSupportedServiceNames());
+ for (sal_Int32 i = 0; i != s.getLength(); ++i) {
+ if (ServiceName == s[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+css::uno::Sequence< rtl::OUString > BridgeFactory::getSupportedServiceNames()
+ throw (css::uno::RuntimeException)
+{
+ return static_getSupportedServiceNames();
+}
+
+css::uno::Reference< css::bridge::XBridge > BridgeFactory::createBridge(
+ rtl::OUString const & sName, rtl::OUString const & sProtocol,
+ css::uno::Reference< css::connection::XConnection > const & aConnection,
+ css::uno::Reference< css::bridge::XInstanceProvider > const &
+ anInstanceProvider)
+ throw (
+ css::bridge::BridgeExistsException, css::lang::IllegalArgumentException,
+ css::uno::RuntimeException)
+{
+ rtl::Reference< Bridge > b;
+ {
+ osl::MutexGuard g(*this);
+ if (named_.find(sName) != named_.end()) {
+ throw css::bridge::BridgeExistsException(
+ sName, static_cast< cppu::OWeakObject * >(this));
+ }
+ if (!(sProtocol.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("urp")) &&
+ aConnection.is()))
+ {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "BridgeFactory::createBridge: sProtocol != urp ||"
+ " aConnection == null")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ b.set(new Bridge(this, sName, aConnection, anInstanceProvider));
+ if (sName.getLength() == 0) {
+ unnamed_.push_back(
+ css::uno::Reference< css::bridge::XBridge >(b.get()));
+ } else {
+ named_[sName] = b.get();
+ }
+ }
+ b->start();
+ return css::uno::Reference< css::bridge::XBridge >(b.get());
+}
+
+css::uno::Reference< css::bridge::XBridge > BridgeFactory::getBridge(
+ rtl::OUString const & sName) throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard g(*this);
+ BridgeMap::iterator i(named_.find(sName));
+ return i == named_.end()
+ ? css::uno::Reference< css::bridge::XBridge >() : i->second;
+}
+
+css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > >
+BridgeFactory::getExistingBridges() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(*this);
+ if (unnamed_.size() > SAL_MAX_INT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "BridgeFactory::getExistingBridges: too many")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ sal_Int32 n = static_cast< sal_Int32 >(unnamed_.size());
+ if (named_.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32 - n)) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "BridgeFactory::getExistingBridges: too many")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ n = static_cast< sal_Int32 >(n + named_.size());
+ css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > > s(n);
+ sal_Int32 i = 0;
+ for (BridgeList::iterator j(unnamed_.begin()); j != unnamed_.end(); ++j) {
+ s[i++] = *j;
+ }
+ for (BridgeMap::iterator j(named_.begin()); j != named_.end(); ++j) {
+ s[i++] = j->second;
+ }
+ return s;
+}
+
+}
+
+namespace {
+
+static cppu::ImplementationEntry const services[] = {
+ { &binaryurp::BridgeFactory::static_create,
+ &binaryurp::BridgeFactory::static_getImplementationName,
+ &binaryurp::BridgeFactory::static_getSupportedServiceNames,
+ &cppu::createSingleComponentFactory, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
+ char const * pImplName, void * pServiceManager, void * pRegistryKey)
+{
+ return cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey, services);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL
+component_getImplementationEnvironment(
+ char const ** ppEnvTypeName, uno_Environment **)
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
diff --git a/binaryurp/source/bridgefactory.hxx b/binaryurp/source/bridgefactory.hxx
new file mode 100644
index 000000000000..af6499d61bd0
--- /dev/null
+++ b/binaryurp/source/bridgefactory.hxx
@@ -0,0 +1,144 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_BRIDGEFACTORY_HXX
+#define INCLUDED_BINARYURP_SOURCE_BRIDGEFACTORY_HXX
+
+#include "sal/config.h"
+
+#include <list>
+#include <map>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/bridge/XBridgeFactory.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "cppuhelper/compbase2.hxx"
+#include "sal/types.h"
+
+namespace com { namespace sun { namespace star {
+ namespace connection { class XConnection; }
+ namespace uno {
+ class XComponentContext;
+ class XInterface;
+ }
+} } }
+
+namespace binaryurp {
+
+// That BridgeFactory derives from XComponent appears to be a historic mistake;
+// the implementation does not care about a disposed state:
+
+typedef
+ cppu::WeakComponentImplHelper2<
+ com::sun::star::lang::XServiceInfo,
+ com::sun::star::bridge::XBridgeFactory >
+ BridgeFactoryBase;
+
+class BridgeFactory:
+ private osl::Mutex, public BridgeFactoryBase, private boost::noncopyable
+{
+public:
+ static com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ SAL_CALL static_create(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & xContext)
+ SAL_THROW((com::sun::star::uno::Exception));
+
+ static rtl::OUString SAL_CALL static_getImplementationName();
+
+ static com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+ static_getSupportedServiceNames();
+
+ void removeBridge(
+ com::sun::star::uno::Reference< com::sun::star::bridge::XBridge >
+ const & bridge);
+
+ using BridgeFactoryBase::acquire;
+ using BridgeFactoryBase::release;
+
+private:
+ explicit BridgeFactory(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & context);
+
+ virtual ~BridgeFactory();
+
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Reference< com::sun::star::bridge::XBridge >
+ SAL_CALL createBridge(
+ rtl::OUString const & sName, rtl::OUString const & sProtocol,
+ com::sun::star::uno::Reference<
+ com::sun::star::connection::XConnection > const & aConnection,
+ com::sun::star::uno::Reference<
+ com::sun::star::bridge::XInstanceProvider > const &
+ anInstanceProvider)
+ throw (
+ com::sun::star::bridge::BridgeExistsException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Reference< com::sun::star::bridge::XBridge >
+ SAL_CALL getBridge(
+ rtl::OUString const & sName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual
+ com::sun::star::uno::Sequence<
+ com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > >
+ SAL_CALL getExistingBridges() throw (com::sun::star::uno::RuntimeException);
+
+ typedef
+ std::list<
+ com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > >
+ BridgeList;
+
+ typedef
+ std::map<
+ rtl::OUString,
+ com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > >
+ BridgeMap;
+
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ context_;
+ BridgeList unnamed_;
+ BridgeMap named_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/cache.hxx b/binaryurp/source/cache.hxx
new file mode 100644
index 000000000000..118b8a07b98d
--- /dev/null
+++ b/binaryurp/source/cache.hxx
@@ -0,0 +1,134 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_CACHE_HXX
+#define INCLUDED_BINARYURP_SOURCE_CACHE_HXX
+
+#include "sal/config.h"
+
+#include <cstddef>
+#include <map>
+
+#include "boost/noncopyable.hpp"
+#include "osl/diagnose.h"
+#include "sal/types.h"
+
+namespace binaryurp {
+
+namespace cache {
+
+enum { size = 256, ignore = 0xFFFF };
+
+}
+
+template< typename T > class Cache: private boost::noncopyable {
+public:
+ explicit Cache(std::size_t size):
+ size_(size), first_(map_.end()), last_(map_.end())
+ {
+ OSL_ASSERT(size < cache::ignore);
+ }
+
+ sal_uInt16 add(T const & content, bool * found) {
+ OSL_ASSERT(found != 0);
+ typename Map::iterator i(map_.find(content));
+ *found = i != map_.end();
+ if (i == map_.end()) {
+ typename Map::size_type n = map_.size();
+ if (n < size_) {
+ i =
+ (map_.insert(
+ typename Map::value_type(
+ content,
+ Entry(
+ static_cast< sal_uInt16 >(n), map_.end(),
+ first_)))).
+ first;
+ if (first_ == map_.end()) {
+ last_ = i;
+ } else {
+ first_->second.prev = i;
+ }
+ first_ = i;
+ } else if (last_ != map_.end()) {
+ i =
+ (map_.insert(
+ typename Map::value_type(
+ content,
+ Entry(last_->second.index, map_.end(), first_)))).
+ first;
+ first_->second.prev = i;
+ first_ = i;
+ typename Map::iterator j(last_);
+ last_ = last_->second.prev;
+ last_->second.next = map_.end();
+ map_.erase(j);
+ } else {
+ // Reached iff size_ == 0:
+ return cache::ignore;
+ }
+ } else if (i != first_) {
+ // Move to front (reached only if size_ > 1):
+ i->second.prev->second.next = i->second.next;
+ if (i->second.next == map_.end()) {
+ last_ = i->second.prev;
+ } else {
+ i->second.next->second.prev = i->second.prev;
+ }
+ i->second.prev = map_.end();
+ i->second.next = first_;
+ first_->second.prev = i;
+ first_ = i;
+ }
+ return i->second.index;
+ }
+
+private:
+ struct Entry;
+
+ typedef std::map< T, Entry > Map;
+
+ struct Entry {
+ sal_uInt16 index;
+ typename Map::iterator prev;
+ typename Map::iterator next;
+
+ Entry(
+ sal_uInt16 theIndex, typename Map::iterator thePrev,
+ typename Map::iterator theNext):
+ index(theIndex), prev(thePrev), next(theNext) {}
+ };
+
+ std::size_t size_;
+ Map map_;
+ typename Map::iterator first_;
+ typename Map::iterator last_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/currentcontext.cxx b/binaryurp/source/currentcontext.cxx
new file mode 100644
index 000000000000..aed9640d84a0
--- /dev/null
+++ b/binaryurp/source/currentcontext.cxx
@@ -0,0 +1,80 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "uno/current_context.h"
+#include "uno/dispatcher.hxx"
+#include "uno/lbnames.h"
+
+#include "currentcontext.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+namespace current_context {
+
+css::uno::UnoInterfaceReference get() {
+ css::uno::UnoInterfaceReference cc;
+ if (!uno_getCurrentContext(
+ reinterpret_cast< void ** >(&cc.m_pUnoI),
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)).pData, 0))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("uno_getCurrentContext failed")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return cc;
+}
+
+void set(css::uno::UnoInterfaceReference const & value) {
+ css::uno::UnoInterfaceReference cc(value);
+ if (!uno_setCurrentContext(
+ cc.m_pUnoI,
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)).pData, 0))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("uno_setCurrentContext failed")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+}
+
+}
diff --git a/binaryurp/source/currentcontext.hxx b/binaryurp/source/currentcontext.hxx
new file mode 100644
index 000000000000..558d9ac04d5c
--- /dev/null
+++ b/binaryurp/source/currentcontext.hxx
@@ -0,0 +1,49 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_CURRENTCONTEXT_HXX
+#define INCLUDED_BINARYURP_SOURCE_CURRENTCONTEXT_HXX
+
+#include "sal/config.h"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class UnoInterfaceReference;
+} } } }
+
+namespace binaryurp {
+
+namespace current_context {
+
+com::sun::star::uno::UnoInterfaceReference get();
+
+void set(com::sun::star::uno::UnoInterfaceReference const & value);
+
+}
+
+}
+
+#endif
diff --git a/binaryurp/source/incomingreply.hxx b/binaryurp/source/incomingreply.hxx
new file mode 100644
index 000000000000..654542f701fa
--- /dev/null
+++ b/binaryurp/source/incomingreply.hxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_INCOMINGREPLY_HXX
+#define INCLUDED_BINARYURP_SOURCE_INCOMINGREPLY_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+
+#include "binaryany.hxx"
+
+namespace binaryurp {
+
+struct IncomingReply: private boost::noncopyable {
+ IncomingReply(
+ bool theException, BinaryAny const & theReturnValue,
+ std::vector< BinaryAny > const & theOutArguments):
+ exception(theException), returnValue(theReturnValue),
+ outArguments(theOutArguments)
+ {}
+
+ bool exception;
+
+ BinaryAny returnValue;
+
+ std::vector< BinaryAny > outArguments;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/incomingrequest.cxx b/binaryurp/source/incomingrequest.cxx
new file mode 100644
index 000000000000..646a868f66fd
--- /dev/null
+++ b/binaryurp/source/incomingrequest.cxx
@@ -0,0 +1,300 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <list>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/bridge/XInstanceProvider.hpp"
+#include "cppuhelper/exc_hlp.hxx"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "currentcontext.hxx"
+#include "incomingrequest.hxx"
+#include "specialfunctionids.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+IncomingRequest::IncomingRequest(
+ rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid,
+ rtl::OUString const & oid, css::uno::UnoInterfaceReference const & object,
+ css::uno::TypeDescription const & type, sal_uInt16 functionId,
+ bool synchronous, css::uno::TypeDescription const & member, bool setter,
+ std::vector< BinaryAny > const & inArguments, bool currentContextMode,
+ css::uno::UnoInterfaceReference const & currentContext):
+ bridge_(bridge), tid_(tid), oid_(oid), object_(object), type_(type),
+ functionId_(functionId), synchronous_(synchronous), member_(member),
+ setter_(setter), inArguments_(inArguments),
+ currentContextMode_(currentContextMode), currentContext_(currentContext)
+{
+ OSL_ASSERT(bridge.is() && member.is() && member.get()->bComplete);
+}
+
+IncomingRequest::~IncomingRequest() {}
+
+void IncomingRequest::execute() const {
+ BinaryAny ret;
+ std::vector< BinaryAny > outArgs;
+ bool isExc;
+ try {
+ bool resetCc = false;
+ css::uno::UnoInterfaceReference oldCc;
+ if (currentContextMode_) {
+ oldCc = current_context::get();
+ current_context::set(currentContext_);
+ resetCc = true;
+ }
+ try {
+ try {
+ isExc = !execute_throw(&ret, &outArgs);
+ } catch (std::exception & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) +
+ rtl::OStringToOUString(
+ rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)),
+ css::uno::Reference< css::uno::XInterface >());
+ // best-effort string conversion
+ }
+ } catch (css::uno::RuntimeException &) {
+ css::uno::Any exc(cppu::getCaughtException());
+ ret = bridge_->mapCppToBinaryAny(exc);
+ isExc = true;
+ }
+ if (resetCc) {
+ current_context::set(oldCc);
+ }
+ } catch (css::uno::RuntimeException &) {
+ css::uno::Any exc(cppu::getCaughtException());
+ ret = bridge_->mapCppToBinaryAny(exc);
+ isExc = true;
+ }
+ if (synchronous_) {
+ bridge_->decrementActiveCalls();
+ try {
+ bridge_->getWriter()->queueReply(
+ tid_, member_, setter_, isExc, ret, outArgs, false);
+ return;
+ } catch (css::uno::RuntimeException & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught UNO runtime exception '%s'",
+ (rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).
+ getStr()));
+ } catch (std::exception & e) {
+ OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
+ }
+ bridge_->terminate();
+ } else {
+ if (isExc) {
+ OSL_TRACE(OSL_LOG_PREFIX "oneway method raised exception");
+ }
+ bridge_->decrementCalls();
+ }
+}
+
+bool IncomingRequest::execute_throw(
+ BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const
+{
+ OSL_ASSERT(
+ returnValue != 0 &&
+ returnValue->getType().equals(
+ css::uno::TypeDescription(
+ cppu::UnoType< cppu::UnoVoidType >::get())) &&
+ outArguments != 0 && outArguments->empty());
+ bool isExc = false;
+ switch (functionId_) {
+ case SPECIAL_FUNCTION_ID_RESERVED:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ case SPECIAL_FUNCTION_ID_RELEASE:
+ bridge_->releaseStub(oid_, type_);
+ break;
+ case SPECIAL_FUNCTION_ID_QUERY_INTERFACE:
+ if (!object_.is()) {
+ css::uno::Reference< css::uno::XInterface > ifc;
+ css::uno::Reference< css::bridge::XInstanceProvider > prov(
+ bridge_->getProvider());
+ if (prov.is()) {
+ try {
+ ifc = prov->getInstance(oid_);
+ } catch (css::container::NoSuchElementException & e) {
+ OSL_TRACE(
+ (OSL_LOG_PREFIX "initial element '%s':"
+ " NoSuchElementException '%s'"),
+ (rtl::OUStringToOString(oid_, RTL_TEXTENCODING_UTF8).
+ getStr()),
+ (rtl::OUStringToOString(
+ e.Message, RTL_TEXTENCODING_UTF8).
+ getStr()));
+ }
+ }
+ if (ifc.is()) {
+ css::uno::UnoInterfaceReference unoIfc(
+ static_cast< uno_Interface * >(
+ bridge_->getCppToBinaryMapping().mapInterface(
+ ifc.get(),
+ (css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference<
+ css::uno::XInterface > >::get()).
+ get()))),
+ SAL_NO_ACQUIRE);
+ *returnValue = BinaryAny(
+ css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference<
+ css::uno::XInterface > >::get()),
+ &unoIfc.m_pUnoI);
+ }
+ break;
+ }
+ // fall through
+ default:
+ {
+ OSL_ASSERT(object_.is());
+ css::uno::TypeDescription retType;
+ std::list< std::vector< char > > outBufs;
+ std::vector< void * > args;
+ switch (member_.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ css::uno::TypeDescription t(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ member_.get())->
+ pAttributeTypeRef);
+ if (setter_) {
+ OSL_ASSERT(inArguments_.size() == 1);
+ args.push_back(inArguments_[0].getValue(t));
+ } else {
+ OSL_ASSERT(inArguments_.empty());
+ retType = t;
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(
+ member_.get());
+ retType = css::uno::TypeDescription(mtd->pReturnTypeRef);
+ std::vector< BinaryAny >::const_iterator i(
+ inArguments_.begin());
+ for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
+ void * p;
+ if (mtd->pParams[j].bIn) {
+ p = i++->getValue(
+ css::uno::TypeDescription(
+ mtd->pParams[j].pTypeRef));
+ } else {
+ outBufs.push_back(
+ std::vector< char >(
+ css::uno::TypeDescription(
+ mtd->pParams[j].pTypeRef).
+ get()->nSize));
+ p = &outBufs.back()[0];
+ }
+ args.push_back(p);
+ if (mtd->pParams[j].bOut) {
+ outArguments->push_back(BinaryAny());
+ }
+ }
+ OSL_ASSERT(i == inArguments_.end());
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ std::vector< char > retBuf(retType.is() ? retType.get()->nSize : 0);
+ uno_Any exc;
+ uno_Any * pexc = &exc;
+ (*object_.get()->pDispatcher)(
+ object_.get(), member_.get(), retBuf.empty() ? 0 : &retBuf[0],
+ args.empty() ? 0 : &args[0], &pexc);
+ isExc = pexc != 0;
+ if (isExc) {
+ *returnValue = BinaryAny(
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Any >::get()),
+ &exc);
+ uno_any_destruct(&exc, 0);
+ } else {
+ if (!retBuf.empty()) {
+ *returnValue = BinaryAny(retType, &retBuf[0]);
+ uno_destructData(&retBuf[0], retType.get(), 0);
+ }
+ if (!outArguments->empty()) {
+ OSL_ASSERT(
+ member_.get()->eTypeClass ==
+ typelib_TypeClass_INTERFACE_METHOD);
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(
+ member_.get());
+ std::vector< BinaryAny >::iterator i(outArguments->begin());
+ std::list< std::vector< char > >::iterator j(
+ outBufs.begin());
+ for (sal_Int32 k = 0; k != mtd->nParams; ++k) {
+ if (mtd->pParams[k].bOut) {
+ *i++ = BinaryAny(
+ css::uno::TypeDescription(
+ mtd->pParams[k].pTypeRef),
+ args[k]);
+ }
+ if (!mtd->pParams[k].bIn) {
+ uno_type_destructData(
+ &(*j++)[0], mtd->pParams[k].pTypeRef, 0);
+ }
+ }
+ OSL_ASSERT(i == outArguments->end());
+ OSL_ASSERT(j == outBufs.end());
+ }
+ }
+ break;
+ }
+ }
+ return !isExc;
+}
+
+}
diff --git a/binaryurp/source/incomingrequest.hxx b/binaryurp/source/incomingrequest.hxx
new file mode 100644
index 000000000000..ead7067f8ae9
--- /dev/null
+++ b/binaryurp/source/incomingrequest.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_INCOMINGREQUEST_HXX
+#define INCLUDED_BINARYURP_SOURCE_INCOMINGREQUEST_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+#include "uno/dispatcher.hxx"
+
+namespace binaryurp {
+ class BinaryAny;
+ class Bridge;
+}
+
+namespace binaryurp {
+
+class IncomingRequest: private boost::noncopyable {
+public:
+ IncomingRequest(
+ rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid,
+ rtl::OUString const & oid,
+ com::sun::star::uno::UnoInterfaceReference const & object,
+ com::sun::star::uno::TypeDescription const & type,
+ sal_uInt16 functionId, bool synchronous,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ std::vector< BinaryAny > const & inArguments, bool currentContextMode,
+ com::sun::star::uno::UnoInterfaceReference const & currentContext);
+
+ ~IncomingRequest();
+
+ void execute() const;
+
+private:
+ bool execute_throw(
+ BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const;
+
+ rtl::Reference< Bridge > bridge_;
+ rtl::ByteSequence tid_;
+ rtl::OUString oid_; // initial object queryInterface; release
+ com::sun::star::uno::UnoInterfaceReference object_;
+ com::sun::star::uno::TypeDescription type_;
+ sal_uInt16 functionId_;
+ bool synchronous_;
+ com::sun::star::uno::TypeDescription member_;
+ bool setter_;
+ std::vector< BinaryAny > inArguments_;
+ bool currentContextMode_;
+ com::sun::star::uno::UnoInterfaceReference currentContext_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/lessoperators.cxx b/binaryurp/source/lessoperators.cxx
new file mode 100644
index 000000000000..354118625ce8
--- /dev/null
+++ b/binaryurp/source/lessoperators.cxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <algorithm>
+
+#include "osl/diagnose.h"
+#include "rtl/byteseq.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.hxx"
+
+#include "lessoperators.hxx"
+
+namespace com { namespace sun { namespace star { namespace uno {
+
+bool operator <(TypeDescription const & left, TypeDescription const & right) {
+ OSL_ASSERT(left.is() && right.is());
+ typelib_TypeClass tc1 = left.get()->eTypeClass;
+ typelib_TypeClass tc2 = right.get()->eTypeClass;
+ return tc1 < tc2 ||
+ (tc1 == tc2 &&
+ (rtl::OUString(left.get()->pTypeName) <
+ rtl::OUString(right.get()->pTypeName)));
+}
+
+} } } }
+
+namespace rtl {
+
+bool operator <(ByteSequence const & left, ByteSequence const & right) {
+ for (sal_Int32 i = 0; i != std::min(left.getLength(), right.getLength());
+ ++i)
+ {
+ if (left[i] < right[i]) {
+ return true;
+ }
+ if (right[i] < left[i]) {
+ return false;
+ }
+ }
+ return left.getLength() < right.getLength();
+}
+
+}
diff --git a/binaryurp/source/lessoperators.hxx b/binaryurp/source/lessoperators.hxx
new file mode 100644
index 000000000000..014f0f4d56bf
--- /dev/null
+++ b/binaryurp/source/lessoperators.hxx
@@ -0,0 +1,50 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_LESSOPERATORS_HXX
+#define INCLUDED_BINARYURP_SOURCE_LESSOPERATORS_HXX
+
+#include "sal/config.h"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class TypeDescription;
+} } } }
+namespace rtl { class ByteSequence; }
+
+namespace com { namespace sun { namespace star { namespace uno {
+
+bool operator <(TypeDescription const & left, TypeDescription const & right);
+
+} } } }
+
+namespace rtl {
+
+bool operator <(ByteSequence const & left, ByteSequence const & right);
+
+}
+
+#endif
diff --git a/binaryurp/source/makefile.mk b/binaryurp/source/makefile.mk
new file mode 100644
index 000000000000..ca9e7c72b65d
--- /dev/null
+++ b/binaryurp/source/makefile.mk
@@ -0,0 +1,69 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#***********************************************************************/
+
+PRJ = ..
+PRJNAME = binaryurp
+TARGET = binaryurp
+
+ENABLE_EXCEPTIONS = TRUE
+VISIBILITY_HIDDEN = TRUE
+
+.INCLUDE: settings.mk
+
+DLLPRE =
+
+SLOFILES = \
+ $(SLO)/binaryany.obj \
+ $(SLO)/bridge.obj \
+ $(SLO)/bridgefactory.obj \
+ $(SLO)/currentcontext.obj \
+ $(SLO)/incomingrequest.obj \
+ $(SLO)/lessoperators.obj \
+ $(SLO)/marshal.obj \
+ $(SLO)/outgoingrequests.obj \
+ $(SLO)/proxy.obj \
+ $(SLO)/reader.obj \
+ $(SLO)/unmarshal.obj \
+ $(SLO)/writer.obj
+
+SHL1IMPLIB = i$(SHL1TARGET)
+SHL1OBJS = $(SLOFILES)
+SHL1RPATH = URELIB
+SHL1STDLIBS = $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB)
+SHL1TARGET = binaryurp.uno
+SHL1USE_EXPORTS = name
+DEF1NAME = $(SHL1TARGET)
+
+.INCLUDE: target.mk
+
+ALLTAR : $(MISC)/binaryurp.component
+
+$(MISC)/binaryurp.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \
+ binaryurp.component
+ $(XSLTPROC) --nonet --stringparam uri \
+ '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \
+ $(SOLARENV)/bin/createcomponent.xslt binaryurp.component
diff --git a/binaryurp/source/marshal.cxx b/binaryurp/source/marshal.cxx
new file mode 100644
index 000000000000..ce520382efac
--- /dev/null
+++ b/binaryurp/source/marshal.cxx
@@ -0,0 +1,314 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppu/unotype.hxx"
+#include "osl/diagnose.h"
+#include "rtl/byteseq.hxx"
+#include "rtl/string.hxx"
+#include "rtl/textcvt.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "cache.hxx"
+#include "lessoperators.hxx"
+#include "marshal.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+void write64(std::vector< unsigned char > * buffer, sal_uInt64 value) {
+ Marshal::write8(buffer, value >> 56);
+ Marshal::write8(buffer, (value >> 48) & 0xFF);
+ Marshal::write8(buffer, (value >> 40) & 0xFF);
+ Marshal::write8(buffer, (value >> 32) & 0xFF);
+ Marshal::write8(buffer, (value >> 24) & 0xFF);
+ Marshal::write8(buffer, (value >> 16) & 0xFF);
+ Marshal::write8(buffer, (value >> 8) & 0xFF);
+ Marshal::write8(buffer, value & 0xFF);
+}
+
+void writeCompressed(std::vector< unsigned char > * buffer, sal_uInt32 value) {
+ if (value < 0xFF) {
+ Marshal::write8(buffer, static_cast< sal_uInt8 >(value));
+ } else {
+ Marshal::write8(buffer, 0xFF);
+ Marshal::write32(buffer, value);
+ }
+}
+
+void writeString(
+ std::vector< unsigned char > * buffer, rtl::OUString const & value)
+{
+ OSL_ASSERT(buffer != 0);
+ rtl::OString v;
+ if (!value.convertToString(
+ &v, RTL_TEXTENCODING_UTF8,
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "UNO string contains invalid UTF-16 sequence")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ writeCompressed(buffer, static_cast< sal_uInt32 >(v.getLength()));
+ buffer->insert(buffer->end(), v.getStr(), v.getStr() + v.getLength());
+}
+
+}
+
+Marshal::Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state):
+ bridge_(bridge), state_(state)
+{
+ OSL_ASSERT(bridge.is());
+}
+
+Marshal::~Marshal() {}
+
+void Marshal::write8(std::vector< unsigned char > * buffer, sal_uInt8 value) {
+ OSL_ASSERT(buffer != 0);
+ buffer->push_back(value);
+}
+
+void Marshal::write16(std::vector< unsigned char > * buffer, sal_uInt16 value) {
+ write8(buffer, value >> 8);
+ write8(buffer, value & 0xFF);
+}
+
+void Marshal::write32(std::vector< unsigned char > * buffer, sal_uInt32 value) {
+ write8(buffer, value >> 24);
+ write8(buffer, (value >> 16) & 0xFF);
+ write8(buffer, (value >> 8) & 0xFF);
+ write8(buffer, value & 0xFF);
+}
+
+void Marshal::writeValue(
+ std::vector< unsigned char > * buffer,
+ css::uno::TypeDescription const & type, BinaryAny const & value)
+{
+ OSL_ASSERT(
+ type.is() &&
+ (type.get()->eTypeClass == typelib_TypeClass_ANY ||
+ value.getType().equals(type)));
+ writeValue(buffer, type, value.getValue(type));
+}
+
+void Marshal::writeType(
+ std::vector< unsigned char > * buffer,
+ css::uno::TypeDescription const & value)
+{
+ value.makeComplete();
+ OSL_ASSERT(value.is());
+ typelib_TypeClass tc = value.get()->eTypeClass;
+ if (tc <= typelib_TypeClass_ANY) {
+ write8(buffer, static_cast< sal_uInt8 >(tc));
+ } else {
+ bool found;
+ sal_uInt16 idx = state_.typeCache.add(value, &found);
+ if (found) {
+ write8(buffer, static_cast< sal_uInt8 >(tc));
+ write16(buffer, idx);
+ } else {
+ write8(buffer, static_cast< sal_uInt8 >(tc) | 0x80);
+ write16(buffer, idx);
+ writeString(buffer, rtl::OUString(value.get()->pTypeName));
+ }
+ }
+}
+
+void Marshal::writeOid(
+ std::vector< unsigned char > * buffer, rtl::OUString const & oid)
+{
+ bool found;
+ sal_uInt16 idx;
+ if (oid.getLength() == 0) {
+ found = true;
+ idx = cache::ignore;
+ } else {
+ idx = state_.oidCache.add(oid, &found);
+ }
+ if (found) {
+ write8(buffer, 0);
+ } else {
+ writeString(buffer, oid);
+ }
+ write16(buffer, idx);
+}
+
+void Marshal::writeTid(
+ std::vector< unsigned char > * buffer, rtl::ByteSequence const & tid)
+{
+ bool found;
+ sal_uInt16 idx = state_.tidCache.add(tid, &found);
+ if (found) {
+ write8(buffer, 0);
+ } else {
+ sal_Sequence * p = tid.getHandle();
+ writeValue(
+ buffer,
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()), &p);
+ }
+ write16(buffer, idx);
+}
+
+void Marshal::writeValue(
+ std::vector< unsigned char > * buffer,
+ css::uno::TypeDescription const & type, void const * value)
+{
+ OSL_ASSERT(buffer != 0 && type.is());
+ type.makeComplete();
+ switch (type.get()->eTypeClass) {
+ case typelib_TypeClass_VOID:
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ OSL_ASSERT(*static_cast< sal_uInt8 const * >(value) <= 1);
+ // fall through
+ case typelib_TypeClass_BYTE:
+ write8(buffer, *static_cast< sal_uInt8 const * >(value));
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_CHAR:
+ write16(buffer, *static_cast< sal_uInt16 const * >(value));
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_ENUM:
+ write32(buffer, *static_cast< sal_uInt32 const * >(value));
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_DOUBLE:
+ write64(buffer, *static_cast< sal_uInt64 const * >(value));
+ break;
+ case typelib_TypeClass_STRING:
+ writeString(
+ buffer,
+ rtl::OUString(*static_cast< rtl_uString * const * >(value)));
+ break;
+ case typelib_TypeClass_TYPE:
+ writeType(
+ buffer,
+ css::uno::TypeDescription(
+ *static_cast< typelib_TypeDescriptionReference * const * >(
+ value)));
+ break;
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any const * p = static_cast< uno_Any const * >(value);
+ css::uno::TypeDescription t(p->pType);
+ writeType(buffer, t);
+ writeValue(buffer, t, p->pData);
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ sal_Sequence * p = *static_cast< sal_Sequence * const * >(value);
+ writeCompressed(buffer, static_cast< sal_uInt32 >(p->nElements));
+ css::uno::TypeDescription ctd(
+ reinterpret_cast< typelib_IndirectTypeDescription * >(
+ type.get())->
+ pType);
+ OSL_ASSERT(ctd.is());
+ if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
+ buffer->insert(
+ buffer->end(), p->elements, p->elements + p->nElements);
+ } else {
+ for (sal_Int32 i = 0; i != p->nElements; ++i) {
+ writeValue(buffer, ctd, p->elements + i * ctd.get()->nSize);
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ writeMemberValues(buffer, type, value);
+ break;
+ case typelib_TypeClass_INTERFACE:
+ writeOid(
+ buffer,
+ bridge_->registerOutgoingInterface(
+ css::uno::UnoInterfaceReference(
+ *static_cast< uno_Interface * const * >(value)),
+ type));
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+}
+
+void Marshal::writeMemberValues(
+ std::vector< unsigned char > * buffer,
+ css::uno::TypeDescription const & type, void const * aggregateValue)
+{
+ OSL_ASSERT(
+ type.is() &&
+ (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
+ type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
+ aggregateValue != 0);
+ type.makeComplete();
+ typelib_CompoundTypeDescription * ctd =
+ reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
+ if (ctd->pBaseTypeDescription != 0) {
+ writeMemberValues(
+ buffer,
+ css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
+ aggregateValue);
+ }
+ for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
+ writeValue(
+ buffer, css::uno::TypeDescription(ctd->ppTypeRefs[i]),
+ (static_cast< char const * >(aggregateValue) +
+ ctd->pMemberOffsets[i]));
+ }
+}
+
+}
diff --git a/binaryurp/source/marshal.hxx b/binaryurp/source/marshal.hxx
new file mode 100644
index 000000000000..a922ec1008f6
--- /dev/null
+++ b/binaryurp/source/marshal.hxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_MARSHAL_HXX
+#define INCLUDED_BINARYURP_SOURCE_MARSHAL_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+
+namespace binaryurp {
+ class BinaryAny;
+ class Bridge;
+ struct WriterState;
+}
+
+namespace binaryurp {
+
+class Marshal: private boost::noncopyable {
+public:
+ Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state);
+
+ ~Marshal();
+
+ static void write8(std::vector< unsigned char > * buffer, sal_uInt8 value);
+
+ static void write16(
+ std::vector< unsigned char > * buffer, sal_uInt16 value);
+
+ static void write32(
+ std::vector< unsigned char > * buffer, sal_uInt32 value);
+
+ void writeValue(
+ std::vector< unsigned char > * buffer,
+ com::sun::star::uno::TypeDescription const & type,
+ BinaryAny const & value);
+
+ void writeType(
+ std::vector< unsigned char > * buffer,
+ com::sun::star::uno::TypeDescription const & value);
+
+ void writeOid(
+ std::vector< unsigned char > * buffer, rtl::OUString const & oid);
+
+ void writeTid(
+ std::vector< unsigned char > * buffer, rtl::ByteSequence const & tid);
+
+private:
+ void writeValue(
+ std::vector< unsigned char > * buffer,
+ com::sun::star::uno::TypeDescription const & type, void const * value);
+
+ void writeMemberValues(
+ std::vector< unsigned char > * buffer,
+ com::sun::star::uno::TypeDescription const & type,
+ void const * aggregateValue);
+
+ rtl::Reference< Bridge > bridge_;
+ WriterState & state_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/outgoingrequest.hxx b/binaryurp/source/outgoingrequest.hxx
new file mode 100644
index 000000000000..7fe67bf96a3b
--- /dev/null
+++ b/binaryurp/source/outgoingrequest.hxx
@@ -0,0 +1,55 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_OUTGOINGREQUEST_HXX
+#define INCLUDED_BINARYURP_SOURCE_OUTGOINGREQUEST_HXX
+
+#include "sal/config.h"
+
+#include "typelib/typedescription.hxx"
+
+namespace binaryurp {
+
+struct OutgoingRequest {
+ enum Kind { KIND_NORMAL, KIND_REQUEST_CHANGE, KIND_COMMIT_CHANGE };
+
+ OutgoingRequest(
+ Kind theKind, com::sun::star::uno::TypeDescription const & theMember,
+ bool theSetter):
+ kind(theKind), member(theMember), setter(theSetter)
+ {}
+
+ Kind kind;
+
+ com::sun::star::uno::TypeDescription member;
+
+ bool setter;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/outgoingrequests.cxx b/binaryurp/source/outgoingrequests.cxx
new file mode 100644
index 000000000000..388b7755466f
--- /dev/null
+++ b/binaryurp/source/outgoingrequests.cxx
@@ -0,0 +1,80 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "rtl/byteseq.hxx"
+#include "osl/mutex.hxx"
+
+#include "lessoperators.hxx"
+#include "outgoingrequest.hxx"
+#include "outgoingrequests.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+OutgoingRequests::OutgoingRequests() {}
+
+OutgoingRequests::~OutgoingRequests() {}
+
+void OutgoingRequests::push(
+ rtl::ByteSequence const & tid, OutgoingRequest const & request)
+{
+ osl::MutexGuard g(mutex_);
+ map_[tid].push_back(request);
+}
+
+OutgoingRequest OutgoingRequests::top(rtl::ByteSequence const & tid) {
+ osl::MutexGuard g(mutex_);
+ Map::iterator i(map_.find(tid));
+ if (i == map_.end()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URP: reply for unknown TID")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OSL_ASSERT(!i->second.empty());
+ return i->second.back();
+}
+
+void OutgoingRequests::pop(rtl::ByteSequence const & tid) throw () {
+ osl::MutexGuard g(mutex_);
+ Map::iterator i(map_.find(tid));
+ OSL_ASSERT(i != map_.end());
+ i->second.pop_back();
+ if (i->second.empty()) {
+ map_.erase(i);
+ }
+}
+
+}
diff --git a/binaryurp/source/outgoingrequests.hxx b/binaryurp/source/outgoingrequests.hxx
new file mode 100644
index 000000000000..92ee622bf682
--- /dev/null
+++ b/binaryurp/source/outgoingrequests.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_OUTGOINGREQUESTS_HXX
+#define INCLUDED_BINARYURP_SOURCE_OUTGOINGREQUESTS_HXX
+
+#include "sal/config.h"
+
+#include <map>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "osl/mutex.hxx"
+
+namespace binaryurp { struct OutgoingRequest; }
+namespace rtl { class ByteSequence; }
+
+namespace binaryurp {
+
+class OutgoingRequests: private boost::noncopyable {
+public:
+ OutgoingRequests();
+
+ ~OutgoingRequests();
+
+ void push(rtl::ByteSequence const & tid, OutgoingRequest const & request);
+
+ OutgoingRequest top(rtl::ByteSequence const & tid);
+
+ void pop(rtl::ByteSequence const & tid) throw ();
+
+private:
+ typedef std::map< rtl::ByteSequence, std::vector< OutgoingRequest > > Map;
+
+ osl::Mutex mutex_;
+ Map map_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/proxy.cxx b/binaryurp/source/proxy.cxx
new file mode 100644
index 000000000000..876199e7bc17
--- /dev/null
+++ b/binaryurp/source/proxy.cxx
@@ -0,0 +1,260 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <exception>
+#include <vector>
+
+#include "cppuhelper/exc_hlp.hxx"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/any2.h"
+#include "uno/dispatcher.h"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "proxy.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+extern "C" void SAL_CALL proxy_acquireInterface(uno_Interface * pInterface) {
+ OSL_ASSERT(pInterface != 0);
+ static_cast< Proxy * >(pInterface)->do_acquire();
+}
+
+extern "C" void SAL_CALL proxy_releaseInterface(uno_Interface * pInterface) {
+ OSL_ASSERT(pInterface != 0);
+ static_cast< Proxy * >(pInterface)->do_release();
+}
+
+extern "C" void SAL_CALL proxy_dispatchInterface(
+ uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType,
+ void * pReturn, void ** pArgs, uno_Any ** ppException)
+{
+ OSL_ASSERT(pUnoI != 0);
+ static_cast< Proxy * >(pUnoI)->do_dispatch(
+ pMemberType, pReturn, pArgs, ppException);
+}
+
+}
+
+Proxy::Proxy(
+ rtl::Reference< Bridge > const & bridge, rtl::OUString const & oid,
+ css::uno::TypeDescription const & type):
+ bridge_(bridge), oid_(oid), type_(type), references_(1)
+{
+ OSL_ASSERT(bridge.is());
+ acquire = &proxy_acquireInterface;
+ release = &proxy_releaseInterface;
+ pDispatcher = &proxy_dispatchInterface;
+}
+
+rtl::OUString Proxy::getOid() const {
+ return oid_;
+}
+
+css::uno::TypeDescription Proxy::getType() const {
+ return type_;
+}
+
+void Proxy::do_acquire() {
+ if (osl_incrementInterlockedCount(&references_) == 1) {
+ bridge_->resurrectProxy(*this);
+ }
+}
+
+void Proxy::do_release() {
+ if (osl_decrementInterlockedCount(&references_) == 0) {
+ bridge_->revokeProxy(*this);
+ }
+}
+
+void Proxy::do_free() {
+ bridge_->freeProxy(*this);
+ delete this;
+}
+
+void Proxy::do_dispatch(
+ typelib_TypeDescription const * member, void * returnValue,
+ void ** arguments, uno_Any ** exception) const
+{
+ try {
+ try {
+ do_dispatch_throw(member, returnValue, arguments, exception);
+ } catch (std::exception & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) +
+ rtl::OStringToOUString(
+ rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)),
+ css::uno::Reference< css::uno::XInterface >());
+ // best-effort string conversion
+ }
+ } catch (css::uno::RuntimeException &) {
+ css::uno::Any exc(cppu::getCaughtException());
+ uno_copyAndConvertData(
+ *exception, &exc,
+ (css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).
+ get()),
+ bridge_->getCppToBinaryMapping().get());
+ }
+}
+
+bool Proxy::isProxy(
+ rtl::Reference< Bridge > const & bridge,
+ css::uno::UnoInterfaceReference const & object, rtl::OUString * oid)
+{
+ OSL_ASSERT(object.is());
+ return object.m_pUnoI->acquire == &proxy_acquireInterface &&
+ static_cast< Proxy * >(object.m_pUnoI)->isProxy(bridge, oid);
+}
+
+Proxy::~Proxy() {}
+
+void Proxy::do_dispatch_throw(
+ typelib_TypeDescription const * member, void * returnValue,
+ void ** arguments, uno_Any ** exception) const
+{
+ //TODO: Optimize queryInterface:
+ OSL_ASSERT(member != 0);
+ bool setter = false;
+ std::vector< BinaryAny > inArgs;
+ switch (member->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ setter = returnValue == 0;
+ if (setter) {
+ inArgs.push_back(
+ BinaryAny(
+ css::uno::TypeDescription(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription const * >(
+ member)->
+ pAttributeTypeRef),
+ arguments[0]));
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription const * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription const * >(member);
+ for (sal_Int32 i = 0; i != mtd->nParams; ++i) {
+ if (mtd->pParams[i].bIn) {
+ inArgs.push_back(
+ BinaryAny(
+ css::uno::TypeDescription(mtd->pParams[i].pTypeRef),
+ arguments[i]));
+ }
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ BinaryAny ret;
+ std::vector< BinaryAny > outArgs;
+ if (bridge_->makeCall(
+ oid_,
+ css::uno::TypeDescription(
+ const_cast< typelib_TypeDescription * >(member)),
+ setter, inArgs, &ret, &outArgs))
+ {
+ OSL_ASSERT(
+ ret.getType().get()->eTypeClass == typelib_TypeClass_EXCEPTION);
+ uno_any_construct(
+ *exception, ret.getValue(ret.getType()), ret.getType().get(), 0);
+ } else {
+ switch (member->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ if (!setter) {
+ css::uno::TypeDescription t(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription const * >(
+ member)->
+ pAttributeTypeRef);
+ uno_copyData(returnValue, ret.getValue(t), t.get(), 0);
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription const * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription const * >(
+ member);
+ css::uno::TypeDescription t(mtd->pReturnTypeRef);
+ if (t.get()->eTypeClass != typelib_TypeClass_VOID) {
+ uno_copyData(returnValue, ret.getValue(t), t.get(), 0);
+ }
+ std::vector< BinaryAny >::iterator i(outArgs.begin());
+ for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
+ if (mtd->pParams[j].bOut) {
+ css::uno::TypeDescription pt(mtd->pParams[j].pTypeRef);
+ if (mtd->pParams[j].bIn) {
+ uno_assignData(
+ arguments[j], pt.get(), i++->getValue(pt),
+ pt.get(), 0, 0, 0);
+ } else {
+ uno_copyData(
+ arguments[j], i++->getValue(pt), pt.get(), 0);
+ }
+ }
+ }
+ OSL_ASSERT(i == outArgs.end());
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ *exception = 0;
+ }
+}
+
+bool Proxy::isProxy(
+ rtl::Reference< Bridge > const & bridge, rtl::OUString * oid) const
+{
+ OSL_ASSERT(oid != 0);
+ if (bridge == bridge_) {
+ *oid = oid_;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+}
diff --git a/binaryurp/source/proxy.hxx b/binaryurp/source/proxy.hxx
new file mode 100644
index 000000000000..c67ab4eb522a
--- /dev/null
+++ b/binaryurp/source/proxy.hxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_PROXY_HXX
+#define INCLUDED_BINARYURP_SOURCE_PROXY_HXX
+
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "osl/interlck.h"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/any2.h"
+#include "uno/dispatcher.h"
+
+namespace binaryurp { class Bridge; }
+namespace com { namespace sun { namespace star { namespace uno {
+ class UnoInterfaceReference;
+} } } }
+
+namespace binaryurp {
+
+class Proxy: public uno_Interface, private boost::noncopyable {
+public:
+ Proxy(
+ rtl::Reference< Bridge > const & bridge, rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type);
+
+ rtl::OUString getOid() const;
+
+ com::sun::star::uno::TypeDescription getType() const;
+
+ void do_acquire();
+
+ void do_release();
+
+ void do_free();
+
+ void do_dispatch(
+ typelib_TypeDescription const * member, void * returnValue,
+ void ** arguments, uno_Any ** exception) const;
+
+ static bool isProxy(
+ rtl::Reference< Bridge > const & bridge,
+ com::sun::star::uno::UnoInterfaceReference const & object,
+ rtl::OUString * oid);
+
+private:
+ ~Proxy();
+
+ void do_dispatch_throw(
+ typelib_TypeDescription const * member, void * returnValue,
+ void ** arguments, uno_Any ** exception) const;
+
+ bool isProxy(rtl::Reference< Bridge > const & bridge, rtl::OUString * oid)
+ const;
+
+ rtl::Reference< Bridge > bridge_;
+ rtl::OUString oid_;
+ com::sun::star::uno::TypeDescription type_;
+ oslInterlockedCount references_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/reader.cxx b/binaryurp/source/reader.cxx
new file mode 100644
index 000000000000..f622fb5b0c42
--- /dev/null
+++ b/binaryurp/source/reader.cxx
@@ -0,0 +1,553 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <exception>
+#include <memory>
+#include <vector>
+
+#include "com/sun/star/connection/XConnection.hpp"
+#include "com/sun/star/io/IOException.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/XCurrentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppu/unotype.hxx"
+#include "osl/diagnose.h"
+#include "rtl/byteseq.h"
+#include "rtl/string.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/lbnames.h"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "incomingreply.hxx"
+#include "incomingrequest.hxx"
+#include "outgoingrequest.hxx"
+#include "reader.hxx"
+#include "specialfunctionids.hxx"
+#include "unmarshal.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+css::uno::Sequence< sal_Int8 > read(
+ css::uno::Reference< css::connection::XConnection > const & connection,
+ sal_uInt32 size, bool eofOk)
+{
+ OSL_ASSERT(connection.is());
+ if (size > SAL_MAX_INT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Reader: block size too large")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ css::uno::Sequence< sal_Int8 > buf;
+ sal_Int32 n = connection->read(buf, static_cast< sal_Int32 >(size));
+ if (n == 0 && eofOk) {
+ return css::uno::Sequence< sal_Int8 >();
+ }
+ if (n != static_cast< sal_Int32 >(size)) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Reader: premature end of input")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OSL_ASSERT(buf.getLength() == static_cast< sal_Int32 >(size));
+ return buf;
+}
+
+extern "C" void SAL_CALL request(void * pThreadSpecificData) {
+ OSL_ASSERT(pThreadSpecificData != 0);
+ std::auto_ptr< IncomingRequest >(
+ static_cast< IncomingRequest * >(pThreadSpecificData))->
+ execute();
+}
+
+}
+
+Reader::Reader(rtl::Reference< Bridge > const & bridge): bridge_(bridge) {
+ OSL_ASSERT(bridge.is());
+ acquire();
+}
+
+Reader::~Reader() {}
+
+void Reader::run() {
+ setName("binaryurpReader");
+ try {
+ bridge_->sendRequestChangeRequest();
+ css::uno::Reference< css::connection::XConnection > con(
+ bridge_->getConnection());
+ for (;;) {
+ css::uno::Sequence< sal_Int8 > s(read(con, 8, true));
+ if (s.getLength() == 0) {
+ break;
+ }
+ Unmarshal header(bridge_, state_, s);
+ sal_uInt32 size = header.read32();
+ sal_uInt32 count = header.read32();
+ header.done();
+ if (count == 0) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Reader: block with zero message count"
+ " received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ Unmarshal block(bridge_, state_, read(con, size, false));
+ for (sal_uInt32 i = 0; i != count; ++i) {
+ readMessage(block);
+ }
+ block.done();
+ }
+ } catch (css::uno::Exception & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught UNO exception '%s'",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ } catch (std::exception & e) {
+ OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
+ }
+ bridge_->terminate();
+}
+
+void Reader::onTerminated() {
+ release();
+}
+
+void Reader::readMessage(Unmarshal & unmarshal) {
+ sal_uInt8 flags1 = unmarshal.read8();
+ bool newType;
+ bool newOid;
+ bool newTid;
+ bool forceSynchronous;
+ sal_uInt16 functionId;
+ if ((flags1 & 0x80) != 0) { // bit 7: LONGHEADER
+ if ((flags1 & 0x40) == 0) { // bit 6: REQUEST
+ readReplyMessage(unmarshal, flags1);
+ return;
+ }
+ newType = (flags1 & 0x20) != 0; // bit 5: NEWTYPE
+ newOid = (flags1 & 0x10) != 0; // bit 4: NEWOID
+ newTid = (flags1 & 0x08) != 0; // bit 3: NEWTID
+ if ((flags1 & 0x01) != 0) { // bit 0: MOREFLAGSS
+ sal_uInt8 flags2 = unmarshal.read8();
+ forceSynchronous = (flags2 & 0x80) != 0; // bit 7: MUSTREPLY
+ if (((flags2 & 0x40) != 0) != forceSynchronous) {
+ // bit 6: SYNCHRONOUS
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with MUSTREPLY != SYNCHRONOUS"
+ " received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ forceSynchronous = false;
+ }
+ functionId = ((flags1 & 0x04) != 0) // bit 2: FUNCTIONID16
+ ? unmarshal.read16() : unmarshal.read8();
+ } else {
+ newType = false;
+ newOid = false;
+ newTid = false;
+ forceSynchronous = false;
+ functionId = ((flags1 & 0x40) != 0) // bit 6: FUNCTIONID14
+ ? ((flags1 & 0x3F) << 8) | unmarshal.read8() : flags1 & 0x3F;
+ }
+ css::uno::TypeDescription type;
+ if (newType) {
+ type = unmarshal.readType();
+ lastType_ = type;
+ } else {
+ if (!lastType_.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with NEWTYPE received when last"
+ " interface type has not yet been set")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ type = lastType_;
+ }
+ rtl::OUString oid;
+ if (newOid) {
+ oid = unmarshal.readOid();
+ if (oid.getLength() == 0) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: emtpy OID")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ lastOid_ = oid;
+ } else {
+ if (lastOid_.getLength() == 0) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with NEWOID received when last"
+ " OID has not yet been set")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ oid = lastOid_;
+ }
+ rtl::ByteSequence tid(getTid(unmarshal, newTid));
+ lastTid_ = tid;
+ type.makeComplete();
+ if (type.get()->eTypeClass != typelib_TypeClass_INTERFACE) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with non-interface interface type"
+ " received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ typelib_InterfaceTypeDescription * itd =
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(type.get());
+ if (functionId >= itd->nMapFunctionIndexToMemberIndex) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with unknown function ID received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ sal_Int32 memberId = itd->pMapFunctionIndexToMemberIndex[functionId];
+ css::uno::TypeDescription memberTd(itd->ppAllMembers[memberId]);
+ memberTd.makeComplete();
+ OSL_ASSERT(memberTd.is());
+ bool protProps = bridge_->isProtocolPropertiesRequest(oid, type);
+ bool ccMode = !protProps && functionId != SPECIAL_FUNCTION_ID_RELEASE &&
+ bridge_->isCurrentContextMode();
+ css::uno::UnoInterfaceReference cc;
+ if (ccMode) {
+ css::uno::TypeDescription t(
+ cppu::UnoType< css::uno::Reference< css::uno::XCurrentContext > >::
+ get());
+ cc.set(
+ *static_cast< uno_Interface ** >(
+ unmarshal.readValue(t).getValue(t)));
+ }
+ bool synchronous;
+ if (memberTd.get()->eTypeClass == typelib_TypeClass_INTERFACE_METHOD &&
+ (reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
+ memberTd.get())->
+ bOneWay))
+ {
+ synchronous = forceSynchronous;
+ } else {
+ if (forceSynchronous) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: synchronous request message with non-oneway"
+ " function ID received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ synchronous = true;
+ }
+ bool setter = false;
+ std::vector< BinaryAny > inArgs;
+ switch (memberTd.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ setter = itd->pMapMemberIndexToFunctionIndex[memberId] != functionId;
+ // pMapMemberIndexToFunctionIndex contains function index of
+ // attribute getter
+ if (setter) {
+ inArgs.push_back(
+ unmarshal.readValue(
+ css::uno::TypeDescription(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ memberTd.get())->
+ pAttributeTypeRef)));
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
+ memberTd.get());
+ for (sal_Int32 i = 0; i != mtd->nParams; ++i) {
+ if (mtd->pParams[i].bIn) {
+ inArgs.push_back(
+ unmarshal.readValue(
+ css::uno::TypeDescription(
+ mtd->pParams[i].pTypeRef)));
+ }
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ bridge_->incrementCalls(
+ !protProps && functionId != SPECIAL_FUNCTION_ID_RELEASE);
+ if (protProps) {
+ switch (functionId) {
+ case SPECIAL_FUNCTION_ID_REQUEST_CHANGE:
+ bridge_->handleRequestChangeRequest(tid, inArgs);
+ break;
+ case SPECIAL_FUNCTION_ID_COMMIT_CHANGE:
+ bridge_->handleCommitChangeRequest(tid, inArgs);
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with UrpProtocolProperties OID"
+ " and unknown function ID received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ css::uno::UnoInterfaceReference obj;
+ switch (functionId) {
+ case SPECIAL_FUNCTION_ID_QUERY_INTERFACE:
+ obj = bridge_->findStub(oid, type);
+ if (!obj.is()) {
+ OSL_ASSERT(
+ inArgs.size() == 1
+ && inArgs[0].getType().equals(
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Type >::get())));
+ if (!(type.equals(
+ css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference<
+ css::uno::XInterface > >::get()))
+ && (css::uno::TypeDescription(
+ *static_cast<
+ typelib_TypeDescriptionReference ** >(
+ inArgs[0].getValue(inArgs[0].getType()))).
+ equals(
+ css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference<
+ css::uno::XInterface > >::get())))))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: queryInterface request message with"
+ " unknown OID received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ break;
+ case SPECIAL_FUNCTION_ID_RESERVED:
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with unknown function ID 1"
+ " received")),
+ css::uno::Reference< css::uno::XInterface >());
+ case SPECIAL_FUNCTION_ID_RELEASE:
+ break;
+ default:
+ obj = bridge_->findStub(oid, type);
+ if (!obj.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: request message with unknown OID received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ }
+ std::auto_ptr< IncomingRequest > req(
+ new IncomingRequest(
+ bridge_, tid, oid, obj, type, functionId, synchronous, memberTd,
+ setter, inArgs, ccMode, cc));
+ if (synchronous) {
+ bridge_->incrementActiveCalls();
+ }
+ uno_threadpool_putJob(
+ bridge_->getThreadPool(), tid.getHandle(), req.get(), &request,
+ !synchronous);
+ req.release();
+ }
+}
+
+void Reader::readReplyMessage(Unmarshal & unmarshal, sal_uInt8 flags1) {
+ rtl::ByteSequence tid(getTid(unmarshal, (flags1 & 0x08) != 0));
+ // bit 3: NEWTID
+ lastTid_ = tid;
+ OutgoingRequest req(bridge_->lastOutgoingRequest(tid));
+ bool exc = (flags1 & 0x20) != 0; // bit 5: EXCEPTION
+ BinaryAny ret;
+ std::vector< BinaryAny > outArgs;
+ if (exc) {
+ ret = unmarshal.readValue(
+ css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()));
+ if (!typelib_typedescription_isAssignableFrom(
+ (css::uno::TypeDescription(
+ cppu::UnoType< css::uno::RuntimeException >::get()).
+ get()),
+ ret.getType().get()))
+ {
+ sal_Int32 n = 0;
+ typelib_TypeDescriptionReference ** p = 0;
+ switch (req.member.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_InterfaceAttributeTypeDescription * atd =
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ req.member.get());
+ n = req.setter ? atd->nSetExceptions : atd->nGetExceptions;
+ p = req.setter
+ ? atd->ppSetExceptions : atd->ppGetExceptions;
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(
+ req.member.get());
+ n = mtd->nExceptions;
+ p = mtd->ppExceptions;
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ bool ok = false;
+ for (sal_Int32 i = 0; i != n; ++i) {
+ if (typelib_typedescriptionreference_isAssignableFrom(
+ p[i],
+ reinterpret_cast< typelib_TypeDescriptionReference * >(
+ ret.getType().get())))
+ {
+ ok = true;
+ break;
+ }
+ }
+ if (!ok) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: reply message with bad exception type"
+ " received")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ } else {
+ switch (req.member.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ if (!req.setter) {
+ ret = unmarshal.readValue(
+ css::uno::TypeDescription(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ req.member.get())->
+ pAttributeTypeRef));
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(
+ req.member.get());
+ ret = unmarshal.readValue(
+ css::uno::TypeDescription(mtd->pReturnTypeRef));
+ for (sal_Int32 i = 0; i != mtd->nParams; ++i) {
+ if (mtd->pParams[i].bOut) {
+ outArgs.push_back(
+ unmarshal.readValue(
+ css::uno::TypeDescription(
+ mtd->pParams[i].pTypeRef)));
+ }
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+ switch (req.kind) {
+ case OutgoingRequest::KIND_NORMAL:
+ {
+ std::auto_ptr< IncomingReply > resp(
+ new IncomingReply(exc, ret, outArgs));
+ uno_threadpool_putJob(
+ bridge_->getThreadPool(), tid.getHandle(), resp.get(), 0,
+ false);
+ resp.release();
+ break;
+ }
+ case OutgoingRequest::KIND_REQUEST_CHANGE:
+ OSL_ASSERT(outArgs.empty());
+ bridge_->handleRequestChangeReply(exc, ret);
+ break;
+ case OutgoingRequest::KIND_COMMIT_CHANGE:
+ OSL_ASSERT(outArgs.empty());
+ bridge_->handleCommitChangeReply(exc, ret);
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+}
+
+rtl::ByteSequence Reader::getTid(Unmarshal & unmarshal, bool newTid) const {
+ if (newTid) {
+ return unmarshal.readTid();
+ }
+ if (lastTid_.getLength() == 0) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "URP: message with NEWTID received when last TID has not"
+ " yet been set")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return lastTid_;
+}
+
+}
diff --git a/binaryurp/source/reader.hxx b/binaryurp/source/reader.hxx
new file mode 100644
index 000000000000..37d0b9462ae4
--- /dev/null
+++ b/binaryurp/source/reader.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_READER_HXX
+#define INCLUDED_BINARYURP_SOURCE_READER_HXX
+
+#include "sal/config.h"
+
+#include <cstddef>
+
+#include "boost/noncopyable.hpp"
+#include "osl/thread.hxx"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "salhelper/simplereferenceobject.hxx"
+#include "typelib/typedescription.hxx"
+
+#include "readerstate.hxx"
+
+namespace binaryurp {
+ class BinaryAny;
+ class Bridge;
+ class Unmarshal;
+}
+
+namespace binaryurp {
+
+class Reader:
+ public osl::Thread, public salhelper::SimpleReferenceObject,
+ private boost::noncopyable
+{
+public:
+ static void * operator new(std::size_t size)
+ { return Thread::operator new(size); }
+
+ static void operator delete(void * pointer)
+ { Thread::operator delete(pointer); }
+
+ explicit Reader(rtl::Reference< Bridge > const & bridge);
+
+private:
+ virtual ~Reader();
+
+ virtual void SAL_CALL run();
+
+ virtual void SAL_CALL onTerminated();
+
+ void readMessage(Unmarshal & unmarshal);
+
+ void readReplyMessage(Unmarshal & unmarshal, sal_uInt8 flags1);
+
+ rtl::ByteSequence getTid(Unmarshal & unmarshal, bool newTid) const;
+
+ rtl::Reference< Bridge > bridge_;
+ com::sun::star::uno::TypeDescription lastType_;
+ rtl::OUString lastOid_;
+ rtl::ByteSequence lastTid_;
+ ReaderState state_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/readerstate.hxx b/binaryurp/source/readerstate.hxx
new file mode 100644
index 000000000000..ef7ed4d7196f
--- /dev/null
+++ b/binaryurp/source/readerstate.hxx
@@ -0,0 +1,52 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_READERSTATE_HXX
+#define INCLUDED_BINARYURP_SOURCE_READERSTATE_HXX
+
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "rtl/byteseq.hxx"
+#include "rtl/ustring.hxx"
+#include "typelib/typedescription.hxx"
+
+#include "cache.hxx"
+
+namespace binaryurp {
+
+struct ReaderState: private boost::noncopyable {
+ com::sun::star::uno::TypeDescription typeCache[cache::size];
+
+ rtl::OUString oidCache[cache::size];
+
+ rtl::ByteSequence tidCache[cache::size];
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/specialfunctionids.hxx b/binaryurp/source/specialfunctionids.hxx
new file mode 100644
index 000000000000..a2a59791ba09
--- /dev/null
+++ b/binaryurp/source/specialfunctionids.hxx
@@ -0,0 +1,49 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_SPECIALFUNCTIONIDS_HXX
+#define INCLUDED_BINARYURP_SOURCE_SPECIALFUNCTIONIDS_HXX
+
+#include "sal/config.h"
+
+namespace binaryurp {
+
+enum SpecialFunctionIds {
+ SPECIAL_FUNCTION_ID_QUERY_INTERFACE = 0,
+
+ SPECIAL_FUNCTION_ID_RESERVED = 1,
+
+ SPECIAL_FUNCTION_ID_RELEASE = 2,
+
+ SPECIAL_FUNCTION_ID_REQUEST_CHANGE = 4,
+
+ SPECIAL_FUNCTION_ID_COMMIT_CHANGE = 5
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/unmarshal.cxx b/binaryurp/source/unmarshal.cxx
new file mode 100644
index 000000000000..62f8683e33ad
--- /dev/null
+++ b/binaryurp/source/unmarshal.cxx
@@ -0,0 +1,563 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <cstdlib>
+#include <new>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/io/IOException.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppu/unotype.hxx"
+#include "osl/diagnose.h"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/textcvt.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+#include "typelib/typedescription.hxx"
+#include "uno/any2.h"
+#include "uno/data.h"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "cache.hxx"
+#include "readerstate.hxx"
+#include "unmarshal.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+void * allocate(sal_Size size) {
+ void * p = rtl_allocateMemory(size);
+ if (p == 0) {
+ throw std::bad_alloc();
+ }
+ return p;
+}
+
+std::vector< BinaryAny >::iterator copyMemberValues(
+ css::uno::TypeDescription const & type,
+ std::vector< BinaryAny >::iterator const & it, void * buffer) throw ()
+{
+ OSL_ASSERT(
+ type.is() &&
+ (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
+ type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
+ buffer != 0);
+ type.makeComplete();
+ std::vector< BinaryAny >::iterator i(it);
+ typelib_CompoundTypeDescription * ctd =
+ reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
+ if (ctd->pBaseTypeDescription != 0) {
+ i = copyMemberValues(
+ css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase), i,
+ buffer);
+ }
+ for (sal_Int32 j = 0; j != ctd->nMembers; ++j) {
+ uno_type_copyData(
+ static_cast< char * >(buffer) + ctd->pMemberOffsets[j],
+ const_cast< void * >(
+ i++->getValue(css::uno::TypeDescription(ctd->ppTypeRefs[j]))),
+ ctd->ppTypeRefs[j], 0);
+ }
+ return i;
+}
+
+}
+
+Unmarshal::Unmarshal(
+ rtl::Reference< Bridge > const & bridge, ReaderState & state,
+ css::uno::Sequence< sal_Int8 > const & buffer):
+ bridge_(bridge), state_(state), buffer_(buffer)
+{
+ data_ = reinterpret_cast< sal_uInt8 const * >(buffer_.getConstArray());
+ end_ = data_ + buffer_.getLength();
+}
+
+Unmarshal::~Unmarshal() {}
+
+sal_uInt8 Unmarshal::read8() {
+ check(1);
+ return *data_++;
+}
+
+sal_uInt16 Unmarshal::read16() {
+ check(2);
+ sal_uInt16 n = static_cast< sal_uInt16 >(*data_++) << 8;
+ return n | *data_++;
+}
+
+sal_uInt32 Unmarshal::read32() {
+ check(4);
+ sal_uInt32 n = static_cast< sal_uInt32 >(*data_++) << 24;
+ n |= static_cast< sal_uInt32 >(*data_++) << 16;
+ n |= static_cast< sal_uInt32 >(*data_++) << 8;
+ return n | *data_++;
+}
+
+css::uno::TypeDescription Unmarshal::readType() {
+ sal_uInt8 flags = read8();
+ typelib_TypeClass tc = static_cast< typelib_TypeClass >(flags & 0x7F);
+ switch (tc) {
+ case typelib_TypeClass_VOID:
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_STRING:
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ if ((flags & 0x80) != 0) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: cache flag of simple type is"
+ " set")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return css::uno::TypeDescription(
+ *typelib_static_type_getByTypeClass(
+ static_cast< typelib_TypeClass >(tc)));
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_INTERFACE:
+ {
+ sal_uInt16 idx = readCacheIndex();
+ if ((flags & 0x80) == 0) {
+ if (idx == cache::ignore || !state_.typeCache[idx].is()) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: unknown type cache"
+ " index")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return state_.typeCache[idx];
+ } else {
+ css::uno::TypeDescription t(readString());
+ if (!t.is() ||
+ t.get()->eTypeClass != static_cast< typelib_TypeClass >(tc))
+ {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: type with unknown"
+ " name")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ for (css::uno::TypeDescription t2(t);
+ t2.get()->eTypeClass == typelib_TypeClass_SEQUENCE;)
+ {
+ t2.makeComplete();
+ t2 = css::uno::TypeDescription(
+ reinterpret_cast< typelib_IndirectTypeDescription * >(
+ t2.get())->pType);
+ if (!t2.is()) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: sequence type with"
+ " unknown component type")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ switch (t2.get()->eTypeClass) {
+ case typelib_TypeClass_VOID:
+ case typelib_TypeClass_EXCEPTION:
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: sequence type with"
+ " bad component type")),
+ css::uno::Reference< css::uno::XInterface >());
+ default:
+ break;
+ }
+ }
+ if (idx != cache::ignore) {
+ state_.typeCache[idx] = t;
+ }
+ return t;
+ }
+ }
+ default:
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: type of unknown type class")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+rtl::OUString Unmarshal::readOid() {
+ rtl::OUString oid(readString());
+ for (sal_Int32 i = 0; i != oid.getLength(); ++i) {
+ if (oid[i] > 0x7F) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: OID contains non-ASCII"
+ " character")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ sal_uInt16 idx = readCacheIndex();
+ if (oid.getLength() == 0 && idx != cache::ignore) {
+ if (state_.oidCache[idx].getLength() == 0) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: unknown OID cache index")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return state_.oidCache[idx];
+ }
+ if (idx != cache::ignore) {
+ state_.oidCache[idx] = oid;
+ }
+ return oid;
+}
+
+rtl::ByteSequence Unmarshal::readTid() {
+ rtl::ByteSequence tid(
+ *static_cast< sal_Sequence * const * >(
+ readSequence(
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get())).
+ getValue(
+ css::uno::TypeDescription(
+ cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()))));
+ sal_uInt16 idx = readCacheIndex();
+ if (tid.getLength() == 0) {
+ if (idx == cache::ignore || state_.tidCache[idx].getLength() == 0) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: unknown TID cache index")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return state_.tidCache[idx];
+ }
+ if (idx != cache::ignore) {
+ state_.tidCache[idx] = tid;
+ }
+ return tid;
+}
+
+BinaryAny Unmarshal::readValue(css::uno::TypeDescription const & type) {
+ OSL_ASSERT(type.is());
+ switch (type.get()->eTypeClass) {
+ default:
+ std::abort(); // this cannot happen
+ // pseudo fall-through to avoid compiler warnings
+ case typelib_TypeClass_VOID:
+ return BinaryAny();
+ case typelib_TypeClass_BOOLEAN:
+ {
+ sal_uInt8 v = read8();
+ if (v > 1) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: boolean of unknown value")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ sal_uInt8 v = read8();
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_CHAR:
+ {
+ sal_uInt16 v = read16();
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_FLOAT:
+ {
+ sal_uInt32 v = read32();
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_DOUBLE:
+ {
+ sal_uInt64 v = read64();
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_STRING:
+ {
+ rtl::OUString v(readString());
+ return BinaryAny(type, &v.pData);
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ css::uno::TypeDescription v(readType());
+ typelib_TypeDescription * p = v.get();
+ return BinaryAny(type, &p);
+ }
+ case typelib_TypeClass_ANY:
+ {
+ css::uno::TypeDescription t(readType());
+ if (t.get()->eTypeClass == typelib_TypeClass_ANY) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: any of type ANY")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return readValue(t);
+ }
+ case typelib_TypeClass_SEQUENCE:
+ type.makeComplete();
+ return readSequence(type);
+ case typelib_TypeClass_ENUM:
+ {
+ sal_Int32 v = static_cast< sal_Int32 >(read32());
+ type.makeComplete();
+ typelib_EnumTypeDescription * etd =
+ reinterpret_cast< typelib_EnumTypeDescription * >(type.get());
+ bool found = false;
+ for (sal_Int32 i = 0; i != etd->nEnumValues; ++i) {
+ if (etd->pEnumValues[i] == v) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: unknown enum value")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return BinaryAny(type, &v);
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ std::vector< BinaryAny > as;
+ readMemberValues(type, &as);
+ void * buf = allocate(type.get()->nSize);
+ copyMemberValues(type, as.begin(), buf);
+ uno_Any raw;
+ raw.pType = reinterpret_cast< typelib_TypeDescriptionReference * >(
+ type.get());
+ raw.pData = buf;
+ raw.pReserved = 0;
+ return BinaryAny(raw);
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ css::uno::UnoInterfaceReference obj(
+ bridge_->registerIncomingInterface(readOid(), type));
+ return BinaryAny(type, &obj.m_pUnoI);
+ }
+ }
+}
+
+void Unmarshal::done() const {
+ if (data_ != end_) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: block contains excess data")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void Unmarshal::check(sal_Int32 size) const {
+ if (end_ - data_ < size) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: trying to read past end of block")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+sal_uInt32 Unmarshal::readCompressed() {
+ sal_uInt8 n = read8();
+ return n == 0xFF ? read32() : n;
+}
+
+sal_uInt16 Unmarshal::readCacheIndex() {
+ sal_uInt16 idx = read16();
+ if (idx >= cache::size && idx != cache::ignore) {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: cache index out of range")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return idx;
+}
+
+sal_uInt64 Unmarshal::read64() {
+ check(8);
+ sal_uInt64 n = static_cast< sal_uInt64 >(*data_++) << 56;
+ n |= static_cast< sal_uInt64 >(*data_++) << 48;
+ n |= static_cast< sal_uInt64 >(*data_++) << 40;
+ n |= static_cast< sal_uInt64 >(*data_++) << 32;
+ n |= static_cast< sal_uInt64 >(*data_++) << 24;
+ n |= static_cast< sal_uInt64 >(*data_++) << 16;
+ n |= static_cast< sal_uInt64 >(*data_++) << 8;
+ return n | *data_++;
+}
+
+rtl::OUString Unmarshal::readString() {
+ sal_uInt32 n = readCompressed();
+ if (n > SAL_MAX_INT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: string size too large")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ check(static_cast< sal_Int32 >(n));
+ rtl::OUString s;
+ if (!rtl_convertStringToUString(
+ &s.pData, reinterpret_cast< char const * >(data_),
+ static_cast< sal_Int32 >(n), RTL_TEXTENCODING_UTF8,
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+ {
+ throw css::io::IOException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: string does not contain UTF-8")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ data_ += n;
+ return s;
+}
+
+BinaryAny Unmarshal::readSequence(css::uno::TypeDescription const & type) {
+ OSL_ASSERT(
+ type.is() && type.get()->eTypeClass == typelib_TypeClass_SEQUENCE);
+ sal_uInt32 n = readCompressed();
+ if (n > SAL_MAX_INT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: sequence size too large")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (n == 0) {
+ return BinaryAny(type, 0);
+ }
+ css::uno::TypeDescription ctd(
+ reinterpret_cast< typelib_IndirectTypeDescription * >(
+ type.get())->pType);
+ if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
+ check(static_cast< sal_Int32 >(n));
+ rtl::ByteSequence s(
+ reinterpret_cast< sal_Int8 const * >(data_),
+ static_cast< sal_Int32 >(n));
+ data_ += n;
+ sal_Sequence * p = s.getHandle();
+ return BinaryAny(type, &p);
+ }
+ std::vector< BinaryAny > as;
+ for (sal_uInt32 i = 0; i != n; ++i) {
+ as.push_back(readValue(ctd));
+ }
+ OSL_ASSERT(ctd.get()->nSize >= 0);
+ sal_uInt64 size = static_cast< sal_uInt64 >(n) *
+ static_cast< sal_uInt64 >(ctd.get()->nSize);
+ // sal_uInt32 * sal_Int32 -> sal_uInt64 cannot overflow
+ if (size > SAL_MAX_SIZE - SAL_SEQUENCE_HEADER_SIZE) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "binaryurp::Unmarshal: sequence size too large")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ void * buf = allocate(
+ SAL_SEQUENCE_HEADER_SIZE + static_cast< sal_Size >(size));
+ static_cast< sal_Sequence * >(buf)->nRefCount = 0;
+ static_cast< sal_Sequence * >(buf)->nElements =
+ static_cast< sal_Int32 >(n);
+ for (sal_uInt32 i = 0; i != n; ++i) {
+ uno_copyData(
+ static_cast< sal_Sequence * >(buf)->elements + i * ctd.get()->nSize,
+ const_cast< void * >(as[i].getValue(ctd)), ctd.get(), 0);
+ }
+ return BinaryAny(type, reinterpret_cast< sal_Sequence ** >(&buf));
+}
+
+void Unmarshal::readMemberValues(
+ css::uno::TypeDescription const & type, std::vector< BinaryAny > * values)
+{
+ OSL_ASSERT(
+ type.is() &&
+ (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
+ type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
+ values != 0);
+ type.makeComplete();
+ typelib_CompoundTypeDescription * ctd =
+ reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
+ if (ctd->pBaseTypeDescription != 0) {
+ readMemberValues(
+ css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
+ values);
+ }
+ for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
+ values->push_back(
+ readValue(css::uno::TypeDescription(ctd->ppTypeRefs[i])));
+ }
+}
+
+}
diff --git a/binaryurp/source/unmarshal.hxx b/binaryurp/source/unmarshal.hxx
new file mode 100644
index 000000000000..33a4aafec75e
--- /dev/null
+++ b/binaryurp/source/unmarshal.hxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_UNMARSHAL_HXX
+#define INCLUDED_BINARYURP_SOURCE_UNMARSHAL_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.hxx"
+
+namespace binaryurp {
+ class BinaryAny;
+ class Bridge;
+ struct ReaderState;
+}
+namespace com { namespace sun { namespace star { namespace uno {
+ class TypeDescription;
+} } } }
+namespace rtl {
+ class ByteSequecne;
+ class OUString;
+}
+
+namespace binaryurp {
+
+class Unmarshal: private boost::noncopyable {
+public:
+ Unmarshal(
+ rtl::Reference< Bridge > const & bridge, ReaderState & state,
+ com::sun::star::uno::Sequence< sal_Int8 > const & buffer);
+
+ ~Unmarshal();
+
+ sal_uInt8 read8();
+
+ sal_uInt16 read16();
+
+ sal_uInt32 read32();
+
+ com::sun::star::uno::TypeDescription readType();
+
+ rtl::OUString readOid();
+
+ rtl::ByteSequence readTid();
+
+ BinaryAny readValue(com::sun::star::uno::TypeDescription const & type);
+
+ void done() const;
+
+private:
+ void check(sal_Int32 size) const;
+
+ sal_uInt32 readCompressed();
+
+ sal_uInt16 readCacheIndex();
+
+ sal_uInt64 read64();
+
+ rtl::OUString readString();
+
+ BinaryAny readSequence(com::sun::star::uno::TypeDescription const & type);
+
+ void readMemberValues(
+ com::sun::star::uno::TypeDescription const & type,
+ std::vector< BinaryAny > * values);
+
+ rtl::Reference< Bridge > bridge_;
+ ReaderState & state_;
+ com::sun::star::uno::Sequence< sal_Int8 > buffer_;
+ sal_uInt8 const * data_;
+ sal_uInt8 const * end_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/writer.cxx b/binaryurp/source/writer.cxx
new file mode 100644
index 000000000000..97a60157eb6f
--- /dev/null
+++ b/binaryurp/source/writer.cxx
@@ -0,0 +1,476 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "sal/config.h"
+
+#include <exception>
+#include <vector>
+
+#include "com/sun/star/connection/XConnection.hpp"
+#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
+#include "com/sun/star/uno/XCurrentContext.hpp"
+#include "cppuhelper/exc_hlp.hxx"
+#include "osl/mutex.hxx"
+#include "rtl/memory.h"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "bridge.hxx"
+#include "currentcontext.hxx"
+#include "specialfunctionids.hxx"
+#include "writer.hxx"
+
+namespace binaryurp {
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool isProtocolPropertyMessage(rtl::OUString const & oid) {
+ return oid.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties"));
+}
+
+}
+
+Writer::Item::Item() {}
+
+Writer::Item::Item(
+ rtl::ByteSequence const & theTid, rtl::OUString const & theOid,
+ css::uno::TypeDescription const & theType,
+ css::uno::TypeDescription const & theMember,
+ std::vector< BinaryAny > const & inArguments,
+ css::uno::UnoInterfaceReference const & theCurrentContext):
+ request(true), tid(theTid), oid(theOid), type(theType), member(theMember),
+ arguments(inArguments), currentContext(theCurrentContext)
+{}
+
+Writer::Item::Item(
+ rtl::ByteSequence const & theTid,
+ css::uno::TypeDescription const & theMember, bool theSetter,
+ bool theException, BinaryAny const & theReturnValue,
+ std::vector< BinaryAny > const & outArguments,
+ bool theSetCurrentContextMode):
+ request(false), tid(theTid), member(theMember), setter(theSetter),
+ arguments(outArguments), exception(theException),
+ returnValue(theReturnValue), setCurrentContextMode(theSetCurrentContextMode)
+{}
+
+Writer::Writer(rtl::Reference< Bridge > const & bridge):
+ bridge_(bridge), marshal_(bridge, state_), stop_(false)
+{
+ OSL_ASSERT(bridge.is());
+ acquire();
+}
+
+void Writer::sendDirectRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ css::uno::TypeDescription const & type,
+ css::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments)
+{
+ OSL_ASSERT(!unblocked_.check());
+ sendRequest(
+ tid, oid, type, member, inArguments, false,
+ css::uno::UnoInterfaceReference());
+}
+
+void Writer::sendDirectReply(
+ rtl::ByteSequence const & tid, css::uno::TypeDescription const & member,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments)
+{
+ OSL_ASSERT(!unblocked_.check());
+ sendReply(tid, member, false, exception, returnValue,outArguments);
+}
+
+void Writer::queueRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ css::uno::TypeDescription const & type,
+ css::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments)
+{
+ css::uno::UnoInterfaceReference cc(current_context::get());
+ osl::MutexGuard g(mutex_);
+ queue_.push_back(Item(tid, oid, type, member, inArguments, cc));
+ items_.set();
+}
+
+void Writer::queueReply(
+ rtl::ByteSequence const & tid,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments, bool setCurrentContextMode)
+{
+ osl::MutexGuard g(mutex_);
+ queue_.push_back(
+ Item(
+ tid, member, setter, exception, returnValue, outArguments,
+ setCurrentContextMode));
+ items_.set();
+}
+
+void Writer::unblock() {
+ // Assumes that osl::Condition::set works as a memory barrier, so that
+ // changes made by preceeding sendDirectRequest/Reply calls are visible to
+ // subsequent sendRequest/Reply calls:
+ unblocked_.set();
+}
+
+void Writer::stop() {
+ {
+ osl::MutexGuard g(mutex_);
+ stop_ = true;
+ }
+ unblocked_.set();
+ items_.set();
+}
+
+Writer::~Writer() {}
+
+void Writer::run() {
+ setName("binaryurpWriter");
+ try {
+ unblocked_.wait();
+ for (;;) {
+ items_.wait();
+ Item item;
+ {
+ osl::MutexGuard g(mutex_);
+ if (stop_) {
+ return;
+ }
+ OSL_ASSERT(!queue_.empty());
+ item = queue_.front();
+ queue_.pop_front();
+ if (queue_.empty()) {
+ items_.reset();
+ }
+ }
+ if (item.request) {
+ sendRequest(
+ item.tid, item.oid, item.type, item.member, item.arguments,
+ (!item.oid.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties")) &&
+ !item.member.equals(
+ css::uno::TypeDescription(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.uno.XInterface::"
+ "release")))) &&
+ bridge_->isCurrentContextMode()),
+ item.currentContext);
+ } else {
+ sendReply(
+ item.tid, item.member, item.setter, item.exception,
+ item.returnValue, item.arguments);
+ if (item.setCurrentContextMode) {
+ bridge_->setCurrentContextMode();
+ }
+ }
+ }
+ } catch (css::uno::Exception & e) {
+ OSL_TRACE(
+ OSL_LOG_PREFIX "caught UNO exception '%s'",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ } catch (std::exception & e) {
+ OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
+ }
+ bridge_->terminate();
+}
+
+void Writer::onTerminated() {
+ release();
+}
+
+void Writer::sendRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ css::uno::TypeDescription const & type,
+ css::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments, bool currentContextMode,
+ css::uno::UnoInterfaceReference const & currentContext)
+{
+ OSL_ASSERT(tid.getLength() != 0 && oid.getLength() != 0 && member.is());
+ css::uno::TypeDescription t(type);
+ sal_Int32 functionId = 0;
+ bool forceSynchronous = false;
+ member.makeComplete();
+ switch (member.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_InterfaceAttributeTypeDescription * atd =
+ reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
+ member.get());
+ OSL_ASSERT(atd->pInterface != 0);
+ if (!t.is()) {
+ t = css::uno::TypeDescription(&atd->pInterface->aBase);
+ }
+ t.makeComplete();
+ functionId = atd->pInterface->pMapMemberIndexToFunctionIndex[
+ atd->aBase.nPosition];
+ if (!inArguments.empty()) { // setter
+ ++functionId;
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
+ member.get());
+ OSL_ASSERT(mtd->pInterface != 0);
+ if (!t.is()) {
+ t = css::uno::TypeDescription(&mtd->pInterface->aBase);
+ }
+ t.makeComplete();
+ functionId = mtd->pInterface->pMapMemberIndexToFunctionIndex[
+ mtd->aBase.nPosition];
+ forceSynchronous = mtd->bOneWay &&
+ functionId != SPECIAL_FUNCTION_ID_RELEASE;
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ OSL_ASSERT(functionId >= 0);
+ if (functionId > SAL_MAX_UINT16) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("function ID too large for URP")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ std::vector< unsigned char > buf;
+ bool newType = !(lastType_.is() && t.equals(lastType_));
+ bool newOid = oid != lastOid_;
+ bool newTid = tid != lastTid_;
+ if (newType || newOid || newTid || forceSynchronous || functionId > 0x3FFF)
+ // > 14 bit function ID
+ {
+ Marshal::write8(
+ &buf,
+ (0xC0 | (newType ? 0x20 : 0) | (newOid ? 0x10 : 0) |
+ (newTid ? 0x08 : 0) | (functionId > 0xFF ? 0x04 : 0) |
+ (forceSynchronous ? 0x01 : 0)));
+ // bit 7: LONGHEADER, bit 6: REQUEST, bit 5: NEWTYPE, bit 4: NEWOID,
+ // bit 3: NEWTID, bit 2: FUNCTIONID16, bit 0: MOREFLAGS
+ if (forceSynchronous) {
+ Marshal::write8(&buf, 0xC0); // bit 7: MUSTREPLY, bit 6: SYNCHRONOUS
+ }
+ if (functionId <= 0xFF) {
+ Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
+ } else {
+ Marshal::write16(&buf, static_cast< sal_uInt16 >(functionId));
+ }
+ if (newType) {
+ marshal_.writeType(&buf, t);
+ }
+ if (newOid) {
+ marshal_.writeOid(&buf, oid);
+ }
+ if (newTid) {
+ marshal_.writeTid(&buf, tid);
+ }
+ } else if (functionId <= 0x3F) { // <= 6 bit function ID
+ Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
+ // bit 7: !LONGHEADER, bit 6: !FUNCTIONID14
+ } else {
+ Marshal::write8(
+ &buf, static_cast< sal_uInt8 >(0x40 | (functionId >> 8)));
+ // bit 7: !LONGHEADER, bit 6: FUNCTIONID14
+ Marshal::write8(&buf, functionId & 0xFF);
+ }
+ if (currentContextMode) {
+ css::uno::UnoInterfaceReference cc(currentContext);
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference< css::uno::XCurrentContext > >::get()),
+ BinaryAny(
+ css::uno::TypeDescription(
+ cppu::UnoType<
+ css::uno::Reference<
+ css::uno::XCurrentContext > >::get()),
+ &cc.m_pUnoI));
+ }
+ switch (member.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ if (!inArguments.empty()) { // setter
+ OSL_ASSERT(inArguments.size() == 1);
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ member.get())->
+ pAttributeTypeRef),
+ inArguments.front());
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
+ member.get());
+ std::vector< BinaryAny >::const_iterator i(inArguments.begin());
+ for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
+ if (mtd->pParams[j].bIn) {
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
+ *i++);
+ }
+ }
+ OSL_ASSERT(i == inArguments.end());
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ sendMessage(buf);
+ lastType_ = t;
+ lastOid_ = oid;
+ lastTid_ = tid;
+}
+
+void Writer::sendReply(
+ rtl::ByteSequence const & tid,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments)
+{
+ OSL_ASSERT(tid.getLength() != 0 && member.is() && member.get()->bComplete);
+ std::vector< unsigned char > buf;
+ bool newTid = tid != lastTid_;
+ Marshal::write8(&buf, 0x80 | (exception ? 0x20 : 0) | (newTid ? 0x08 : 0));
+ // bit 7: LONGHEADER; bit 6: !REQUEST; bit 5: EXCEPTION; bit 3: NEWTID
+ if (newTid) {
+ marshal_.writeTid(&buf, tid);
+ }
+ if (exception) {
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()),
+ returnValue);
+ } else {
+ switch (member.get()->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ if (!setter) {
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(
+ member.get())->
+ pAttributeTypeRef),
+ returnValue);
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * mtd =
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(
+ member.get());
+ marshal_.writeValue(
+ &buf, css::uno::TypeDescription(mtd->pReturnTypeRef),
+ returnValue);
+ std::vector< BinaryAny >::const_iterator i(
+ outArguments.begin());
+ for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
+ if (mtd->pParams[j].bOut) {
+ marshal_.writeValue(
+ &buf,
+ css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
+ *i++);
+ }
+ }
+ OSL_ASSERT(i == outArguments.end());
+ break;
+ }
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+ sendMessage(buf);
+ lastTid_ = tid;
+ bridge_->decrementCalls();
+}
+
+void Writer::sendMessage(std::vector< unsigned char > const & buffer) {
+ std::vector< unsigned char > header;
+ if (buffer.size() > SAL_MAX_UINT32) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("message too large for URP")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ Marshal::write32(&header, static_cast< sal_uInt32 >(buffer.size()));
+ Marshal::write32(&header, 1);
+ OSL_ASSERT(!buffer.empty());
+ unsigned char const * p = &buffer[0];
+ std::vector< unsigned char >::size_type n = buffer.size();
+ OSL_ASSERT(header.size() <= SAL_MAX_INT32 && SAL_MAX_INT32 <= SAL_MAX_SIZE);
+ sal_Size k = SAL_MAX_INT32 - header.size();
+ if (n < k) {
+ k = static_cast< sal_Size >(n);
+ }
+ css::uno::Sequence< sal_Int8 > s(
+ static_cast< sal_Int32 >(header.size() + k));
+ OSL_ASSERT(!header.empty());
+ rtl_copyMemory(
+ s.getArray(), &header[0], static_cast< sal_Size >(header.size()));
+ for (;;) {
+ rtl_copyMemory(s.getArray() + s.getLength() - k, p, k);
+ try {
+ bridge_->getConnection()->write(s);
+ } catch (css::io::IOException & e) {
+ css::uno::Any exc(cppu::getCaughtException());
+ throw css::lang::WrappedTargetRuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "Binary URP write raised IO exception: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >(), exc);
+ }
+ n = static_cast< std::vector< unsigned char >::size_type >(n - k);
+ if (n == 0) {
+ break;
+ }
+ p += k;
+ k = SAL_MAX_INT32;
+ if (n < k) {
+ k = static_cast< sal_Size >(n);
+ }
+ s.realloc(k);
+ }
+}
+
+}
diff --git a/binaryurp/source/writer.hxx b/binaryurp/source/writer.hxx
new file mode 100644
index 000000000000..fe5dba2cc1d9
--- /dev/null
+++ b/binaryurp/source/writer.hxx
@@ -0,0 +1,185 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_WRITER_HXX
+#define INCLUDED_BINARYURP_SOURCE_WRITER_HXX
+
+#include "sal/config.h"
+
+#include <cstddef>
+#include <deque>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "osl/conditn.hxx"
+#include "osl/mutex.hxx"
+#include "osl/thread.hxx"
+#include "rtl/byteseq.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "salhelper/simplereferenceobject.hxx"
+#include "typelib/typedescription.hxx"
+#include "uno/dispatcher.hxx"
+
+#include "binaryany.hxx"
+#include "marshal.hxx"
+#include "writerstate.hxx"
+
+namespace binaryurp { class Bridge; }
+
+namespace binaryurp {
+
+class Writer:
+ public osl::Thread, public salhelper::SimpleReferenceObject,
+ private boost::noncopyable
+{
+public:
+ static void * operator new(std::size_t size)
+ { return Thread::operator new(size); }
+
+ static void operator delete(void * pointer)
+ { Thread::operator delete(pointer); }
+
+ explicit Writer(rtl::Reference< Bridge > const & bridge);
+
+ // Only called from Bridge::reader_ thread, and only before Bridge::writer_
+ // thread is unblocked:
+ void sendDirectRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type,
+ com::sun::star::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments);
+
+ // Only called from Bridge::reader_ thread, and only before Bridge::writer_
+ // thread is unblocked:
+ void sendDirectReply(
+ rtl::ByteSequence const & tid,
+ com::sun::star::uno::TypeDescription const & member,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments);
+
+ void queueRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type,
+ com::sun::star::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments);
+
+ void queueReply(
+ rtl::ByteSequence const & tid,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments,
+ bool setCurrentContextMode);
+
+ void unblock();
+
+ void stop();
+
+private:
+ virtual ~Writer();
+
+ virtual void SAL_CALL run();
+
+ virtual void SAL_CALL onTerminated();
+
+ void sendRequest(
+ rtl::ByteSequence const & tid, rtl::OUString const & oid,
+ com::sun::star::uno::TypeDescription const & type,
+ com::sun::star::uno::TypeDescription const & member,
+ std::vector< BinaryAny > const & inArguments, bool currentContextMode,
+ com::sun::star::uno::UnoInterfaceReference const & currentContext);
+
+ void sendReply(
+ rtl::ByteSequence const & tid,
+ com::sun::star::uno::TypeDescription const & member, bool setter,
+ bool exception, BinaryAny const & returnValue,
+ std::vector< BinaryAny > const & outArguments);
+
+ void sendMessage(std::vector< unsigned char > const & buffer);
+
+ struct Item {
+ Item();
+
+ // Request:
+ Item(
+ rtl::ByteSequence const & theTid, rtl::OUString const & theOid,
+ com::sun::star::uno::TypeDescription const & theType,
+ com::sun::star::uno::TypeDescription const & theMember,
+ std::vector< BinaryAny > const & inArguments,
+ com::sun::star::uno::UnoInterfaceReference const &
+ theCurrentContext);
+
+ // Reply:
+ Item(
+ rtl::ByteSequence const & theTid,
+ com::sun::star::uno::TypeDescription const & theMember,
+ bool theSetter, bool theException, BinaryAny const & theReturnValue,
+ std::vector< BinaryAny > const & outArguments,
+ bool theSetCurrentContextMode);
+
+ bool request;
+
+ rtl::ByteSequence tid; // request + reply
+
+ rtl::OUString oid; // request
+
+ com::sun::star::uno::TypeDescription type; // request
+
+ com::sun::star::uno::TypeDescription member; // request + reply
+
+ bool setter; // reply
+
+ std::vector< BinaryAny > arguments;
+ // request: inArguments; reply: outArguments
+
+ bool exception; // reply
+
+ BinaryAny returnValue; // reply
+
+ com::sun::star::uno::UnoInterfaceReference currentContext; // request
+
+ bool setCurrentContextMode; // reply
+ };
+
+ rtl::Reference< Bridge > bridge_;
+ WriterState state_;
+ Marshal marshal_;
+ com::sun::star::uno::TypeDescription lastType_;
+ rtl::OUString lastOid_;
+ rtl::ByteSequence lastTid_;
+ osl::Condition unblocked_;
+ osl::Condition items_;
+
+ osl::Mutex mutex_;
+ std::deque< Item > queue_;
+ bool stop_;
+};
+
+}
+
+#endif
diff --git a/binaryurp/source/writerstate.hxx b/binaryurp/source/writerstate.hxx
new file mode 100644
index 000000000000..cbb0208ba019
--- /dev/null
+++ b/binaryurp/source/writerstate.hxx
@@ -0,0 +1,55 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2011 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_BINARYURP_SOURCE_WRITERSTATE_HXX
+#define INCLUDED_BINARYURP_SOURCE_WRITERSTATE_HXX
+
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "rtl/byteseq.hxx"
+#include "rtl/ustring.hxx"
+#include "typelib/typedescription.hxx"
+
+#include "cache.hxx"
+
+namespace binaryurp {
+
+struct WriterState: private boost::noncopyable {
+ WriterState():
+ typeCache(cache::size), oidCache(cache::size), tidCache(cache::size) {}
+
+ Cache< com::sun::star::uno::TypeDescription > typeCache;
+
+ Cache< rtl::OUString > oidCache;
+
+ Cache< rtl::ByteSequence > tidCache;
+};
+
+}
+
+#endif