summaryrefslogtreecommitdiffstats
path: root/cli_ure/source
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /cli_ure/source
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--cli_ure/source/basetypes/assembly.cs21
-rw-r--r--cli_ure/source/basetypes/cli_basetypes_config11
-rw-r--r--cli_ure/source/basetypes/uno/Any.cs202
-rw-r--r--cli_ure/source/basetypes/uno/BoundAttribute.cs37
-rw-r--r--cli_ure/source/basetypes/uno/ExceptionAttribute.cs61
-rw-r--r--cli_ure/source/basetypes/uno/OnewayAttribute.cs34
-rw-r--r--cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs59
-rw-r--r--cli_ure/source/basetypes/uno/PolymorphicType.cs434
-rw-r--r--cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs75
-rw-r--r--cli_ure/source/basetypes/uno/TypeParametersAttribute.cs56
-rw-r--r--cli_ure/source/climaker/climaker_app.cxx675
-rw-r--r--cli_ure/source/climaker/climaker_emit.cxx2279
-rw-r--r--cli_ure/source/climaker/climaker_share.h258
-rw-r--r--cli_ure/source/cliuno.snkbin0 -> 596 bytes
-rw-r--r--cli_ure/source/native/assembly.cxx26
-rw-r--r--cli_ure/source/native/cli_cppuhelper_config11
-rw-r--r--cli_ure/source/native/native_bootstrap.cxx297
-rw-r--r--cli_ure/source/native/native_share.h112
-rw-r--r--cli_ure/source/native/path.cxx48
-rw-r--r--cli_ure/source/scripts/increment_version.pl273
-rw-r--r--cli_ure/source/scripts/subst_template.pl124
-rw-r--r--cli_ure/source/uno_bridge/README.txt20
-rw-r--r--cli_ure/source/uno_bridge/cli_base.h171
-rw-r--r--cli_ure/source/uno_bridge/cli_bridge.cxx321
-rw-r--r--cli_ure/source/uno_bridge/cli_bridge.h113
-rw-r--r--cli_ure/source/uno_bridge/cli_data.cxx1929
-rw-r--r--cli_ure/source/uno_bridge/cli_environment.cxx168
-rw-r--r--cli_ure/source/uno_bridge/cli_environment.h105
-rw-r--r--cli_ure/source/uno_bridge/cli_proxy.cxx1105
-rw-r--r--cli_ure/source/uno_bridge/cli_proxy.h294
-rw-r--r--cli_ure/source/uno_bridge/cli_uno.cxx277
-rw-r--r--cli_ure/source/ure/assembly.cs21
-rw-r--r--cli_ure/source/ure/cli_ure_config11
-rw-r--r--cli_ure/source/ure/uno/util/DisposeGuard.cs50
-rw-r--r--cli_ure/source/ure/uno/util/WeakAdapter.cs111
-rw-r--r--cli_ure/source/ure/uno/util/WeakBase.cs135
-rw-r--r--cli_ure/source/ure/uno/util/WeakComponentBase.cs185
37 files changed, 10109 insertions, 0 deletions
diff --git a/cli_ure/source/basetypes/assembly.cs b/cli_ure/source/basetypes/assembly.cs
new file mode 100644
index 000000000..ac99fffd8
--- /dev/null
+++ b/cli_ure/source/basetypes/assembly.cs
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+[assembly:System.Reflection.AssemblyDescription( "CLI-UNO: Language Binding specific types" )]
+[assembly:System.Reflection.AssemblyCompany( "OpenOffice.org" )]
+[assembly:System.Reflection.AssemblyVersion( "@CLI_BASETYPES_NEW_VERSION@" )]
diff --git a/cli_ure/source/basetypes/cli_basetypes_config b/cli_ure/source/basetypes/cli_basetypes_config
new file mode 100644
index 000000000..44ef60600
--- /dev/null
+++ b/cli_ure/source/basetypes/cli_basetypes_config
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="cli_basetypes" publicKeyToken="ce2cb7e279207b9e"/>
+ <bindingRedirect oldVersion="CLI_BASETYPES_OLD_VERSION" newVersion="CLI_BASETYPES_NEW_VERSION" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/cli_ure/source/basetypes/uno/Any.cs b/cli_ure/source/basetypes/uno/Any.cs
new file mode 100644
index 000000000..ea44d0f3b
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/Any.cs
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using System.Text;
+
+namespace uno
+{
+
+/** This class can be used as a base class for UNO objects.
+ It implements the capability to be kept weakly
+ (unoidl.com.sun.star.uno.XWeak) and it implements
+ unoidl.com.sun.star.lang.XTypeProvider which is necessary for
+ using the object from StarBasic.
+*/
+public struct Any
+{
+ private object _value;
+ private Type _type;
+
+ public static Any VOID = new Any(typeof(void), null);
+
+ private static void checkArgs(Type type, Object value)
+ {
+ //value can only be null if type == void
+ if (type == null
+ || (value == null
+ && type != typeof(void)
+ && type != typeof(object)
+ && type.IsInterface == false))
+ throw new System.Exception(
+ "uno.Any: Constructor called with illegal arguments!");
+ //If value is a polymorphic struct then type must be
+ //uno.Polymorphic
+ if (value != null)
+ {
+ TypeParametersAttribute t = (TypeParametersAttribute) Attribute.GetCustomAttribute(
+ value.GetType(), typeof(TypeParametersAttribute));
+ if (t != null && !(type is PolymorphicType))
+ throw new System.Exception(
+ "uno.Any: The value has a polymorphic type but the type argument is not " +
+ "uno.PolymorphicType. Please use the constructor Any(Type, object) and " +
+ "supply a uno.PolymorphicType as type argument!");
+ }
+ }
+
+ /** constructs an instance.
+
+ <p>If the arguments are invalid then an exception is thrown.</p>
+ @exception System.Exception
+ */
+ public Any(Type type, object value)
+ {
+ checkArgs(type, value);
+ _type = type;
+ _value = value;
+ }
+
+ /** sets the type and value.
+ <p>If the arguments ar invalid then an exception is thrown.</p>
+ @exception System.Exception
+ */
+ public void setValue(Type type, object value)
+ {
+ checkArgs(type, value);
+ _type = type;
+ _value = value;
+ }
+
+ public Type Type
+ {
+ get
+ {
+ if (_type == null)
+ _type = typeof(void);
+ return _type;
+ }
+ }
+
+ public Object Value
+ {
+ get
+ {
+ return _value;
+ }
+ }
+
+ public Any(char value): this(typeof(char), value)
+ {
+ }
+
+ public Any(bool value): this(typeof(bool), value)
+ {
+ }
+
+ public Any(byte value): this(typeof(byte), value)
+ {
+ }
+
+ public Any(short value): this(typeof(short), value)
+ {
+ }
+
+ public Any(ushort value): this(typeof(ushort), value)
+ {
+ }
+
+ public Any(int value): this(typeof(int), value)
+ {
+ }
+
+ public Any(uint value): this(typeof(uint), value)
+ {
+ }
+
+ public Any(long value): this(typeof(long), value)
+ {
+ }
+
+ public Any(ulong value): this(typeof(ulong), value)
+ {
+ }
+
+ public Any(float value): this(typeof(float), value)
+ {
+ }
+
+ public Any(double value): this(typeof(double), value)
+ {
+ }
+
+ public Any(Type value): this(typeof(Type), value)
+ {
+ }
+
+ public Any(string value): this(typeof(string), value)
+ {
+ }
+
+ public override string ToString()
+ {
+ StringBuilder msg = new StringBuilder("uno.Any { Type= ");
+ msg.Append(Type.ToString());
+ msg.Append(", Value=");
+ msg.Append(Value.ToString());
+ msg.Append("}");
+ return msg.ToString();
+ }
+
+ public bool hasValue()
+ {
+ if (Type == null || Type == typeof(void))
+ return false;
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj != null)
+ {
+ try
+ {
+ return Equals((Any) obj);
+ }
+ catch (InvalidCastException)
+ {
+ }
+ }
+ return false;
+ }
+
+ public bool Equals(Any obj)
+ {
+ return Type.Equals(obj.Type)
+ && (Value == null ?
+ obj.Value == null :
+ Value.Equals(obj.Value));
+ }
+
+ public override int GetHashCode()
+ {
+ return Type.GetHashCode() ^ (Value != null ? Value.GetHashCode() : 0);
+ }
+}
+
+}
+
diff --git a/cli_ure/source/basetypes/uno/BoundAttribute.cs b/cli_ure/source/basetypes/uno/BoundAttribute.cs
new file mode 100644
index 000000000..d89925739
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/BoundAttribute.cs
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark UNO interface attributes as &quot;bound&quot.
+
+ <p>It corresponds to <const
+ scope="com::sun::star::beans">PropertyAttribute::BOUND</const>.
+ </p>
+ UNO interface attributes are mapped to CLI properties.
+ */
+[AttributeUsage(AttributeTargets.Property, Inherited=false)]
+public sealed class BoundAttribute: System.Attribute
+{
+}
+
+}
+
diff --git a/cli_ure/source/basetypes/uno/ExceptionAttribute.cs b/cli_ure/source/basetypes/uno/ExceptionAttribute.cs
new file mode 100644
index 000000000..1c8847b44
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/ExceptionAttribute.cs
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark a UNO method to throw exceptions.
+
+ <p>A method can be an ordinary interface method, a get or set method from
+ an interface attribute, or the constructor methods of service creator
+ classes. If there are no exceptions specified for a method then this
+ attribute should not be applied. Because a
+ <type scope="com.sun.star.uno">RuntimeException</type>
+ can always be thrown it is not specified. Hence no
+ <code>ExceptionAttribute</code>
+ should be applied in that case.</p>
+ */
+[AttributeUsage(AttributeTargets.Method, Inherited=false)]
+public sealed class ExceptionAttribute: System.Attribute
+{
+ /** initializes an instance with the specified values.
+
+ @param raises
+ array of types of Exceptions which are declared in UNOIDL.
+ It must not be null.
+ */
+ public ExceptionAttribute(Type[] raises)
+ {
+ m_raises = raises;
+ }
+
+ public Type[] Raises
+ {
+ get
+ {
+ return m_raises;
+ }
+ }
+
+ private Type[] m_raises;
+}
+
+}
+
diff --git a/cli_ure/source/basetypes/uno/OnewayAttribute.cs b/cli_ure/source/basetypes/uno/OnewayAttribute.cs
new file mode 100644
index 000000000..ed8ad85ff
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/OnewayAttribute.cs
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark UNO interface methods as being one - way according to the
+ UNOIDL <code>oneway<code> attribute.
+ <p>
+ */
+[AttributeUsage(AttributeTargets.Method, Inherited=false)]
+public sealed class OnewayAttribute: System.Attribute
+{
+
+}
+}
+
diff --git a/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs b/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs
new file mode 100644
index 000000000..1ff37b280
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/ParameterizedTypeAttribute.cs
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark a UNO entity to have a parameterized type.
+
+ <p>Currently it is only applied to members of polymorphic structs. That is structs,
+ which have a type parameter list.
+ </p>
+
+ @see TypeParametersAttribute
+ */
+[AttributeUsage(AttributeTargets.Field, Inherited=false)]
+public sealed class ParameterizedTypeAttribute: System.Attribute
+{
+ /** initializes an instance with the specified value.
+
+ @param parameter
+ the name of parameter from the parameter list from
+ <type scope="uno.idl">TypeParametersAttribute</type>
+ It must not be null.
+ */
+ public ParameterizedTypeAttribute(string parameter)
+ {
+ m_parameter = parameter;
+ }
+
+ public string Type
+ {
+ get
+ {
+ return m_parameter;
+ }
+ }
+
+ private string m_parameter;
+}
+
+}
+
diff --git a/cli_ure/source/basetypes/uno/PolymorphicType.cs b/cli_ure/source/basetypes/uno/PolymorphicType.cs
new file mode 100644
index 000000000..e996131fc
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/PolymorphicType.cs
@@ -0,0 +1,434 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Globalization;
+
+namespace uno {
+
+
+
+/** represents a polymorphic type.
+
+ This class is used to carry type information for polymorphic struct types
+ and arrays of polymorphic struct types. These types would be easiest represented
+ with type templates, which are not available in .NET 1.1. Therefore
+ the System.Type cannot contain information about template parameters. To
+ retain this information we use PolymorphicType which directly inherits from
+ System.Type. The additional information about type parameters are passed
+ as simple string when creating an instance of PolymorphicType. Usually one
+ only needs a PolymorphicType when a polymporphic type is put into an
+ uno.Any. For example, let's assume there is a idl type PolyStruct:
+
+ module test {
+ struct PolyStruct< T >
+ {
+ T member;
+ };
+ };
+
+ Then one would use it in C# in this way:
+
+ uno.Any myAny = new uno.Any( PolymorphicType.GetType(
+ typeof(PolyStruct), "unoidl.test.PolyStruct<System.Boolean>"),
+ new PolyStruct(true));
+
+ or if one has a sequence of polymorphic structs:
+
+ uno.Any myAny = new uno.Any( PolymorphicType.GetType(
+ typeof(PolyStruct), "unoidl.test.PolyStruct<System.Boolean>[]"),
+ new PolyStruct[] {new PolyStruct(true)} );
+
+
+ To get a new instance of PolymorphicType one uses the static method
+ PolymorphicType.GetType. The method ensures that there is only one instance
+ for each distinct name. For example, if GetType is called multiple times with
+ the name "unoidl.test.PolyStruct<System.Boolean>" then the same instance of
+ PolymorphicType is returned. This makes it possible to compare the instances
+ by reference, thas is using the operator "==".
+
+ The polymorphic name, which is passed as second argument to PolymorphicType.GetType,
+ contains a list of type names. Only type names common
+ to all CLI languages can be used. That is, instead of using names, such as
+ char, int, float, the names System.Char, System.Int32 and
+ System.Single are to be used. Spaces are not allowed.
+ The name will always start with "unoidl", when the type was generated by climaker.
+ Here are a couple of possible strings:
+
+ unoidl.test.PolyStruct<System.Int32>
+ unoidl.test.PolyStruct<System.Char[]>
+ unoidl.test.PolyStruct<System.Int64>[]
+ unoidl.test.PolyStruct<unoidl.test.PolyStruct<System.Int64>>
+ unoidl.test.PolyStruct<unoidl.test.PolyStruct<System.Int64[]>[]>[]
+
+ In the future, when the CLI supports templates, we will probably adapt the cli-uno
+ bridge accordingly to use real template types. Then this class will become obsolete.
+ */
+public class PolymorphicType: Type
+{
+ private Type m_base;
+ private string m_type_name;
+
+ private static Hashtable m_ht_types = Hashtable.Synchronized(new Hashtable(256));
+
+ /** provides a unique instance of this class.
+
+ This function returns null if the specified type is no polymorphic struct.
+
+ @param type
+ the type of the polymorphic struct. For example, created by
+ <code>typeof(unoidl.com.sun.star.beans.Defaulted)</code>
+ @param name
+ the full name of the struct (including the type list).
+ @return
+ null - the argument type is no valid polymorphic struct or <br>
+ an instance of this class.
+ @exception System.ArgumentNullException
+ The argument was null.
+ */
+ public static PolymorphicType GetType(Type type, string name)
+ {
+ if (name == null || type == null)
+ throw new ArgumentNullException(
+ "cli-uno: uno.PolymorphicType.GetType was called with a null argument");
+ //check if the type is either an array of structs or a polymorphic struct.
+ if (type.IsArray)
+ {
+ Type elementType = type;
+ while ((elementType = elementType.GetElementType()).IsArray);
+ //unfortunately we cannot check if it is a real polymorphic struct here.
+ if ( ! elementType.IsClass)
+ return null;
+
+
+ }
+ else if (Attribute.GetCustomAttribute(type, typeof(uno.TypeParametersAttribute))
+ == null)
+ {
+ return null;
+ }
+
+ lock (m_ht_types.SyncRoot)
+ {
+ PolymorphicType t = (PolymorphicType) m_ht_types[name];
+ if (t == null)
+ {
+ t = new PolymorphicType(type, name);
+ m_ht_types.Add(name, t);
+ }
+ return t;
+ }
+ }
+
+ private PolymorphicType(Type type, string name)
+ {
+ m_type_name = name;
+ m_base = type;
+ }
+
+ public string PolymorphicName
+ {
+ get
+ {
+ return m_type_name;
+ }
+ }
+
+ public Type OriginalType
+ {
+ get
+ {
+ return m_base;
+ }
+ }
+
+
+ //implementations of abstract methods and properties from base class
+ public override string Name
+ {
+ get
+ {
+ return m_base.Name;
+ }
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return m_base.Assembly;
+ }
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get
+ {
+ return m_base.AssemblyQualifiedName;
+ }
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ return m_base.BaseType;
+ }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ return m_base.FullName;
+ }
+ }
+
+ public override Guid GUID
+ {
+ get
+ {
+ return m_base.GUID;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return m_base.Module;
+ }
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ return m_base.Namespace;
+ }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return m_base.TypeHandle;
+ }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return m_base.UnderlyingSystemType;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return m_base.DeclaringType;
+ }
+ }
+
+ public override object[] GetCustomAttributes(
+ bool inherit)
+ {
+ return m_base.GetCustomAttributes(inherit);
+ }
+
+ public override object[] GetCustomAttributes(
+ Type attributeType,
+ bool inherit)
+ {
+ return m_base.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined(
+ Type attributeType,
+ bool inherit)
+ {
+ return IsDefined(attributeType, inherit);
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return m_base.Attributes;
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(
+ BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ return m_base.GetConstructor(
+ bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public override ConstructorInfo[] GetConstructors(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetConstructors(bindingAttr);
+ }
+
+ public override Type GetElementType()
+ {
+ return m_base.GetElementType();
+ }
+
+ public override EventInfo GetEvent(
+ string name,
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetEvent(name, bindingAttr);
+ }
+
+ public override EventInfo[] GetEvents(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetEvents(bindingAttr);
+ }
+
+ public override FieldInfo GetField(
+ string name,
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetField(name, bindingAttr);
+ }
+
+ public override FieldInfo[] GetFields(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetFields(bindingAttr);
+ }
+
+ public override Type GetInterface(
+ string name, bool ignoreCase)
+ {
+ return m_base.GetInterface(name, ignoreCase);
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return m_base.GetInterfaces();
+ }
+
+ public override MemberInfo[] GetMembers(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetMembers(bindingAttr);
+ }
+
+ protected override MethodInfo GetMethodImpl(
+ string name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ return m_base.GetMethod(
+ name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public override MethodInfo[] GetMethods(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetMethods(bindingAttr);
+ }
+
+ public override Type GetNestedType(
+ string name, BindingFlags bindingAttr)
+ {
+ return m_base.GetNestedType(name, bindingAttr);
+ }
+
+ public override Type[] GetNestedTypes(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetNestedTypes(bindingAttr);
+ }
+
+ public override PropertyInfo[] GetProperties(
+ BindingFlags bindingAttr)
+ {
+ return m_base.GetProperties(bindingAttr);
+ }
+
+ protected override PropertyInfo GetPropertyImpl(
+ string name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type returnType,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ return m_base.GetProperty(
+ name, bindingAttr, binder, returnType, types, modifiers);
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return m_base.HasElementType;
+ }
+
+ public override object InvokeMember(
+ string name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ object target,
+ object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ string[] namedParameters)
+ {
+ return m_base.InvokeMember(
+ name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return m_base.IsArray;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return m_base.IsByRef;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return m_base.IsCOMObject;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return m_base.IsPointer;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return m_base.IsPrimitive;
+ }
+}
+}
diff --git a/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs b/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs
new file mode 100644
index 000000000..f2e8c8e39
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/TypeArgumentsAttribute.cs
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark a parameterized UNO entity(i.e. struct)
+ to be an instantiation of a
+ template with the specified type arguments.
+
+ <p>Currently only UNO structs can have type parameters.</p>
+
+ <pre>
+
+ [TypeParameters(new string[]{"T"})]
+ struct Foo {
+ [ParameterizedType("T")]
+ Object member;
+ }
+
+ public interface XFoo {
+ [return:TypeArguments(new string[]{typeof(char)})]
+ Foo func( [TypeArguments(new string[]{typeof(char)})] Foo f);
+ }
+ </pre>
+
+ @see TypeParametersAttribute
+ @see ParameterizedTypeAttribute
+ */
+[AttributeUsage(AttributeTargets.ReturnValue
+ | AttributeTargets.Parameter
+ | AttributeTargets.Field, Inherited=false)]
+public sealed class TypeArgumentsAttribute: System.Attribute
+{
+ /** initializes an instance with the specified value.
+
+ @param parameters
+ arrayay of names representing the types.
+ It must not be null.
+ */
+ public TypeArgumentsAttribute(Type[] arguments)
+ {
+ m_arguments = arguments;
+ }
+
+ public Type[] Arguments
+ {
+ get
+ {
+ return m_arguments;
+ }
+ }
+
+ private Type[] m_arguments;
+}
+
+}
+
diff --git a/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs b/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs
new file mode 100644
index 000000000..f6adebaa0
--- /dev/null
+++ b/cli_ure/source/basetypes/uno/TypeParametersAttribute.cs
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+
+
+namespace uno
+{
+/** is used to mark a UNO entity to have type parameters.
+
+ <p>Currently it is only applied with polymorphic structs. That is structs,
+ which have a type parameter list.
+ </p>
+ */
+[AttributeUsage(AttributeTargets.Class, Inherited=false)]
+public sealed class TypeParametersAttribute: System.Attribute
+{
+ /** initializes an instance with the specified value.
+
+ @param parameters
+ array of names representing the types.
+ It must not be null.
+ */
+ public TypeParametersAttribute(string[] parameters)
+ {
+ m_parameters = parameters;
+ }
+
+ public string[] Parameters
+ {
+ get
+ {
+ return m_parameters;
+ }
+ }
+
+ private string[] m_parameters;
+}
+
+}
+
diff --git a/cli_ure/source/climaker/climaker_app.cxx b/cli_ure/source/climaker/climaker_app.cxx
new file mode 100644
index 000000000..7b9bc001a
--- /dev/null
+++ b/cli_ure/source/climaker/climaker_app.cxx
@@ -0,0 +1,675 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "sal/config.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <stdio.h>
+#include <vector>
+
+#include "climaker_share.h"
+
+#include "sal/main.h"
+#include "osl/process.h"
+#include "osl/file.hxx"
+#include "osl/thread.h"
+#include "rtl/ustrbuf.hxx"
+#include "cppuhelper/bootstrap.hxx"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
+#include "com/sun/star/container/XSet.hpp"
+#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "unoidl/unoidl.hxx"
+
+using namespace ::std;
+using namespace ::System::Reflection;
+
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace climaker
+{
+
+
+static char const s_usingText [] =
+"\n"
+"using: climaker <switches> [registry-file-1 registry-file-2 ...]\n"
+"\n"
+"switches:\n"
+" -O, --out <output-file> output assembly file;\n"
+" defaults to cli_unotypes.dll if more than one\n"
+" registry-file is given, else <registry-file>.dll\n"
+" -T, --types types to be generated (if none is given,\n"
+" <type1[;type2;...]> then all types of given registries are emitted\n"
+" -X, --extra <rdb-file> additional rdb to saturate referenced types in\n"
+" given registry file(s); these types will not be\n"
+" emitted into the output assembly file\n"
+" -r, --reference reference metadata from assembly file\n"
+" <assembly-file>\n"
+" -k, --keyfile keyfile needed for strong name\n"
+" --assembly-version <version> sets assembly version\n"
+" --assembly-description <text> sets assembly description text\n"
+" --assembly-product <text> sets assembly product name\n"
+" --assembly-company <text> sets assembly company\n"
+" --assembly-copyright <text> sets assembly copyright\n"
+" --assembly-trademark <text> sets assembly trademark\n"
+" -v, --verbose verbose output to stdout\n"
+" -h, --help this message\n"
+"\n"
+"example: climaker --out cli_mytypes.dll \\\n"
+" --reference cli_uretypes.dll \\\n"
+" --extra types.rdb \\\n"
+" mytypes.rdb\n"
+"\n";
+
+struct OptionInfo
+{
+ char const * m_name;
+ sal_uInt32 m_name_length;
+ sal_Unicode m_short_option;
+ bool m_has_argument;
+};
+
+bool g_bVerbose = false;
+
+
+static const OptionInfo s_option_infos [] = {
+ { RTL_CONSTASCII_STRINGPARAM("out"), 'O', true },
+ { RTL_CONSTASCII_STRINGPARAM("types"), 'T', true },
+ { RTL_CONSTASCII_STRINGPARAM("extra"), 'X', true },
+ { RTL_CONSTASCII_STRINGPARAM("reference"), 'r', true },
+ { RTL_CONSTASCII_STRINGPARAM("keyfile"), 'k', true },
+ { RTL_CONSTASCII_STRINGPARAM("delaySign"), 'd', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-version"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-description"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-product"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-company"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-copyright"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("assembly-trademark"), '\0', true },
+ { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false },
+ { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false }
+};
+
+
+static OptionInfo const * get_option_info(
+ OUString const & opt, sal_Unicode copt = '\0' )
+{
+ for ( sal_Int32 pos = 0;
+ pos < (sizeof (s_option_infos) / sizeof (OptionInfo));
+ ++pos )
+ {
+ OptionInfo const & option_info = s_option_infos[ pos ];
+
+ if (opt.getLength() > 0)
+ {
+ if (opt.equalsAsciiL(
+ option_info.m_name, option_info.m_name_length ) &&
+ (copt == '\0' || copt == option_info.m_short_option))
+ {
+ return &option_info;
+ }
+ }
+ else
+ {
+ OSL_ASSERT( copt != '\0' );
+ if (copt == option_info.m_short_option)
+ {
+ return &option_info;
+ }
+ }
+ }
+ OSL_FAIL(
+ OUStringToOString( opt, osl_getThreadTextEncoding() ).getStr() );
+ return 0;
+}
+
+
+static bool is_option(
+ OptionInfo const * option_info, sal_uInt32 * pIndex )
+{
+ OSL_ASSERT( option_info != 0 );
+ if (osl_getCommandArgCount() <= *pIndex)
+ return false;
+
+ OUString arg;
+ osl_getCommandArg( *pIndex, &arg.pData );
+ sal_Int32 len = arg.getLength();
+
+ if (len < 2 || arg[ 0 ] != '-')
+ return false;
+
+ if (len == 2 && arg[ 1 ] == option_info->m_short_option)
+ {
+ ++(*pIndex);
+ return true;
+ }
+ if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
+ arg.pData->buffer + 2, option_info->m_name ) == 0)
+ {
+ ++(*pIndex);
+ return true;
+ }
+ return false;
+}
+
+
+static inline bool read_option(
+ bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex )
+{
+ bool ret = is_option( option_info, pIndex );
+ if (ret)
+ *flag = true;
+ return ret;
+}
+
+
+static bool read_argument(
+ OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
+{
+ if (is_option( option_info, pIndex ))
+ {
+ if (*pIndex < osl_getCommandArgCount())
+ {
+ osl_getCommandArg( *pIndex, &pValue->pData );
+ ++(*pIndex);
+ return true;
+ }
+ --(*pIndex);
+ }
+ return false;
+}
+
+
+static OUString const & path_get_working_dir()
+{
+ static OUString s_workingDir;
+ if (! s_workingDir.getLength())
+ osl_getProcessWorkingDir( &s_workingDir.pData );
+ return s_workingDir;
+}
+
+
+static OUString path_make_absolute_file_url( OUString const & path )
+{
+ OUString file_url;
+ oslFileError rc = osl_getFileURLFromSystemPath(
+ path.pData, &file_url.pData );
+ if (osl_File_E_None == rc)
+ {
+ OUString abs;
+ rc = osl_getAbsoluteFileURL(
+ path_get_working_dir().pData, file_url.pData, &abs.pData );
+ if (osl_File_E_None == rc)
+ {
+ return abs;
+ }
+ else
+ {
+ throw RuntimeException(
+ "cannot make absolute: " + file_url );
+ }
+ }
+ else
+ {
+ throw RuntimeException(
+ "cannot get file url from system path: " + path );
+ }
+}
+
+}
+
+using namespace ::climaker;
+
+
+SAL_IMPLEMENT_MAIN()
+{
+ sal_uInt32 nCount = osl_getCommandArgCount();
+ if (0 == nCount)
+ {
+ puts( s_usingText );
+ return 0;
+ }
+
+ int ret = 0;
+ css::uno::Reference< XComponentContext > xContext;
+
+ try
+ {
+ OptionInfo const * info_help =
+ get_option_info( "help" );
+ OptionInfo const * info_verbose =
+ get_option_info( "verbose" );
+ OptionInfo const * info_out =
+ get_option_info( "out" );
+ OptionInfo const * info_types =
+ get_option_info( "types" );
+ OptionInfo const * info_reference =
+ get_option_info( "reference" );
+ OptionInfo const * info_extra =
+ get_option_info( "extra" );
+ OptionInfo const * info_keyfile =
+ get_option_info( "keyfile" );
+ OptionInfo const * info_delaySign =
+ get_option_info( "delaySign" );
+ OptionInfo const * info_version =
+ get_option_info( "assembly-version" );
+ OptionInfo const * info_product =
+ get_option_info( "assembly-product" );
+ OptionInfo const * info_description =
+ get_option_info( "assembly-description" );
+ OptionInfo const * info_company =
+ get_option_info( "assembly-company" );
+ OptionInfo const * info_copyright =
+ get_option_info( "assembly-copyright" );
+ OptionInfo const * info_trademark =
+ get_option_info( "assembly-trademark" );
+
+ OUString output;
+ vector< OUString > mandatory_registries;
+ vector< OUString > extra_registries;
+ vector< OUString > extra_assemblies;
+ vector< OUString > explicit_types;
+ OUString version, product, description, company, copyright, trademark,
+ keyfile, delaySign;
+
+ OUString cmd_arg;
+ for ( sal_uInt32 nPos = 0; nPos < nCount; )
+ {
+ // options
+ if (is_option( info_help, &nPos ))
+ {
+ puts( s_usingText );
+ return 0;
+ }
+ else if (read_argument( &cmd_arg, info_types, &nPos ))
+ {
+ sal_Int32 index = 0;
+ do
+ {
+ explicit_types.push_back(
+ cmd_arg.getToken( 0, ';', index ) );
+ }
+ while (index >= 0);
+ }
+ else if (read_argument( &cmd_arg, info_extra, &nPos ))
+ {
+ extra_registries.push_back(
+ path_make_absolute_file_url( cmd_arg ) );
+ }
+ else if (read_argument( &cmd_arg, info_reference, &nPos ))
+ {
+ extra_assemblies.push_back(
+ path_make_absolute_file_url( cmd_arg ) );
+ }
+ else if (!read_option( &g_bVerbose, info_verbose, &nPos ) &&
+ !read_argument( &output, info_out, &nPos ) &&
+ !read_argument( &version, info_version, &nPos ) &&
+ !read_argument( &description, info_description, &nPos ) &&
+ !read_argument( &product, info_product, &nPos ) &&
+ !read_argument( &company, info_company, &nPos ) &&
+ !read_argument( &copyright, info_copyright, &nPos ) &&
+ !read_argument( &trademark, info_trademark, &nPos ) &&
+ !read_argument( &keyfile, info_keyfile, &nPos ) &&
+ !read_argument( &delaySign, info_delaySign, &nPos ))
+ {
+ osl_getCommandArg( nPos, &cmd_arg.pData );
+ ++nPos;
+ cmd_arg = cmd_arg.trim();
+ if (cmd_arg.getLength() > 0)
+ {
+ if (cmd_arg[ 0 ] == '-') // is option
+ {
+ OptionInfo const * option_info = 0;
+ if (cmd_arg.getLength() > 2 &&
+ cmd_arg[ 1 ] == '-')
+ {
+ // long option
+ option_info = get_option_info(
+ cmd_arg.copy( 2 ), '\0' );
+ }
+ else if (cmd_arg.getLength() == 2 &&
+ cmd_arg[ 1 ] != '-')
+ {
+ // short option
+ option_info = get_option_info(
+ OUString(), cmd_arg[ 1 ] );
+ }
+ if (option_info == 0)
+ {
+ throw RuntimeException("unknown option " + cmd_arg + "! Use climaker --help to print all options.");
+ }
+ else
+ {
+ OSL_FAIL( "unhandled valid option?!" );
+ if (option_info->m_has_argument)
+ ++nPos;
+ }
+ }
+ else
+ {
+ mandatory_registries.push_back(
+ path_make_absolute_file_url( cmd_arg ) );
+ }
+ }
+ }
+ }
+
+ // bootstrap uno
+ xContext = ::cppu::defaultBootstrap_InitialComponentContext();
+ css::uno::Reference< container::XHierarchicalNameAccess > xTDmgr(
+ xContext->getValueByName(
+ "/singletons/com.sun.star.reflection."
+ "theTypeDescriptionManager" ),
+ UNO_QUERY_THROW );
+
+ // The registries are consumed twice, once to insert them into the
+ // TypeDescriptionManager so that TypeEmitter can work on
+ // css.star.reflection.XTypeDescription representation, and once
+ // directly as unoidl::Provider instances to keep track which types are
+ // coming from the mandatory registries for the "no explicit types
+ // given" case (which iterates over the full TypeDescriptionManager
+ // now); a welcome clean-up would be to make TypeEmitter work on
+ // unoidl::Entity directly like the other codemakers:
+ css::uno::Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW );
+ rtl::Reference unoidlMgr(new unoidl::Manager);
+ std::vector< rtl::Reference< unoidl::Provider > > unoidlMandatoryProvs;
+ for (auto& rRegistry : extra_registries)
+ {
+ xSet->insert(Any(rRegistry));
+ unoidlMgr->addProvider(rRegistry);
+ }
+ for (auto& rRegistry : mandatory_registries)
+ {
+ xSet->insert(Any(rRegistry));
+ rtl::Reference< unoidl::Provider > prov(unoidlMgr->addProvider(rRegistry));
+ unoidlMandatoryProvs.push_back(prov);
+ }
+
+ if (0 == output.getLength()) // no output file specified
+ {
+ // if only one rdb has been given, then take rdb name
+ if (1 == mandatory_registries.size())
+ {
+ output = mandatory_registries[ 0 ];
+ output = output.copy( output.lastIndexOf( '/' ) +1 );
+ sal_Int32 dot = output.lastIndexOf( '.' );
+ if (dot > 0)
+ output = output.copy( 0, dot );
+ }
+ else
+ {
+ output = "cli_unotypes";
+ }
+ }
+ output = path_make_absolute_file_url( output );
+ sal_Int32 slash = output.lastIndexOf( '/' );
+ OUString sys_output_dir;
+ if (FileBase::E_None != FileBase::getSystemPathFromFileURL(
+ output.copy( 0, slash ), sys_output_dir ))
+ {
+ throw RuntimeException(
+ "cannot get system path from file url " +
+ output.copy( 0, slash ) );
+ }
+ OUString filename( output.copy( slash +1 ) );
+ sal_Int32 dot = filename.lastIndexOf( '.' );
+ OUString name( filename );
+ if (dot < 0) // has no extension
+ filename += ".dll";
+ else
+ name = name.copy( 0, dot );
+ ::System::String ^ output_dir = ustring_to_String( sys_output_dir );
+ ::System::String ^ output_file = ustring_to_String( filename );
+
+ //Get the key pair for making a strong name
+ StrongNameKeyPair^ kp = nullptr;
+ if (keyfile.getLength() > 0)
+ {
+ ::System::String ^ sKeyFile = ustring_to_String(keyfile);
+ try {
+ System::IO::FileStream^ fs = gcnew System::IO::FileStream(
+ sKeyFile, System::IO::FileMode::Open,
+ System::IO::FileAccess::Read, System::IO::FileShare::Read);
+ kp = gcnew StrongNameKeyPair(fs);
+ fs->Close();
+ }
+ catch (System::IO::FileNotFoundException ^ )
+ {
+ throw Exception("Could not find the keyfile. Verify the --keyfile argument!", 0);
+ }
+ }
+ else
+ {
+ if (g_bVerbose)
+ {
+ ::System::Console::Write(
+ "> no key file specified. Cannot create strong name!\n");
+ }
+ }
+ // setup assembly info: xxx todo set more? e.g. avoid strong versioning
+ AssemblyName ^ assembly_name = gcnew AssemblyName();
+ assembly_name->CodeBase = output_dir;
+ assembly_name->Name = gcnew ::System::String(
+ reinterpret_cast<wchar_t const *>(name.getStr()));
+ if (kp != nullptr)
+ assembly_name->KeyPair= kp;
+
+ if (version.getLength() != 0)
+ {
+ assembly_name->Version=
+ gcnew ::System::Version( ustring_to_String( version ) );
+ }
+
+ // app domain
+ ::System::AppDomain ^ current_appdomain =
+ ::System::AppDomain::CurrentDomain;
+
+// Weird warning from this statement
+// warning C4538: 'cli::array<Type> ^' : const/volatile qualifiers on this type are not supported
+// Could be a compiler bug, says http://stackoverflow.com/questions/12151060/seemingly-inappropriate-compilation-warning-with-c-cli
+#pragma warning (push)
+#pragma warning (disable: 4538)
+ // target assembly
+ Emit::AssemblyBuilder ^ assembly_builder =
+ current_appdomain->DefineDynamicAssembly(
+ assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir );
+#pragma warning (pop)
+
+ if (product.getLength() != 0)
+ {
+ cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^> (1);
+ cli::array< ::System::Object^>^args = gcnew cli::array< ::System::Object^>(1);
+ params[ 0 ] = ::System::String::typeid;
+ args[ 0 ] = ustring_to_String( product );
+ assembly_builder->SetCustomAttribute(
+ gcnew Emit::CustomAttributeBuilder(
+ (AssemblyProductAttribute::typeid)->GetConstructor(
+ params ), args ) );
+ }
+ if (description.getLength() != 0)
+ {
+ cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
+ cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
+ params[ 0 ] = ::System::String::typeid;
+ args[ 0 ] = ustring_to_String( description );
+ assembly_builder->SetCustomAttribute(
+ gcnew Emit::CustomAttributeBuilder(
+ (AssemblyDescriptionAttribute::typeid)->GetConstructor(
+ params ), args ) );
+ }
+ if (company.getLength() != 0)
+ {
+ cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
+ cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
+ params[ 0 ] = ::System::String::typeid;
+ args[ 0 ] = ustring_to_String( company );
+ assembly_builder->SetCustomAttribute(
+ gcnew Emit::CustomAttributeBuilder(
+ (AssemblyCompanyAttribute::typeid)->GetConstructor(
+ params ), args ) );
+ }
+ if (copyright.getLength() != 0)
+ {
+ cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
+ cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
+ params[ 0 ] = ::System::String::typeid;
+ args[ 0 ] = ustring_to_String( copyright );
+ assembly_builder->SetCustomAttribute(
+ gcnew Emit::CustomAttributeBuilder(
+ (AssemblyCopyrightAttribute::typeid)->GetConstructor(
+ params ), args ) );
+ }
+ if (trademark.getLength() != 0)
+ {
+ cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
+ cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
+ params[ 0 ] = ::System::String::typeid;
+ args[ 0 ] = ustring_to_String( trademark );
+ assembly_builder->SetCustomAttribute(
+ gcnew Emit::CustomAttributeBuilder(
+ (AssemblyTrademarkAttribute::typeid)->GetConstructor(
+ params ), args ) );
+ }
+
+ // load extra assemblies
+ cli::array<Assembly^>^ assemblies =
+ gcnew cli::array<Assembly^>(extra_assemblies.size());
+ for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos )
+ {
+ assemblies[ pos ] = Assembly::LoadFrom(
+ ustring_to_String( extra_assemblies[ pos ] ) );
+ }
+
+ // type emitter
+ TypeEmitter ^ type_emitter = gcnew TypeEmitter(
+ assembly_builder->DefineDynamicModule( output_file ), assemblies );
+ // add handler resolving assembly's types
+ ::System::ResolveEventHandler ^ type_resolver =
+ gcnew ::System::ResolveEventHandler(
+ type_emitter, &TypeEmitter::type_resolve );
+ current_appdomain->TypeResolve += type_resolver;
+
+ // and emit types to it
+ if (explicit_types.empty())
+ {
+ css::uno::Reference< reflection::XTypeDescriptionEnumeration > xTD_enum(
+ css::uno::Reference< reflection::XTypeDescriptionEnumerationAccess >(
+ xTDmgr, UNO_QUERY_THROW )
+ ->createTypeDescriptionEnumeration(
+ OUString() /* all IDL modules */,
+ Sequence< TypeClass >() /* all classes of types */,
+ reflection::TypeDescriptionSearchDepth_INFINITE ) );
+ while (xTD_enum->hasMoreElements())
+ {
+ css::uno::Reference< reflection::XTypeDescription > td(
+ xTD_enum->nextTypeDescription());
+ OUString name(td->getName());
+ bool bEmit = std::any_of(unoidlMandatoryProvs.begin(), unoidlMandatoryProvs.end(),
+ [&name](rtl::Reference<unoidl::Provider>& rProv) { return rProv->findEntity(name).is(); });
+ if (bEmit) {
+ type_emitter->get_type(td);
+ }
+ }
+ }
+ else
+ {
+ for ( size_t nPos = explicit_types.size(); nPos--; )
+ {
+ type_emitter->get_type(
+ css::uno::Reference< reflection::XTypeDescription >(
+ xTDmgr->getByHierarchicalName( explicit_types[ nPos ] ),
+ UNO_QUERY_THROW ) );
+ }
+ }
+ type_emitter->~TypeEmitter();
+
+ if (g_bVerbose)
+ {
+ ::System::Console::Write(
+ "> saving assembly {0}{1}{2}...",
+ output_dir,
+ gcnew ::System::String(
+ ::System::IO::Path::DirectorySeparatorChar, 1 ),
+ output_file );
+ }
+ assembly_builder->Save( output_file );
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine( "ok." );
+ }
+ current_appdomain->TypeResolve -= type_resolver;
+ }
+ catch (unoidl::NoSuchFileException & e)
+ {
+ std::cerr << "ERROR: No such file <" << e.getUri() << ">\n";
+ return EXIT_FAILURE;
+ }
+ catch (unoidl::FileFormatException & e)
+ {
+ std::cerr
+ << "ERROR: Bad format of <" << e.getUri() << ">, \""
+ << e.getDetail() << "\"\n";
+ return EXIT_FAILURE;
+ }
+ catch (Exception & exc)
+ {
+ OString msg(
+ OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
+ fprintf(
+ stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() );
+ ret = 1;
+ }
+ catch (::System::Exception ^ exc)
+ {
+ OString msg( OUStringToOString(
+ String_to_ustring( exc->ToString() ),
+ osl_getThreadTextEncoding() ) );
+ fprintf(
+ stderr,
+ "\n> error: .NET exception occurred: %s\n> dying abnormally...",
+ msg.getStr() );
+ ret = 1;
+ }
+
+ try
+ {
+ css::uno::Reference< lang::XComponent > xComp( xContext, UNO_QUERY );
+ if (xComp.is())
+ xComp->dispose();
+ }
+ catch (Exception & exc)
+ {
+ OString msg(
+ OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
+ fprintf(
+ stderr,
+ "\n> error disposing component context: %s\n"
+ "> dying abnormally...\n",
+ msg.getStr() );
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/climaker/climaker_emit.cxx b/cli_ure/source/climaker/climaker_emit.cxx
new file mode 100644
index 000000000..e34a9b088
--- /dev/null
+++ b/cli_ure/source/climaker/climaker_emit.cxx
@@ -0,0 +1,2279 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "climaker_share.h"
+
+#include "rtl/string.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
+#include "com/sun/star/reflection/XStructTypeDescription.hpp"
+#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
+#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
+#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp"
+#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
+#include <vector>
+
+using namespace ::System::Reflection;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace climaker
+{
+System::String^ mapUnoPolymorphicName(System::String^ unoName);
+
+static inline ::System::String ^ to_cts_name(
+ OUString const & uno_name )
+{
+ return ustring_to_String("unoidl." + uno_name);
+}
+
+
+static inline ::System::Object ^ to_cli_constant( Any const & value )
+{
+ switch (value.getValueTypeClass())
+ {
+ case TypeClass_CHAR:
+ return ((::System::Char) *reinterpret_cast< sal_Unicode const * >(
+ value.getValue() ));
+ case TypeClass_BOOLEAN:
+ return ((::System::Boolean)
+ sal_False != *reinterpret_cast< sal_Bool const * >(
+ value.getValue() ));
+ case TypeClass_BYTE:
+ return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
+ value.getValue() ));
+ case TypeClass_SHORT:
+ return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
+ value.getValue() ));
+ case TypeClass_UNSIGNED_SHORT:
+ return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
+ value.getValue() ));
+ case TypeClass_LONG:
+ return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
+ value.getValue() ));
+ case TypeClass_UNSIGNED_LONG:
+ return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
+ value.getValue() ));
+ case TypeClass_HYPER:
+ return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
+ value.getValue() ));
+ case TypeClass_UNSIGNED_HYPER:
+ return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
+ value.getValue() ));
+ case TypeClass_FLOAT:
+ return ((::System::Single) *reinterpret_cast< float const * >(
+ value.getValue() ));
+ case TypeClass_DOUBLE:
+ return ((::System::Double) *reinterpret_cast< double const * >(
+ value.getValue() ));
+ default:
+ throw RuntimeException(
+ "unexpected constant type " +
+ value.getValueType().getTypeName() );
+ }
+}
+
+
+static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
+{
+ switch (index)
+ {
+ case 0:
+#pragma warning (push)
+#pragma warning (disable: 4538) // const/volatile qualifiers on this type are not supported
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+#pragma warning (pop)
+ break;
+ case 1:
+ code->Emit( Emit::OpCodes::Ldarg_1 );
+ break;
+ case 2:
+ code->Emit( Emit::OpCodes::Ldarg_2 );
+ break;
+ case 3:
+ code->Emit( Emit::OpCodes::Ldarg_3 );
+ break;
+ default:
+ if (index < 0x100)
+ code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index );
+ else if (index < 0x8000)
+ code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index );
+ else
+ code->Emit( Emit::OpCodes::Ldarg, index );
+ break;
+ }
+}
+
+void polymorphicStructNameToStructName(::System::String ^* sPolyName)
+{
+ if ((*sPolyName)->EndsWith(">") == false)
+ return;
+
+ int index = (*sPolyName)->IndexOf('<');
+ OSL_ASSERT(index != -1);
+ *sPolyName = (*sPolyName)->Substring(0, index);
+}
+
+
+System::String^ mapUnoTypeName(System::String ^ typeName)
+{
+ ::System::Text::StringBuilder^ buf= gcnew System::Text::StringBuilder();
+ ::System::String ^ sUnoName = ::System::String::Copy(typeName);
+ //determine if the type is a sequence and its dimensions
+ int dims= 0;
+ if (typeName->StartsWith("["))//if (usUnoName[0] == '[')
+ {
+ int index= 1;
+ while (true)
+ {
+ if (typeName[index++] == ']')//if (usUnoName[index++] == ']')
+ dims++;
+ if (typeName[index++] != '[')//usUnoName[index++] != '[')
+ break;
+ }
+ sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
+ }
+ if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoBool)))
+ buf->Append(const_cast<System::String^>(Constants::sBoolean));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoChar)))
+ buf->Append(const_cast<System::String^>(Constants::sChar));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoByte)))
+ buf->Append(const_cast<System::String^>(Constants::sByte));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoShort)))
+ buf->Append(const_cast<System::String^>(Constants::sInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUShort)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoLong)))
+ buf->Append(const_cast<System::String^>(Constants::sInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoULong)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoFloat)))
+ buf->Append(const_cast<System::String^>(Constants::sSingle));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoDouble)))
+ buf->Append(const_cast<System::String^>(Constants::sDouble));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoString)))
+ buf->Append(const_cast<System::String^>(Constants::sString));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoVoid)))
+ buf->Append(const_cast<System::String^>(Constants::sVoid));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoType)))
+ buf->Append(const_cast<System::String^>(Constants::sType));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoXInterface)))
+ buf->Append(const_cast<System::String^>(Constants::sObject));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoAny)))
+ {
+ buf->Append(const_cast<System::String^>(Constants::sAny));
+ }
+ else
+ {
+ //put "unoidl." at the beginning
+ buf->Append(const_cast<System::String^>(Constants::sUnoidl));
+ buf->Append(mapUnoPolymorphicName(sUnoName));
+ }
+ // append []
+ for (;dims--;)
+ buf->Append(const_cast<System::String^>(Constants::sBrackets));
+
+ return buf->ToString();
+}
+
+
+/** For example, there is a uno type
+ com.sun.star.Foo<char, long>.
+ The values in the type list
+ are uno types and are replaced by cli types, such as System.Char,
+ System.Int32, etc.
+
+ Strings can be as complicated as this
+ test.MyStruct<char,test.MyStruct<long, []string>>
+ */
+System::String^ mapUnoPolymorphicName(System::String^ unoName)
+{
+ int index = unoName->IndexOf('<');
+ if (index == -1)
+ return unoName;
+
+ System::Text::StringBuilder ^ builder =
+ gcnew System::Text::StringBuilder(unoName->Substring(0, index +1 ));
+
+ //Find the first occurrence of ','
+ //If the parameter is a polymorphic struct then we need to ignore everything
+ //between the brackets because it can also contain commas
+ //get the type list within < and >
+ int endIndex = unoName->Length - 1;
+ index++;
+ int cur = index;
+ int countParams = 0;
+ while (cur <= endIndex)
+ {
+ System::Char c = unoName[cur];
+ if (c == ',' || c == '>')
+ {
+ //insert a comma if needed
+ if (countParams != 0)
+ builder->Append(",");
+ countParams++;
+ System::String ^ sParam = unoName->Substring(index, cur - index);
+ //skip the comma
+ cur++;
+ //the index to the beginning of the next param
+ index = cur;
+ builder->Append(mapUnoTypeName(sParam));
+ }
+ else if (c == '<')
+ {
+ cur++;
+ //continue until the matching '>'
+ int numNested = 0;
+ for (;;cur++)
+ {
+ System::Char curChar = unoName[cur];
+ if (curChar == '<')
+ {
+ numNested ++;
+ }
+ else if (curChar == '>')
+ {
+ if (numNested > 0)
+ numNested--;
+ else
+ break;
+ }
+ }
+ }
+ cur++;
+ }
+
+ builder->Append((System::Char) '>');
+ return builder->ToString();
+}
+
+
+Assembly ^ TypeEmitter::type_resolve(
+ ::System::Object ^, ::System::ResolveEventArgs ^ args )
+{
+ ::System::String ^ cts_name = args->Name;
+ ::System::Type ^ ret_type = nullptr;
+
+ iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] );
+ if (nullptr != entry)
+ ret_type = entry->m_type_builder;
+
+ if (nullptr == ret_type)
+ {
+ sal_Int32 len = m_extra_assemblies->Length;
+ for ( sal_Int32 pos = 0; pos < len; ++pos )
+ {
+ ret_type = m_extra_assemblies[ pos ]->GetType(
+ cts_name, false /* no exc */ );
+ if (nullptr != ret_type)
+ {
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> resolving type {0} from {1}.",
+ cts_name, ret_type->Assembly->FullName );
+ }
+ break;
+ }
+ }
+ }
+ if (nullptr != ret_type)
+ return ret_type->Assembly;
+ return nullptr;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ ::System::String ^ cts_name, bool throw_exc )
+{
+ ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false );
+ //We get the type from the ModuleBuilder even if the type is not complete
+ //but have been defined.
+ //if (ret_type == 0)
+ //{
+ // iface_entry * entry = dynamic_cast< iface_entry * >(
+ // m_incomplete_ifaces->get_Item( cts_name ) );
+ // if (0 != entry)
+ // ret_type = entry->m_type_builder;
+ //}
+ //try the cli_basetypes assembly
+ if (ret_type == nullptr)
+ {
+ ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
+ builder->Append(",cli_basetypes");
+ ret_type = ::System::Type::GetType(builder->ToString());
+ }
+
+ if (ret_type == nullptr)
+ {
+ try
+ {
+ // may call on type_resolve()
+ return ::System::Type::GetType( cts_name, throw_exc );
+ }
+ catch (::System::Exception^ exc)
+ {
+ //If the type is not found one may have forgotten to specify assemblies with
+ //additional types
+ ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
+ sb->Append(gcnew ::System::String("\nThe type "));
+ sb->Append(cts_name);
+ sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to "
+ "specify an additional assembly with the --reference option?\n"));
+ if (throw_exc)
+ throw gcnew ::System::Exception(sb->ToString(), exc);
+ }
+ }
+ else
+ {
+ return ret_type;
+ }
+}
+
+
+::System::Type ^ TypeEmitter::get_type_Exception()
+{
+ if (nullptr == m_type_Exception)
+ {
+ m_type_Exception = get_type(
+ "unoidl.com.sun.star.uno.Exception", false /* no exc */ );
+ if (nullptr == m_type_Exception)
+ {
+ // define hardcoded type unoidl.com.sun.star.uno.Exception
+ Emit::TypeBuilder ^ type_builder =
+ m_module_builder->DefineType(
+ "unoidl.com.sun.star.uno.Exception",
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass),
+ (::System::Exception::typeid) );
+ Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
+ "Context", (::System::Object::typeid),
+ FieldAttributes::Public );
+ // default .ctor
+ type_builder->DefineDefaultConstructor( c_ctor_method_attr );
+ // .ctor
+ array< ::System::Type^>^ param_types =
+ gcnew array< ::System::Type^>(2);
+ param_types[ 0 ] = ::System::String::typeid;
+ param_types[ 1 ] = ::System::Object::typeid;
+ Emit::ConstructorBuilder ^ ctor_builder =
+ type_builder->DefineConstructor(
+ c_ctor_method_attr, CallingConventions::Standard,
+ param_types );
+ ctor_builder->DefineParameter(
+ 1, ParameterAttributes::In, "Message" );
+ ctor_builder->DefineParameter(
+ 2, ParameterAttributes::In, "Context" );
+ Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldarg_1 );
+ param_types = gcnew array< ::System::Type^>(1);
+ param_types[ 0 ] = ::System::String::typeid;
+ code->Emit(
+ Emit::OpCodes::Call,
+ (::System::Exception::typeid)
+ ->GetConstructor( param_types ) );
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldarg_2 );
+ code->Emit( Emit::OpCodes::Stfld, field_Context );
+ code->Emit( Emit::OpCodes::Ret );
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting exception type "
+ "unoidl.com.sun.star.uno.Exception" );
+ }
+ m_type_Exception = type_builder->CreateType();
+ }
+ }
+ return m_type_Exception;
+}
+
+
+::System::Type ^ TypeEmitter::get_type_RuntimeException()
+{
+ if (nullptr == m_type_RuntimeException)
+ {
+ m_type_RuntimeException = get_type(
+ "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ );
+ if (nullptr == m_type_RuntimeException)
+ {
+ // define hardcoded type unoidl.com.sun.star.uno.RuntimeException
+ ::System::Type ^ type_Exception = get_type_Exception();
+ Emit::TypeBuilder ^ type_builder =
+ m_module_builder->DefineType(
+ "unoidl.com.sun.star.uno.RuntimeException",
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass),
+ type_Exception );
+ // default .ctor
+ type_builder->DefineDefaultConstructor( c_ctor_method_attr );
+ // .ctor
+ array< ::System::Type^>^ param_types =
+ gcnew array< ::System::Type^>(2);
+ param_types[ 0 ] = ::System::String::typeid;
+ param_types[ 1 ] = ::System::Object::typeid;
+ Emit::ConstructorBuilder ^ ctor_builder =
+ type_builder->DefineConstructor(
+ c_ctor_method_attr, CallingConventions::Standard,
+ param_types );
+ ctor_builder->DefineParameter(
+ 1, ParameterAttributes::In, "Message" );
+ ctor_builder->DefineParameter(
+ 2, ParameterAttributes::In, "Context" );
+ Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldarg_1 );
+ code->Emit( Emit::OpCodes::Ldarg_2 );
+ code->Emit(
+ Emit::OpCodes::Call,
+ type_Exception->GetConstructor( param_types ) );
+ code->Emit( Emit::OpCodes::Ret );
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting exception type "
+ "unoidl.com.sun.star.uno.RuntimeException" );
+ }
+ m_type_RuntimeException = type_builder->CreateType();
+ }
+ }
+ return m_type_RuntimeException;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XConstantTypeDescription > const & xType )
+{
+ ::System::String ^ cts_name = to_cts_name( xType->getName() );
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (nullptr == ret_type)
+ {
+ Reference< reflection::XConstantTypeDescription > xConstant(
+ xType, UNO_SET_THROW );
+ ::System::Object ^ constant =
+ to_cli_constant( xConstant->getConstantValue() );
+ Emit::TypeBuilder ^ type_builder =
+ m_module_builder->DefineType(
+ cts_name,
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::Sealed |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass) );
+
+ Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
+ cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ),
+ constant->GetType(),
+ (FieldAttributes) (FieldAttributes::Public |
+ FieldAttributes::Static |
+ FieldAttributes::Literal) );
+ field_builder->SetConstant( constant );
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting constant type {0}", cts_name );
+ }
+ ret_type = type_builder->CreateType();
+ }
+ return ret_type;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XConstantsTypeDescription > const & xType )
+{
+ ::System::String ^ cts_name = to_cts_name( xType->getName() );
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (nullptr == ret_type)
+ {
+ Emit::TypeBuilder ^ type_builder =
+ m_module_builder->DefineType(
+ cts_name,
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::Sealed |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass) );
+
+ Sequence< Reference<
+ reflection::XConstantTypeDescription > > seq_constants(
+ xType->getConstants() );
+ Reference< reflection::XConstantTypeDescription > const * constants =
+ seq_constants.getConstArray();
+ sal_Int32 constants_length = seq_constants.getLength();
+ for ( sal_Int32 constants_pos = 0;
+ constants_pos < constants_length; ++constants_pos )
+ {
+ Reference<
+ reflection::XConstantTypeDescription > const & xConstant =
+ constants[ constants_pos ];
+ ::System::Object ^ constant =
+ to_cli_constant( xConstant->getConstantValue() );
+ ::System::String ^ uno_name =
+ ustring_to_String( xConstant->getName() );
+ Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
+ uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
+ constant->GetType(),
+ (FieldAttributes) (FieldAttributes::Public |
+ FieldAttributes::Static |
+ FieldAttributes::Literal) );
+ field_builder->SetConstant( constant );
+ }
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting constants group type {0}", cts_name );
+ }
+ ret_type = type_builder->CreateType();
+ }
+ return ret_type;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XEnumTypeDescription > const & xType )
+{
+ ::System::String ^ cts_name = to_cts_name( xType->getName() );
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (nullptr == ret_type)
+ {
+ // workaround enum builder bug
+ Emit::TypeBuilder ^ enum_builder =
+ m_module_builder->DefineType(
+ cts_name,
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::Sealed),
+ ::System::Enum::typeid );
+ enum_builder->DefineField(
+ "value__", ::System::Int32::typeid,
+ (FieldAttributes) (FieldAttributes::Private |
+ FieldAttributes::SpecialName |
+ FieldAttributes::RTSpecialName) );
+ Sequence< OUString > seq_enum_names( xType->getEnumNames() );
+ Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
+ sal_Int32 enum_length = seq_enum_names.getLength();
+ OSL_ASSERT( enum_length == seq_enum_values.getLength() );
+ OUString const * enum_names = seq_enum_names.getConstArray();
+ sal_Int32 const * enum_values = seq_enum_values.getConstArray();
+ for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
+ {
+// enum_builder->DefineLiteral(
+// ustring_to_String( enum_names[ enum_pos ] ),
+// __box ((::System::Int32) enum_values[ enum_pos ]) );
+ Emit::FieldBuilder ^ field_builder =
+ enum_builder->DefineField(
+ ustring_to_String( enum_names[ enum_pos ] ),
+ enum_builder,
+ (FieldAttributes) (FieldAttributes::Public |
+ FieldAttributes::Static |
+ FieldAttributes::Literal) );
+ field_builder->SetConstant(
+ ((::System::Int32) enum_values[ enum_pos ]) );
+ }
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting enum type {0}", cts_name );
+ }
+ ret_type = enum_builder->CreateType();
+ }
+ return ret_type;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XCompoundTypeDescription > const & xType )
+{
+ OUString uno_name( xType->getName() );
+ if (TypeClass_EXCEPTION == xType->getTypeClass())
+ {
+ if ( uno_name == "com.sun.star.uno.Exception" )
+ {
+ return get_type_Exception();
+ }
+ if ( uno_name == "com.sun.star.uno.RuntimeException" )
+ {
+ return get_type_RuntimeException();
+ }
+ }
+ ::System::String ^ cts_name = to_cts_name( uno_name );
+ // if the struct is an instantiated polymorphic struct then we create the simple struct name
+ // For example:
+ // void func ([in] PolyStruct<boolean> arg);
+ //PolyStruct<boolean> will be converted to PolyStruct
+ polymorphicStructNameToStructName( & cts_name);
+
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (nullptr == ret_type)
+ {
+ Reference< reflection::XCompoundTypeDescription > xBaseType(
+ xType->getBaseType(), UNO_QUERY );
+ ::System::Type ^ base_type = (xBaseType.is()
+ ? get_type( xBaseType )
+ : ::System::Object::typeid);
+ Emit::TypeBuilder ^ type_builder =
+ m_module_builder->DefineType(
+ cts_name,
+ (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass),
+ base_type );
+
+
+ // insert to be completed
+ struct_entry ^ entry = gcnew struct_entry();
+ xType->acquire();
+ entry->m_xType = xType.get();
+ entry->m_type_builder = type_builder;
+ entry->m_base_type = base_type;
+ m_incomplete_structs->Add( cts_name, entry );
+
+ // type is incomplete
+ ret_type = type_builder;
+ }
+
+ //In case of an instantiated polymorphic struct we want to return a
+ //uno.PolymorphicType (inherits Type) rather than Type. This is needed for constructing
+ //the service code. We can only do that if the struct is completed.
+ if (m_generated_structs[cts_name])
+ {
+ Reference< reflection::XStructTypeDescription> xStructTypeDesc(
+ xType, UNO_QUERY);
+
+ if (xStructTypeDesc.is())
+ {
+ Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
+ sal_Int32 numTypes = seqTypeArgs.getLength();
+ if (numTypes > 0)
+ {
+ //it is an instantiated polymorphic struct
+ ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
+ ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
+ }
+ }
+ }
+ return ret_type;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XInterfaceTypeDescription2 > const & xType )
+{
+ OUString uno_name( xType->getName() );
+ if ( uno_name == "com.sun.star.uno.XInterface" )
+ {
+ return ::System::Object::typeid;
+ }
+
+ ::System::String ^ cts_name = to_cts_name( xType->getName() );
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (nullptr == ret_type)
+ {
+ Emit::TypeBuilder ^ type_builder;
+
+ TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::Interface |
+ TypeAttributes::Abstract |
+ TypeAttributes::AnsiClass);
+
+ std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
+ Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
+ xType->getBaseTypes();
+ if (seqBaseTypes.getLength() > 0)
+ {
+ for (int i = 0; i < seqBaseTypes.getLength(); i++)
+ {
+ Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
+ resolveInterfaceTypedef(seqBaseTypes[i]);
+
+ if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" )
+ {
+ vecBaseTypes.push_back(xIfaceTd);
+ }
+ }
+
+ array< ::System::Type^>^ base_interfaces =
+ gcnew array< ::System::Type^>( vecBaseTypes.size() );
+
+ int index = 0;
+ for (auto const & vecBaseType : vecBaseTypes)
+ {
+ base_interfaces[ index ] = get_type( vecBaseType );
+ ++index;
+ }
+ type_builder = m_module_builder->DefineType(
+ cts_name, attr, nullptr, base_interfaces );
+ }
+ else
+ {
+ ::System::Console::WriteLine(
+ "warning: IDL interface {0} is not derived from "
+ "com.sun.star.uno.XInterface!",
+ ustring_to_String( uno_name ) );
+
+ type_builder = m_module_builder->DefineType( cts_name, attr );
+ }
+
+ // insert to be completed
+ iface_entry ^ entry = gcnew iface_entry();
+ xType->acquire();
+ entry->m_xType = xType.get();
+ entry->m_type_builder = type_builder;
+ m_incomplete_ifaces->Add( cts_name, entry );
+
+ // type is incomplete
+ ret_type = type_builder;
+ }
+ return ret_type;
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XServiceTypeDescription2 > const & xType )
+{
+ if (xType->isSingleInterfaceBased() == sal_False)
+ return nullptr;
+
+ System::String ^ cts_name = to_cts_name( xType->getName() );
+ System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (ret_type != nullptr)
+ return ret_type;
+
+ TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
+ TypeAttributes::Sealed |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass);
+
+ Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
+ cts_name, attr);
+
+ // insert to be completed
+ service_entry ^ entry = gcnew service_entry();
+ xType->acquire();
+ entry->m_xType = xType.get();
+ entry->m_type_builder = type_builder;
+ m_incomplete_services->Add(cts_name,entry );
+
+ return type_builder;
+}
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference<reflection::XSingletonTypeDescription2 > const & xType )
+{
+ if (xType->isInterfaceBased() == sal_False)
+ return nullptr;
+
+ ::System::String^ cts_name = to_cts_name( xType->getName() );
+ ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
+ if (ret_type != nullptr)
+ return ret_type;
+
+ TypeAttributes attr = static_cast<TypeAttributes>(
+ TypeAttributes::Public |
+ TypeAttributes::Sealed |
+ TypeAttributes::BeforeFieldInit |
+ TypeAttributes::AnsiClass);
+
+ Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
+ cts_name, attr);
+
+ // insert to be completed
+ singleton_entry ^ entry = gcnew singleton_entry();
+ xType->acquire();
+ entry->m_xType = xType.get();
+ entry->m_type_builder = type_builder;
+ m_incomplete_singletons->Add(cts_name,entry );
+
+ return type_builder;
+
+}
+
+
+::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
+{
+ Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
+ reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
+
+ Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
+ if (seqBaseTypes.getLength() > 0)
+ {
+ for (int i = 0; i < seqBaseTypes.getLength(); i++)
+ {
+ //make sure we get the interface rather than a typedef
+ Reference<reflection::XInterfaceTypeDescription2> aBaseType =
+ resolveInterfaceTypedef( seqBaseTypes[i]);
+
+ if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
+ {
+ ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
+ iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
+ m_incomplete_ifaces[basetype_name] );
+ if (nullptr != base_entry)
+ {
+ // complete uncompleted base type first
+ complete_iface_type( base_entry );
+ }
+ }
+ }
+ }
+
+ Sequence<
+ Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
+ xType->getMembers() );
+ Reference< reflection::XInterfaceMemberTypeDescription > const * members =
+ seq_members.getConstArray();
+ sal_Int32 members_length = seq_members.getLength();
+ for ( sal_Int32 members_pos = 0;
+ members_pos < members_length; ++members_pos )
+ {
+ Reference<
+ reflection::XInterfaceMemberTypeDescription > const & xMember =
+ members[ members_pos ];
+ Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
+ Emit::MethodBuilder ^ method_builder;
+
+ MethodAttributes c_method_attr = (MethodAttributes)
+ (MethodAttributes::Public |
+ MethodAttributes::Abstract |
+ MethodAttributes::Virtual |
+ MethodAttributes::NewSlot |
+ MethodAttributes::HideBySig);
+
+ if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
+ {
+ Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
+ xMember, UNO_QUERY_THROW );
+
+ Sequence<
+ Reference< reflection::XMethodParameter > > seq_parameters(
+ xMethod->getParameters() );
+ sal_Int32 params_length = seq_parameters.getLength();
+ array< ::System::Type^>^ param_types =
+ gcnew array< ::System::Type^>( params_length );
+ Reference< reflection::XMethodParameter > const * parameters =
+ seq_parameters.getConstArray();
+ // first determine all types
+ //Make the first param type as return type
+ sal_Int32 params_pos = 0;
+ for ( ; params_pos < params_length; ++params_pos )
+ {
+ Reference< reflection::XMethodParameter > const & xParam =
+ parameters[ params_pos ];
+ ::System::Type ^ param_type = get_type( xParam->getType() );
+ ::System::String ^ param_type_name = param_type->FullName;
+ if (xParam->isOut())
+ {
+ param_type = get_type(
+ ::System::String::Concat(
+ param_type_name, "&" ), true );
+ }
+ param_types[ xParam->getPosition() ] = param_type;
+ }
+
+
+ // create method
+// if (tb)
+// method_builder = type_builder->DefineMethod(
+// ustring_to_String( xMethod->getMemberName() ),
+// c_method_attr, tb,
+// param_types );
+// else
+ method_builder = type_builder->DefineMethod(
+ ustring_to_String( xMethod->getMemberName() ),
+ c_method_attr, get_type( xMethod->getReturnType() ),
+ param_types );
+ // then define parameter infos
+ params_pos = 0;
+ for ( ; params_pos < params_length; ++params_pos )
+ {
+ Reference< reflection::XMethodParameter > const & xParam =
+ parameters[ params_pos ];
+ long param_flags = 0;
+ if (xParam->isIn())
+ param_flags |= (long)ParameterAttributes::In;
+ if (xParam->isOut())
+ param_flags |= (long)ParameterAttributes::Out;
+ OSL_ASSERT( 0 != param_flags );
+ method_builder->DefineParameter(
+ xParam->getPosition() +1 /* starts with 1 */,
+ (ParameterAttributes) param_flags,
+ ustring_to_String( xParam->getName() ) );
+ }
+ //Apply attribute TypeParametersAttribute to return value if it
+ //is a parameterized Type. Currently only structs can have parameters.
+ Reference<reflection::XStructTypeDescription> xReturnStruct(
+ xMethod->getReturnType(), UNO_QUERY);
+
+ if (xReturnStruct.is())
+ {
+ Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
+ xReturnStruct->getTypeArguments();
+ if (seq_type_args.getLength() != 0)
+ {
+ //get th ctor of the attribute
+ array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
+ //Get the arguments for the attribute's ctor
+ Reference<reflection::XTypeDescription> const * arXTypeArgs =
+ seq_type_args.getConstArray();
+ int numTypes = seq_type_args.getLength();
+ array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
+ for (int i = 0; i < numTypes; i++)
+ arCtsTypes[i] = get_type(arXTypeArgs[i]);
+ array< ::System::Object^>^ arArgs = {arCtsTypes};
+
+ Emit::CustomAttributeBuilder ^ attrBuilder =
+ gcnew Emit::CustomAttributeBuilder(
+ ::uno::TypeArgumentsAttribute::typeid
+ ->GetConstructor( arCtor),
+ arArgs);
+
+ method_builder->SetCustomAttribute(attrBuilder);
+ }
+ }
+
+ //define UNO exception attribute (exceptions)--------------------------------------
+ Emit::CustomAttributeBuilder^ attrBuilder =
+ get_iface_method_exception_attribute(xMethod);
+ if (attrBuilder != nullptr)
+ method_builder->SetCustomAttribute(attrBuilder);
+
+ // oneway attribute
+ if (xMethod->isOneway())
+ {
+ array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
+ array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
+ Emit::CustomAttributeBuilder ^ attrBuilder =
+ gcnew Emit::CustomAttributeBuilder(
+ ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
+ arArgs);
+ method_builder->SetCustomAttribute(attrBuilder);
+ }
+ }
+ else // attribute
+ {
+ OSL_ASSERT(
+ TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
+ Reference<
+ reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
+ xMember, UNO_QUERY_THROW );
+
+ MethodAttributes c_property_method_attr = (MethodAttributes)
+ (c_method_attr | MethodAttributes::SpecialName);
+
+ ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
+ array< ::System::Type^>^ parameters =
+ gcnew array< ::System::Type^> ( 0 );
+
+ Emit::PropertyBuilder ^ property_builder =
+ type_builder->DefineProperty(
+ ustring_to_String( xAttribute->getMemberName() ),
+ PropertyAttributes::None,
+ attribute_type, parameters );
+
+ //set BoundAttribute, if necessary
+ if (xAttribute->isBound())
+ {
+ ConstructorInfo ^ ctorBoundAttr =
+ ::uno::BoundAttribute::typeid->GetConstructor(
+ gcnew array<System::Type^>(0));
+ Emit::CustomAttributeBuilder ^ attrBuilderBound =
+ gcnew Emit::CustomAttributeBuilder(
+ ctorBoundAttr, gcnew array< ::System::Object^>(0));
+ property_builder->SetCustomAttribute(attrBuilderBound);
+ }
+
+ // getter
+ Emit::MethodBuilder ^ method_builder =
+ type_builder->DefineMethod(
+ ustring_to_String( "get_" +
+ xAttribute->getMemberName() ),
+ c_property_method_attr, attribute_type, parameters );
+
+ //define UNO exception attribute (exceptions)--------------------------------------
+ Emit::CustomAttributeBuilder^ attrBuilder =
+ get_exception_attribute(xAttribute->getGetExceptions());
+ if (attrBuilder != nullptr)
+ method_builder->SetCustomAttribute(attrBuilder);
+
+ property_builder->SetGetMethod( method_builder );
+
+ if (! xAttribute->isReadOnly())
+ {
+ // setter
+ parameters = gcnew array< ::System::Type^> ( 1 );
+ parameters[ 0 ] = attribute_type;
+ method_builder =
+ type_builder->DefineMethod(
+ ustring_to_String( "set_" +
+ xAttribute->getMemberName() ),
+ c_property_method_attr, nullptr, parameters );
+ // define parameter info
+ method_builder->DefineParameter(
+ 1 /* starts with 1 */, ParameterAttributes::In, "value" );
+ //define UNO exception attribute (exceptions)--------------------------------------
+ Emit::CustomAttributeBuilder^ attrBuilder =
+ get_exception_attribute(xAttribute->getSetExceptions());
+ if (attrBuilder != nullptr)
+ method_builder->SetCustomAttribute(attrBuilder);
+
+ property_builder->SetSetMethod( method_builder );
+ }
+ }
+ }
+
+ // remove from incomplete types map
+ ::System::String ^ cts_name = type_builder->FullName;
+ m_incomplete_ifaces->Remove( cts_name );
+ xType->release();
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting interface type {0}", cts_name );
+ }
+ return type_builder->CreateType();
+}
+
+::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
+{
+ OSL_ASSERT(entry);
+ ::System::String ^ cts_name = entry->m_type_builder->FullName;
+
+ //Polymorphic struct, define uno.TypeParametersAttribute
+ //A polymorphic struct cannot have a basetype.
+ //When we create the template of the struct then we have no exact types
+ //and the name does not contain a parameter list
+ Sequence< OUString > seq_type_parameters;
+ Reference< reflection::XStructTypeDescription> xStructTypeDesc(
+ entry->m_xType, UNO_QUERY);
+ if (xStructTypeDesc.is())
+ {
+ seq_type_parameters = xStructTypeDesc->getTypeParameters();
+ int numTypes = 0;
+ if ((numTypes = seq_type_parameters.getLength()) > 0)
+ {
+ array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
+ for (int i = 0; i < numTypes; i++)
+ aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]);
+ array< ::System::Object^>^ args = {aArg};
+
+ array< ::System::Type^>^ arTypesCtor =
+ {::System::Type::GetType("System.String[]")};
+ Emit::CustomAttributeBuilder ^ attrBuilder =
+ gcnew Emit::CustomAttributeBuilder(
+ ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
+ args);
+ entry->m_type_builder->SetCustomAttribute(attrBuilder);
+ }
+ }
+
+ // optional: lookup base type whether generated entry of this session
+ struct_entry ^ base_type_entry = nullptr;
+ if (nullptr != entry->m_base_type)
+ {
+ //ToDo maybe get from incomplete structs
+ base_type_entry =
+ dynamic_cast< struct_entry ^ >(
+ m_generated_structs[
+ entry->m_base_type->FullName ] );
+ }
+
+ // members
+ Sequence< Reference< reflection::XTypeDescription > > seq_members(
+ entry->m_xType->getMemberTypes() );
+ Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
+ sal_Int32 members_length = seq_members.getLength();
+ OSL_ASSERT( seq_member_names.getLength() == members_length );
+ //check if we have a XTypeDescription for every member. If not then the user may
+ //have forgotten to specify additional rdbs with the --extra option.
+ Reference< reflection::XTypeDescription > const * pseq_members =
+ seq_members.getConstArray();
+ OUString const * pseq_member_names =
+ seq_member_names.getConstArray();
+ for (int i = 0; i < members_length; i++)
+ {
+ const OUString sType(entry->m_xType->getName());
+ const OUString sMemberName(pseq_member_names[i]);
+ if ( ! pseq_members[i].is())
+ throw RuntimeException("Missing type description . Check if you need to "
+ "specify additional RDBs with the --extra option. Type missing for: " + sType +
+ "::" + sMemberName,0);
+ }
+
+ sal_Int32 all_members_length = 0;
+ sal_Int32 member_pos;
+ sal_Int32 type_param_pos = 0;
+
+ // collect base types; wrong order
+ ::System::Collections::ArrayList ^ base_types_list =
+ gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
+ for (::System::Type ^ base_type_pos = entry->m_base_type;
+ ! base_type_pos->Equals( ::System::Object::typeid );
+ base_type_pos = base_type_pos->BaseType )
+ {
+ base_types_list->Add( base_type_pos );
+ if (base_type_pos->Equals( ::System::Exception::typeid ))
+ {
+ // special Message member
+ all_members_length += 1;
+ break; // don't include System.Exception base classes
+ }
+ else
+ {
+ //ensure the base type is complete. Otherwise GetFields won't work
+ get_complete_struct(base_type_pos->FullName);
+ all_members_length +=
+ base_type_pos->GetFields(
+ (BindingFlags) (BindingFlags::Instance |
+ BindingFlags::Public |
+ BindingFlags::DeclaredOnly) )
+ ->Length;
+ }
+ }
+
+ // create all_members arrays; right order
+ array< ::System::String^>^ all_member_names =
+ gcnew array< ::System::String^> (all_members_length + members_length );
+ array< ::System::Type^>^ all_param_types =
+ gcnew array< ::System::Type^> (all_members_length + members_length );
+ member_pos = 0;
+ for ( sal_Int32 pos = base_types_list->Count; pos--; )
+ {
+ ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
+ base_types_list[pos] );
+ if (base_type->Equals( ::System::Exception::typeid ))
+ {
+ all_member_names[ member_pos ] = "Message";
+ all_param_types[ member_pos ] = ::System::String::typeid;
+ ++member_pos;
+ }
+ else
+ {
+ ::System::String ^ base_type_name = base_type->FullName;
+
+ //ToDo m_generated_structs?
+ struct_entry ^ entry =
+ dynamic_cast< struct_entry ^ >(
+ m_generated_structs[base_type_name] );
+ if (nullptr == entry)
+ {
+ // complete type
+ array<FieldInfo^>^ fields =
+ base_type->GetFields(
+ (BindingFlags) (BindingFlags::Instance |
+ BindingFlags::Public |
+ BindingFlags::DeclaredOnly) );
+ sal_Int32 len = fields->Length;
+ for ( sal_Int32 pos = 0; pos < len; ++pos )
+ {
+ FieldInfo ^ field = fields[ pos ];
+ all_member_names[ member_pos ] = field->Name;
+ all_param_types[ member_pos ] = field->FieldType;
+ ++member_pos;
+ }
+ }
+ else // generated during this session:
+ // members may be incomplete ifaces
+ {
+ sal_Int32 len = entry->m_member_names->Length;
+ for ( sal_Int32 pos = 0; pos < len; ++pos )
+ {
+ all_member_names[ member_pos ] =
+ entry->m_member_names[ pos ];
+ all_param_types[ member_pos ] =
+ entry->m_param_types[ pos ];
+ ++member_pos;
+ }
+ }
+ }
+ }
+ OSL_ASSERT( all_members_length == member_pos );
+
+ // build up entry
+// struct_entry * entry = new struct_entry();
+ entry->m_member_names = gcnew array< ::System::String^> ( members_length );
+ entry->m_param_types = gcnew array< ::System::Type^> ( members_length );
+
+ // add members
+ array<Emit::FieldBuilder^>^ members = gcnew array<Emit::FieldBuilder^> ( members_length );
+ //Reference< reflection::XTypeDescription > const * pseq_members =
+ // seq_members.getConstArray();
+ //OUString const * pseq_member_names =
+ // seq_member_names.getConstArray();
+
+ int curParamIndex = 0; //count the fields which have parameterized types
+ for ( member_pos = 0; member_pos < members_length; ++member_pos )
+ {
+ ::System::String ^ field_name =
+ ustring_to_String( pseq_member_names[ member_pos ] );
+ ::System::Type ^ field_type;
+ //Special handling of struct parameter types
+ bool bParameterizedType = false;
+ if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
+ {
+ bParameterizedType = true;
+ if (type_param_pos < seq_type_parameters.getLength())
+ {
+ field_type = ::System::Object::typeid;
+ type_param_pos++;
+ }
+ else
+ {
+ throw RuntimeException(
+ "unexpected member type in " + entry->m_xType->getName() );
+ }
+ }
+ else
+ {
+ field_type = get_type( pseq_members[ member_pos ] );
+
+ if (field_type->IsArray
+ && m_incomplete_structs[cts_name]
+ && !field_type->Namespace->Equals("System"))
+ {
+ //Find the value type. In case of sequence<sequence< ... > > find the actual value type
+ ::System::Type ^ value = field_type;
+ while ((value = value->GetElementType())->IsArray);
+ //If the value type is a struct then make sure it is fully created.
+ get_complete_struct(value->FullName);
+ field_type = get_type(pseq_members[member_pos]);
+ }
+ }
+ members[ member_pos ] =
+ entry->m_type_builder->DefineField(
+ field_name, field_type, FieldAttributes::Public );
+
+ //parameterized type (polymorphic struct) ?
+ if (bParameterizedType && xStructTypeDesc.is())
+ {
+ //get the name
+ OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
+ ::System::String^ sTypeName = ustring_to_String(
+ seq_type_parameters.getConstArray()[curParamIndex++]);
+ array< ::System::Object^>^ args = {sTypeName};
+ //set ParameterizedTypeAttribute
+ array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};
+
+ Emit::CustomAttributeBuilder ^ attrBuilder =
+ gcnew Emit::CustomAttributeBuilder(
+ ::uno::ParameterizedTypeAttribute::typeid
+ ->GetConstructor(arCtorTypes),
+ args);
+
+ members[member_pos]->SetCustomAttribute(attrBuilder);
+ }
+ // add to all_members
+ all_member_names[ all_members_length + member_pos ] = field_name;
+ all_param_types[ all_members_length + member_pos ] = field_type;
+ // add to entry
+ entry->m_member_names[ member_pos ] = field_name;
+ entry->m_param_types[ member_pos ] = field_type;
+ }
+ all_members_length += members_length;
+
+ // default .ctor
+ Emit::ConstructorBuilder ^ ctor_builder =
+ entry->m_type_builder->DefineConstructor(
+ c_ctor_method_attr, CallingConventions::Standard,
+ gcnew array< ::System::Type^> ( 0 ) );
+ Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit(
+ Emit::OpCodes::Call,
+ nullptr == base_type_entry
+ ? entry->m_base_type->GetConstructor( gcnew array< ::System::Type^> ( 0 ) )
+ : base_type_entry->m_default_ctor );
+ // default initialize members
+ for ( member_pos = 0; member_pos < members_length; ++member_pos )
+ {
+ FieldInfo ^ field = members[ member_pos ];
+ ::System::Type ^ field_type = field->FieldType;
+ // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false);
+ // default initialize:
+ // string, type, enum, sequence, struct, exception, any
+ if (field_type->Equals( ::System::String::typeid ))
+ {
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldstr, "" );
+ code->Emit( Emit::OpCodes::Stfld, field );
+ }
+ else if (field_type->Equals( ::System::Type::typeid ))
+ {
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit(
+ Emit::OpCodes::Ldtoken, ::System::Void::typeid );
+ code->Emit(
+ Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
+ code->Emit( Emit::OpCodes::Stfld, field );
+ }
+ else if (field_type->IsArray)
+ {
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldc_I4_0 );
+ code->Emit(
+ Emit::OpCodes::Newarr, field_type->GetElementType() );
+ code->Emit( Emit::OpCodes::Stfld, field );
+ }
+ else if (field_type->IsValueType)
+ {
+ if (field_type->FullName->Equals( "uno.Any" ))
+ {
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
+ code->Emit( Emit::OpCodes::Stfld, field );
+ }
+ }
+ else if (field_type->IsClass)
+ {
+ /* may be XInterface */
+ if (! field_type->Equals( ::System::Object::typeid ))
+ {
+ // struct, exception
+ //make sure the struct is already complete.
+ get_complete_struct(field_type->FullName);
+ code->Emit( Emit::OpCodes::Ldarg_0 );
+ code->Emit(
+ Emit::OpCodes::Newobj,
+ //GetConstructor requires that the member types of the object which is to be constructed are already known.
+ field_type->GetConstructor(
+ gcnew array< ::System::Type^> ( 0 ) ) );
+ code->Emit( Emit::OpCodes::Stfld, field );
+ }
+ }
+ }
+ code->Emit( Emit::OpCodes::Ret );
+ entry->m_default_ctor = ctor_builder;
+
+ // parameterized .ctor including all base members
+ ctor_builder = entry->m_type_builder->DefineConstructor(
+ c_ctor_method_attr, CallingConventions::Standard, all_param_types );
+ for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
+ {
+ ctor_builder->DefineParameter(
+ member_pos +1 /* starts with 1 */, ParameterAttributes::In,
+ all_member_names[ member_pos ] );
+ }
+ code = ctor_builder->GetILGenerator();
+ // call base .ctor
+ code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
+ sal_Int32 base_members_length = all_members_length - members_length;
+ array< ::System::Type^>^ param_types =
+ gcnew array< ::System::Type^> ( base_members_length );
+ for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
+ {
+ emit_ldarg( code, member_pos +1 );
+ param_types[ member_pos ] = all_param_types[ member_pos ];
+ }
+ code->Emit(
+ Emit::OpCodes::Call,
+ nullptr == base_type_entry
+ ? entry->m_base_type->GetConstructor( param_types )
+ : base_type_entry->m_ctor );
+ // initialize members
+ for ( member_pos = 0; member_pos < members_length; ++member_pos )
+ {
+ code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
+ emit_ldarg( code, member_pos + base_members_length +1 );
+ code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
+ }
+ code->Emit( Emit::OpCodes::Ret );
+ entry->m_ctor = ctor_builder;
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting {0} type {1}",
+ TypeClass_STRUCT == entry->m_xType->getTypeClass()
+ ? "struct"
+ : "exception",
+ cts_name);
+ }
+ // new entry
+ m_generated_structs->Add(cts_name, entry );
+ ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
+
+ // remove from incomplete types map
+ m_incomplete_structs->Remove( cts_name );
+ entry->m_xType->release();
+
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting struct type {0}", cts_name);
+ }
+ return ret_type;
+}
+
+//Examples of generated code
+// public static XWeak constructor1(XComponentContext ctx)
+// {
+// XMultiComponentFactory factory = ctx.getServiceManager();
+// if (factory == null)
+// throw new com.sun.star.uno.DeploymentException("bla", null);
+// return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
+// }
+// public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
+// {
+// XMultiComponentFactory factory = ctx.getServiceManager();
+// if (factory == null)
+// throw new com.sun.star.uno.DeploymentException("bla", null);
+// Any[] arAny = new Any[3];
+// arAny[0] = new Any(typeof(int), a);
+// arAny[1] = new Any(typeof(int), b);
+// arAny[2] = new Any(c.Type, c.Value);
+// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
+// }
+// Notice that an any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
+// of the parameter.
+
+// public static XWeak constructor3(XComponentContext ctx, params Any[] c)
+// {
+// XMultiComponentFactory factory = ctx.getServiceManager();
+// if (factory == null)
+// throw new com.sun.star.uno.DeploymentException("bla", null);
+// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
+// }
+::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
+{
+ Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
+ reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
+
+ //Create the private default constructor
+ Emit::ConstructorBuilder^ ctor_builder =
+ type_builder->DefineConstructor(
+ (MethodAttributes) (MethodAttributes::Private |
+ MethodAttributes::HideBySig |
+ MethodAttributes::SpecialName |
+ MethodAttributes::RTSpecialName),
+ CallingConventions::Standard, nullptr);
+
+ Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
+ ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
+ ilGen->Emit(
+ Emit::OpCodes::Call,
+ type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
+ ilGen->Emit( Emit::OpCodes::Ret );
+
+
+ //Create the service constructors.
+ //obtain the interface which makes up this service, it is the return
+ //type of the constructor functions
+ Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
+ xServiceType->getInterface(), UNO_QUERY);
+ if (xIfaceType.is () == sal_False)
+ xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
+ System::Type ^ retType = get_type(xIfaceType);
+
+ //Create the ConstructorInfo for a DeploymentException
+ ::System::Type ^ typeDeploymentExc =
+ get_type("unoidl.com.sun.star.uno.DeploymentException", true);
+
+ array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
+ ::System::Object::typeid};
+ ::System::Reflection::ConstructorInfo ^ ctorDeploymentException =
+ typeDeploymentExc->GetConstructor(arTypeCtor);
+
+ Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors =
+ xServiceType->getConstructors();
+
+ ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
+
+ for (int i = seqCtors.getLength() - 1; i >= 0; i--)
+ {
+ bool bParameterArray = false;
+ ::System::Type ^ typeAny = ::uno::Any::typeid;
+ const Reference<reflection::XServiceConstructorDescription> & ctorDes =
+ seqCtors[i];
+ //obtain the parameter types
+ Sequence<Reference<reflection::XParameter> > seqParams =
+ ctorDes->getParameters();
+ Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray();
+ sal_Int32 cParams = seqParams.getLength();
+ array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
+ arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
+ for (int iparam = 0; iparam != cParams; iparam++)
+ {
+ if (arXParams[iparam]->isRestParameter())
+ arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
+ else
+ arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
+ }
+ //The array arTypeParameters can contain:
+ //System.Type and uno.PolymorphicType.
+ //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
+ //The exception will read something like no on information for parameter # d
+ //Maybe we need no override another Type method in PolymorphicType ...
+ //Until we have figured this out, we will create another array of System.Type which
+ //we pass on to DefineMethod.
+ array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
+// arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
+ for (int i = 0; i < cParams + 1; i++)
+ {
+ ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
+ if (pT)
+ arParamTypes[i] = pT->OriginalType;
+ else
+ arParamTypes[i] = arTypeParameters[i];
+ }
+ //define method
+ System::String ^ ctorName;
+ if (ctorDes->isDefaultConstructor())
+ ctorName = gcnew ::System::String("create");
+ else
+ ctorName = ustring_to_String(ctorDes->getName());
+ Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
+ ctorName,
+ static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
+ MethodAttributes::Static),
+ retType,
+// arTypeParameters);
+ arParamTypes);
+
+ //define UNO exception attribute (exceptions)--------------------------------------
+ Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes);
+ if (attrBuilder != nullptr)
+ method_builder->SetCustomAttribute(attrBuilder);
+
+
+ //define parameter attributes (paramarray), names etc.
+ //The first parameter is the XComponentContext, which cannot be obtained
+ //from reflection.
+ //The context is not part of the idl description
+ method_builder->DefineParameter(
+ 1, ParameterAttributes::In, "the_context");
+
+ array<Emit::ParameterBuilder^>^ arParameterBuilder =
+ gcnew array<Emit::ParameterBuilder^> (cParams);
+ for (int iparam = 0; iparam != cParams; iparam++)
+ {
+ Reference<reflection::XParameter> const & aParam = arXParams[iparam];
+ ::System::String ^ sParamName = ustring_to_String(aParam->getName());
+
+ arParameterBuilder[iparam] = method_builder->DefineParameter(
+ iparam + 2, ParameterAttributes::In, sParamName);
+
+ if (aParam->isRestParameter())
+ {
+ bParameterArray = true;
+ //set the ParameterArrayAttribute
+ ::System::Reflection::ConstructorInfo^ ctor_info =
+ System::ParamArrayAttribute::typeid->GetConstructor(
+ gcnew array< ::System::Type^>(0));
+ Emit::CustomAttributeBuilder ^ attr_builder =
+ gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0));
+ arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
+ break;
+ }
+ }
+
+ Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
+
+ //Define locals ---------------------------------
+ //XMultiComponentFactory
+ Emit::LocalBuilder^ local_factory =
+ ilGen->DeclareLocal(
+ get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
+
+ //The return type
+ Emit::LocalBuilder^ local_return_val =
+ ilGen->DeclareLocal(retType);
+
+ //Obtain the XMultiComponentFactory and throw an exception if we do not get one
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+
+ ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
+ "unoidl.com.sun.star.uno.XComponentContext", true)
+ ->GetMethod("getServiceManager");
+ ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
+ ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
+ Emit::Label label1 = ilGen->DefineLabel();
+ ilGen->Emit(Emit::OpCodes::Brtrue, label1);
+ //The string for the exception
+ ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
+ strbuilder->Append("The service ");
+ strbuilder->Append(to_cts_name(xServiceType->getName()));
+ strbuilder->Append(" could not be created. The context failed to supply the service manager.");
+
+ ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
+ ilGen->Emit(Emit::OpCodes::Throw);
+ ilGen->MarkLabel(label1);
+
+ //We create a try/ catch around the createInstanceWithContext, etc. functions
+ //There are 3 cases
+ //1. function do not specify exceptions. Then RuntimeExceptions are re-thrown and other
+ // exceptions produce a DeploymentException.
+ //2. function specify Exception. Then all exceptions fly through
+ //3. function specifies exceptions but no Exception. Then these are rethrown
+ // and other exceptions, except RuntimeException, produce a deployment exception.
+ //In case there are no parameters we call
+ //XMultiComponentFactory.createInstanceWithContext
+
+ ::System::Collections::ArrayList ^ arExceptionTypes =
+ get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
+ if (arExceptionTypes->Contains(
+ type_uno_exception) == false)
+ {
+ ilGen->BeginExceptionBlock();
+ }
+ if (cParams == 0)
+ {
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+
+ ::System::Reflection::MethodInfo ^ methodCreate =
+ local_factory->LocalType->GetMethod("createInstanceWithContext");
+ ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
+ }
+ else if(bParameterArray)
+ {
+ //Service constructor with parameter array
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldarg_1);
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ ::System::Reflection::MethodInfo ^ methodCreate =
+ local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
+ ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
+ }
+ else
+ {
+ // Any param1, Any param2, etc.
+ // For each parameter,except the component context, and parameter array
+ // and Any is created.
+ array<Emit::LocalBuilder^>^ arLocalAny = gcnew array<Emit::LocalBuilder^> (cParams);
+
+ for (int iParam = 0; iParam < cParams; iParam ++)
+ {
+ arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
+ }
+
+ //Any[]. This array is filled with the created Anys which contain the parameters
+ //and the values contained in the parameter array
+ Emit::LocalBuilder ^ local_anyParams =
+ ilGen->DeclareLocal(array< ::uno::Any>::typeid);
+
+ //Create the Any for every argument, except for the parameter array
+ //arLocalAny contains the LocalBuilder for all these parameters.
+ //we call the ctor Any(Type, Object)
+ //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
+ array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid,
+ ::System::Object::typeid};
+ ::System::Reflection::ConstructorInfo ^ ctorAny =
+ typeAny->GetConstructor( arTypesCtorAny);
+ ::System::Reflection::MethodInfo ^ methodAnyGetType =
+ typeAny->GetProperty("Type")->GetGetMethod();
+ ::System::Reflection::MethodInfo ^ methodAnyGetValue =
+ typeAny->GetProperty("Value")->GetGetMethod();
+ for (int i = 0; i < arLocalAny->Length; i ++)
+ {
+ //check if the parameter is a polymorphic struct
+ ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]);
+ //arTypeParameters[i+1] = polyType->OriginalType;
+ if (polyType)
+ {
+ //It is a polymorphic struct
+ //Load the uninitialized local Any on which we will call the ctor
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
+ // Prepare the first parameter
+ ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
+ array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
+ ilGen->Emit(Emit::OpCodes::Call,
+ ::System::Type::typeid->GetMethod(
+ "GetTypeFromHandle", arTypeParams));
+ // Prepare the second parameter
+ ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
+ // Make the actual call
+ array< ::System::Type^>^ arTypeParam_GetType = {
+ ::System::Type::typeid, ::System::String::typeid };
+ ilGen->Emit(Emit::OpCodes::Call,
+ ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
+ arTypeParam_GetType));
+
+ //Stack is: localAny, PolymorphicType
+ //Call Any::Any(Type, Object)
+ //Prepare the second parameter for the any ctor
+ ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
+ // if the parameter is a value type then we need to box it, because
+ // the Any ctor takes an Object
+ if (arTypeParameters[i+1]->IsValueType)
+ ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
+ else if (arTypeParameters[i+1] == typeAny)
+ {
+ //Create the call new Any(param.Type,param,Value)
+ //Stack must be Any,Type,Value
+ //First load the Any which is to be constructed
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ //Load the Type, which is obtained by calling param.Type
+ ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
+ ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
+ //Load the Value, which is obtained by calling param.Value
+ ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
+ ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
+ //Call the Any ctor.
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
+ else
+ {
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
+
+ array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
+ ilGen->Emit(Emit::OpCodes::Call,
+ ::System::Type::typeid->GetMethod(
+ "GetTypeFromHandle", arTypeParams));
+ ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
+ // if the parameter is a value type then we need to box it, because
+ // the Any ctor takes an Object
+ if (arTypeParameters[i+1]->IsValueType)
+ ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
+ }
+
+ //Create the Any[] that is passed to the
+ //createInstanceWithContext[AndArguments] function
+ ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
+ ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
+ ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
+
+ //Assign all anys created from the parameters
+ //array to the Any[]
+ for (int i = 0; i < arLocalAny->Length; i++)
+ {
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
+ ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
+ ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
+ ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
+ ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
+ }
+ // call createInstanceWithArgumentsAndContext
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ ::System::Reflection::MethodInfo ^ methodCreate =
+ local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
+ ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
+ }
+ //cast the object returned by the functions createInstanceWithContext or
+ //createInstanceWithArgumentsAndContext to the interface type
+ ilGen->Emit(Emit::OpCodes::Castclass, retType);
+ ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
+
+ //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
+ if (arExceptionTypes->Contains(type_uno_exception) == false)
+ {
+ // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
+ ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
+ ilGen->Emit(Emit::OpCodes::Pop);
+ ilGen->Emit(Emit::OpCodes::Rethrow);
+
+ //catch and rethrow all other defined Exceptions
+ for (int i = 0; i < arExceptionTypes->Count; i++)
+ {
+ ::System::Type ^ excType = safe_cast< ::System::Type^ >(
+ arExceptionTypes[i]);
+ if (excType->IsInstanceOfType(
+ get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
+ {// we have a catch for RuntimeException already defined
+ continue;
+ }
+
+ //catch Exception and rethrow
+ ilGen->BeginCatchBlock(excType);
+ ilGen->Emit(Emit::OpCodes::Pop);
+ ilGen->Emit(Emit::OpCodes::Rethrow);
+ }
+ //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
+ ilGen->BeginCatchBlock(type_uno_exception);
+
+ //Define the local variable that keeps the exception
+ Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
+ type_uno_exception);
+
+ //Store the exception
+ ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
+
+ //prepare the construction of the exception
+ strbuilder = gcnew ::System::Text::StringBuilder(256);
+ strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
+ strbuilder->Append(to_cts_name(xServiceType->getName()));
+ strbuilder->Append(": ");
+
+ ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
+
+ //add to the string the Exception.Message
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
+ ilGen->Emit(Emit::OpCodes::Callvirt,
+ type_uno_exception->GetProperty("Message")->GetGetMethod());
+ array< ::System::Type^>^ arConcatParams = {System::String::typeid,
+ System::String::typeid};
+ ilGen->Emit(Emit::OpCodes::Call,
+ System::String::typeid->GetMethod("Concat", arConcatParams));
+ //load context argument
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
+ ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
+
+ ilGen->EndExceptionBlock();
+ }
+
+
+ //Check if the service instance was created and threw an exception if not
+ Emit::Label label_service_created = ilGen->DefineLabel();
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
+ ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
+
+ strbuilder = gcnew ::System::Text::StringBuilder(256);
+ strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
+ strbuilder->Append(to_cts_name(xServiceType->getName()));
+ strbuilder->Append(".");
+ ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
+ ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
+
+ ilGen->MarkLabel(label_service_created);
+ ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
+ ilGen->Emit(Emit::OpCodes::Ret);
+
+ }
+ // remove from incomplete types map
+ ::System::String ^ cts_name = type_builder->FullName;
+ m_incomplete_services->Remove( cts_name );
+ xServiceType->release();
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting service type {0}", cts_name );
+ }
+ return type_builder->CreateType();
+}
+
+
+Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute(
+ const Reference<reflection::XServiceConstructorDescription> & ctorDes )
+{
+ return get_exception_attribute(ctorDes->getExceptions());
+}
+
+Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute(
+ const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
+{
+
+ const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
+ int len = seqTD.getLength();
+ Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
+ Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
+ for (int i = 0; i < len; i++)
+ arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
+ return get_exception_attribute(seqCTD);
+}
+
+Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute(
+
+ const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
+{
+ Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
+
+ Reference< reflection::XCompoundTypeDescription > const * exceptions =
+ seq_exceptionsTd.getConstArray();
+
+ array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
+ ConstructorInfo ^ ctor_ExceptionAttribute =
+ ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
+
+ sal_Int32 exc_length = seq_exceptionsTd.getLength();
+ if (exc_length != 0) // opt
+ {
+ array< ::System::Type^>^ exception_types =
+ gcnew array< ::System::Type^> ( exc_length );
+ for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
+ {
+ Reference< reflection::XCompoundTypeDescription > const & xExc =
+ exceptions[ exc_pos ];
+ exception_types[ exc_pos ] = get_type( xExc );
+ }
+ array< ::System::Object^>^ args = {exception_types};
+ attr_builder = gcnew Emit::CustomAttributeBuilder(
+ ctor_ExceptionAttribute, args );
+ }
+ return attr_builder;
+}
+
+
+::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
+{
+ Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
+ reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
+ ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName());
+
+ //Create the private default constructor
+ Emit::ConstructorBuilder^ ctor_builder =
+ type_builder->DefineConstructor(
+ static_cast<MethodAttributes>(MethodAttributes::Private |
+ MethodAttributes::HideBySig |
+ MethodAttributes::SpecialName |
+ MethodAttributes::RTSpecialName),
+ CallingConventions::Standard, nullptr);
+
+ Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
+ ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
+ ilGen->Emit(
+ Emit::OpCodes::Call,
+ type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
+ ilGen->Emit( Emit::OpCodes::Ret );
+
+
+ //obtain the interface which makes up this service, it is the return
+ //type of the constructor functions
+ Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
+ xSingletonType->getInterface(), UNO_QUERY);
+ if (xIfaceType.is () == sal_False)
+ xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
+ System::Type ^ retType = get_type(xIfaceType);
+
+ //define method
+ array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
+ Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
+ gcnew System::String("get"),
+ static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
+ MethodAttributes::Static),
+ retType,
+ arTypeParameters);
+
+
+// method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
+
+ //The first parameter is the XComponentContext, which cannot be obtained
+ //from reflection.
+ //The context is not part of the idl description
+ method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
+
+
+ ilGen = method_builder->GetILGenerator();
+ //Define locals ---------------------------------
+ // Any, returned by XComponentContext.getValueByName
+ Emit::LocalBuilder^ local_any =
+ ilGen->DeclareLocal(::uno::Any::typeid);
+
+ //Call XContext::getValueByName
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ // build the singleton name : /singleton/unoidl.com.sun.star.XXX
+ ::System::Text::StringBuilder^ sBuilder =
+ gcnew ::System::Text::StringBuilder("/singletons/");
+ sBuilder->Append(sSingletonName);
+ ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
+
+ ::System::Reflection::MethodInfo ^ methodGetValueByName =
+ get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
+ ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
+ ilGen->Emit(Emit::OpCodes::Stloc_0);
+
+ //Contains the returned Any a value?
+ ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
+ ::System::Reflection::MethodInfo ^ methodHasValue =
+ ::uno::Any::typeid->GetMethod("hasValue");
+ ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
+
+ //If not, then throw a DeploymentException
+ Emit::Label label_singleton_exists = ilGen->DefineLabel();
+ ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
+ sBuilder = gcnew ::System::Text::StringBuilder(
+ "Component context fails to supply singleton ");
+ sBuilder->Append(sSingletonName);
+ sBuilder->Append(" of type ");
+ sBuilder->Append(retType->FullName);
+ sBuilder->Append(".");
+ ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
+ ilGen->Emit(Emit::OpCodes::Ldarg_0);
+ array< ::System::Type^>^ arTypesCtorDeploymentException = {
+ ::System::String::typeid, ::System::Object::typeid};
+ ilGen->Emit(Emit::OpCodes::Newobj,
+ get_type("unoidl.com.sun.star.uno.DeploymentException",true)
+ ->GetConstructor(arTypesCtorDeploymentException));
+ ilGen->Emit(Emit::OpCodes::Throw);
+ ilGen->MarkLabel(label_singleton_exists);
+
+ //Cast the singleton contained in the Any to the expected interface and return it.
+ ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
+ ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
+ ilGen->Emit(Emit::OpCodes::Castclass, retType);
+ ilGen->Emit(Emit::OpCodes::Ret);
+
+ // remove from incomplete types map
+ ::System::String ^ cts_name = type_builder->FullName;
+ m_incomplete_singletons->Remove( cts_name );
+ xSingletonType->release();
+ if (g_bVerbose)
+ {
+ ::System::Console::WriteLine(
+ "> emitting singleton type {0}", cts_name );
+ }
+ return type_builder->CreateType();
+}
+
+
+::System::Type ^ TypeEmitter::get_type(
+ Reference< reflection::XTypeDescription > const & xType )
+{
+ switch (xType->getTypeClass())
+ {
+ case TypeClass_VOID:
+ return ::System::Void::typeid;
+ case TypeClass_CHAR:
+ return ::System::Char::typeid;
+ case TypeClass_BOOLEAN:
+ return ::System::Boolean::typeid;
+ case TypeClass_BYTE:
+ return ::System::Byte::typeid;
+ case TypeClass_SHORT:
+ return ::System::Int16::typeid;
+ case TypeClass_UNSIGNED_SHORT:
+ return ::System::UInt16::typeid;
+ case TypeClass_LONG:
+ return ::System::Int32::typeid;
+ case TypeClass_UNSIGNED_LONG:
+ return ::System::UInt32::typeid;
+ case TypeClass_HYPER:
+ return ::System::Int64::typeid;
+ case TypeClass_UNSIGNED_HYPER:
+ return ::System::UInt64::typeid;
+ case TypeClass_FLOAT:
+ return ::System::Single::typeid;
+ case TypeClass_DOUBLE:
+ return ::System::Double::typeid;
+ case TypeClass_STRING:
+ return ::System::String::typeid;
+ case TypeClass_TYPE:
+ return ::System::Type::typeid;
+ case TypeClass_ANY:
+ return ::uno::Any::typeid;
+ case TypeClass_ENUM:
+ return get_type( Reference< reflection::XEnumTypeDescription >(
+ xType, UNO_QUERY_THROW ) );
+ case TypeClass_TYPEDEF:
+ // unwind typedefs
+ return get_type(
+ Reference< reflection::XIndirectTypeDescription >(
+ xType, UNO_QUERY_THROW )->getReferencedType() );
+ case TypeClass_STRUCT:
+ case TypeClass_EXCEPTION:
+ return get_type(
+ Reference< reflection::XCompoundTypeDescription >(
+ xType, UNO_QUERY_THROW ) );
+ case TypeClass_SEQUENCE:
+ {
+ ::System::Type ^ element_type = get_type(
+ Reference< reflection::XIndirectTypeDescription >(
+ xType, UNO_QUERY_THROW )->getReferencedType() );
+ ::System::Type ^ retType = get_type(
+ ::System::String::Concat(
+ element_type->FullName, "[]" ), true );
+
+ ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
+ if (pt)
+ {
+ ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
+ retType = ::uno::PolymorphicType::GetType(retType, sName);
+ }
+ return retType;
+ }
+ case TypeClass_INTERFACE:
+ return get_type(
+ Reference< reflection::XInterfaceTypeDescription2 >(
+ xType, UNO_QUERY_THROW ) );
+ case TypeClass_CONSTANT:
+ return get_type(
+ Reference< reflection::XConstantTypeDescription >(
+ xType, UNO_QUERY_THROW ) );
+ case TypeClass_CONSTANTS:
+ return get_type(
+ Reference< reflection::XConstantsTypeDescription >(
+ xType, UNO_QUERY_THROW ) );
+ case TypeClass_SERVICE:
+ return get_type(
+ Reference< reflection::XServiceTypeDescription2 >(
+ xType, UNO_QUERY_THROW) );
+ case TypeClass_SINGLETON:
+ return get_type(
+ Reference< reflection::XSingletonTypeDescription2 >(
+ xType, UNO_QUERY_THROW) );
+ case TypeClass_MODULE:
+ // ignore these
+ return nullptr;
+ default:
+ throw RuntimeException(
+ "unexpected type " + xType->getName() );
+ }
+}
+
+
+::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
+{
+ struct_entry ^ pStruct = safe_cast< struct_entry ^>(
+ m_incomplete_structs[sName]);
+ if (pStruct)
+ {
+ complete_struct_type(pStruct);
+ }
+ //get_type will asked the module builder for the type or otherwise all known assemblies.
+ return get_type(sName, true);
+}
+TypeEmitter::~TypeEmitter()
+{
+ while (true)
+ {
+ ::System::Collections::IDictionaryEnumerator ^ enumerator =
+ m_incomplete_ifaces->GetEnumerator();
+ if (! enumerator->MoveNext())
+ break;
+ complete_iface_type(
+ safe_cast< iface_entry ^ >( enumerator->Value ) );
+ }
+
+ while (true)
+ {
+ ::System::Collections::IDictionaryEnumerator ^ enumerator =
+ m_incomplete_structs->GetEnumerator();
+ if (! enumerator->MoveNext())
+ break;
+ complete_struct_type(
+ safe_cast< struct_entry ^ >( enumerator->Value ) );
+ }
+
+
+ while (true)
+ {
+ ::System::Collections::IDictionaryEnumerator ^ enumerator =
+ m_incomplete_services->GetEnumerator();
+ if (! enumerator->MoveNext())
+ break;
+ complete_service_type(
+ safe_cast< service_entry ^ >( enumerator->Value ) );
+ }
+
+ while (true)
+ {
+ ::System::Collections::IDictionaryEnumerator ^ enumerator =
+ m_incomplete_singletons->GetEnumerator();
+ if (! enumerator->MoveNext())
+ break;
+ complete_singleton_type(
+ safe_cast< singleton_entry ^ >( enumerator->Value ) );
+ }
+}
+
+TypeEmitter::TypeEmitter(
+ ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
+ array< ::System::Reflection::Assembly^>^ extra_assemblies )
+ : m_module_builder( module_builder ),
+ m_extra_assemblies( extra_assemblies ),
+ m_method_info_Type_GetTypeFromHandle( nullptr ),
+ m_type_Exception( nullptr ),
+ m_type_RuntimeException( nullptr ),
+ m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
+ m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
+ m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
+ m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
+ m_generated_structs( gcnew ::System::Collections::Hashtable() )
+{
+ array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 );
+ param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
+ m_method_info_Type_GetTypeFromHandle =
+ ::System::Type::typeid
+ ->GetMethod( "GetTypeFromHandle", param_types );
+}
+
+::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
+ const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
+{
+ if (seqExceptionsTd.getLength() == 0)
+ return gcnew ::System::Collections::ArrayList();
+
+ ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
+ for (int i = 0; i < seqExceptionsTd.getLength(); i++)
+ arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
+
+ int start = 0;
+ while (true)
+ {
+ bool bRemove = false;
+ for (int i = start; i < arTypes->Count; i++)
+ {
+ ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]);
+ for (int j = 0; j < arTypes->Count; j++)
+ {
+ if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j])))
+ {
+ arTypes->RemoveAt(i);
+ bRemove = true;
+ break;
+ }
+ }
+ if (bRemove)
+ break;
+ start++;
+ }
+
+ if (bRemove == false)
+ break;
+ }
+ return arTypes;
+}
+
+
+css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
+resolveInterfaceTypedef(
+ const css::uno::Reference<css::reflection::XTypeDescription>& type)
+{
+ Reference<reflection::XInterfaceTypeDescription2>
+ xIfaceTd(type, UNO_QUERY);
+
+ if (xIfaceTd.is())
+ return xIfaceTd;
+
+ Reference<reflection::XIndirectTypeDescription> xIndTd(
+ type, UNO_QUERY_THROW);
+
+ return resolveInterfaceTypedef(xIndTd->getReferencedType());
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/climaker/climaker_share.h b/cli_ure/source/climaker/climaker_share.h
new file mode 100644
index 000000000..ed7ab256a
--- /dev/null
+++ b/cli_ure/source/climaker/climaker_share.h
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#using <cli_basetypes.dll>
+
+#include <vcclr.h>
+
+#include "osl/diagnose.h"
+#include "com/sun/star/reflection/XConstantTypeDescription.hpp"
+#include "com/sun/star/reflection/XConstantsTypeDescription.hpp"
+#include "com/sun/star/reflection/XEnumTypeDescription.hpp"
+#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
+#include "com/sun/star/reflection/XCompoundTypeDescription.hpp"
+#include "com/sun/star/reflection/XServiceTypeDescription2.hpp"
+#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp"
+#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
+
+
+namespace climaker
+{
+
+
+extern bool g_bVerbose;
+
+ref struct Constants
+{
+ static ::System::String ^ sUnoVoid = "void";
+ static ::System::String ^ sUnoType = "type";
+ static ::System::String ^ sUnoAny = "any";
+ static ::System::String ^ sUnoBool = "boolean";
+ static ::System::String ^ sUnoByte = "byte";
+ static ::System::String ^ sUnoChar = "char";
+ static ::System::String ^ sUnoShort = "short";
+ static ::System::String ^ sUnoUShort = "unsigned short";
+ static ::System::String ^ sUnoLong = "long";
+ static ::System::String ^ sUnoULong = "unsigned long";
+ static ::System::String ^ sUnoHyper = "hyper";
+ static ::System::String ^ sUnoUHyper = "unsigned hyper";
+ static ::System::String ^ sUnoString = "string";
+ static ::System::String ^ sUnoFloat = "float";
+ static ::System::String ^ sUnoDouble = "double";
+ static ::System::String ^ sUnoXInterface = "com.sun.star.uno.XInterface";
+ static ::System::String ^ sBrackets = "[]";
+
+ static System::String^ sObject = "System.Object";
+ static System::String^ sType = "System.Type";
+ static System::String^ sUnoidl = "unoidl.";
+ static System::String^ sVoid = "System.Void";
+ static System::String^ sAny = "uno.Any";
+ static System::String^ sBoolean = "System.Boolean";
+ static System::String^ sChar = "System.Char";
+ static System::String^ sByte = "System.Byte";
+ static System::String^ sInt16 = "System.Int16";
+ static System::String^ sUInt16 = "System.UInt16";
+ static System::String^ sInt32 = "System.Int32";
+ static System::String^ sUInt32 = "System.UInt32";
+ static System::String^ sInt64 = "System.Int64";
+ static System::String^ sUInt64 = "System.UInt64";
+ static System::String^ sString = "System.String";
+ static System::String^ sSingle = "System.Single";
+ static System::String^ sDouble = "System.Double";
+ static System::String^ sComma = gcnew System::String(",");
+
+};
+
+
+inline ::System::String ^ ustring_to_String( OUString const & ustr )
+{
+ return gcnew ::System::String(
+ reinterpret_cast<wchar_t const *>(ustr.getStr()), 0, ustr.getLength());
+}
+
+
+inline OUString String_to_ustring( ::System::String ^ str )
+{
+ OSL_ASSERT( sizeof (wchar_t) == sizeof (sal_Unicode) );
+ pin_ptr<const wchar_t> chars = PtrToStringChars( str );
+ return OUString(reinterpret_cast<sal_Unicode const *>(chars), str->Length);
+}
+
+/* If the argument type is a typedef for an interface then the interface
+ type description is returned, otherwise an exception is thrown.
+*/
+css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
+resolveInterfaceTypedef(const css::uno::Reference<css::reflection::XTypeDescription>& type);
+
+static ::System::Reflection::MethodAttributes c_ctor_method_attr =
+(::System::Reflection::MethodAttributes)
+ (::System::Reflection::MethodAttributes::Public |
+ ::System::Reflection::MethodAttributes::HideBySig |
+ ::System::Reflection::MethodAttributes::SpecialName |
+ ::System::Reflection::MethodAttributes::RTSpecialName
+ /* | xxx todo: ??? compiler does not know Instance ???
+ ::System::Reflection::MethodAttributes::Instance*/);
+
+
+ref class TypeEmitter : public ::System::IDisposable
+{
+ ::System::Reflection::Emit::ModuleBuilder ^ m_module_builder;
+ array< ::System::Reflection::Assembly^>^ m_extra_assemblies;
+
+ ::System::Reflection::MethodInfo ^ m_method_info_Type_GetTypeFromHandle;
+
+ ::System::Type ^ m_type_Exception;
+ ::System::Type ^ get_type_Exception();
+ ::System::Type ^ m_type_RuntimeException;
+ ::System::Type ^ get_type_RuntimeException();
+
+ ::System::Reflection::Emit::CustomAttributeBuilder^ get_service_exception_attribute(
+ const css::uno::Reference<css::reflection::XServiceConstructorDescription> & ctorDesc);
+ ::System::Reflection::Emit::CustomAttributeBuilder^ get_iface_method_exception_attribute(
+ const css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >& xMethod );
+ ::System::Reflection::Emit::CustomAttributeBuilder^ get_exception_attribute(
+ const css::uno::Sequence<css::uno::Reference<
+ css::reflection::XCompoundTypeDescription > >& seq_exceptionsTd );
+/* Creates ::System::Type object for UNO exceptions. The UNO exceptions are
+ obtained by
+ css::reflection::XServiceConstructorDescription::getExceptions
+ In a first step the respective CLI types are created. Then it is examined
+ if a Type represents a super class of another class. If so the Type of the
+ derived class is discarded. For example there are a uno RuntimeException and
+ a DeploymentException which inherits RuntimeException. Then only the cli Type
+ of the RuntimeException is returned.
+ The purpose of this function is to provide exceptions for which catch blocks
+ are generated in the service constructor code.
+
+ It is always an instance of an ArrayList returned, even if the sequence argument
+ does not contain elements.
+ */
+ ::System::Collections::ArrayList ^ get_service_ctor_method_exceptions_reduced(
+ const css::uno::Sequence<
+ css::uno::Reference<css::reflection::XCompoundTypeDescription> > & seqExceptionsTd);
+
+
+ ref class iface_entry
+ {
+ public:
+ css::reflection::XInterfaceTypeDescription2 * m_xType;
+ ::System::Reflection::Emit::TypeBuilder ^ m_type_builder;
+ };
+ ::System::Collections::Hashtable ^ m_incomplete_ifaces;
+ ::System::Type ^ complete_iface_type( iface_entry ^ entry );
+
+ ref class struct_entry
+ {
+ public:
+ css::reflection::XCompoundTypeDescription * m_xType;
+ ::System::Reflection::Emit::TypeBuilder ^ m_type_builder;
+ ::System::Type ^ m_base_type;
+
+ array< ::System::String^>^ m_member_names;
+ array< ::System::Type^>^ m_param_types;
+ ::System::Reflection::ConstructorInfo ^ m_default_ctor;
+ ::System::Reflection::ConstructorInfo ^ m_ctor;
+ };
+ ::System::Collections::Hashtable ^ m_incomplete_structs;
+ ::System::Type ^ complete_struct_type( struct_entry ^ entry );
+
+ /* returns the type for the name. If it is a struct then it may
+ complete the struct if not already done. This also refers to its
+ base types.
+
+ @param sName
+ the full name of the type.
+ @return the type object for sName. Not necessarily a struct.
+ */
+ ::System::Type ^ get_complete_struct( ::System::String ^ sName);
+
+ ref class service_entry
+ {
+ public:
+ ::System::Reflection::Emit::TypeBuilder ^ m_type_builder;
+ css::reflection::XServiceTypeDescription2 * m_xType;
+ };
+ ::System::Collections::Hashtable ^ m_incomplete_services;
+ ::System::Type ^ complete_service_type(service_entry ^ entry);
+
+ ref class singleton_entry
+ {
+ public:
+ ::System::Reflection::Emit::TypeBuilder ^ m_type_builder;
+ css::reflection::XSingletonTypeDescription2 * m_xType;
+ };
+
+
+ ::System::Collections::Hashtable ^ m_incomplete_singletons;
+ ::System::Type ^ complete_singleton_type(singleton_entry ^ entry);
+
+
+ ::System::Collections::Hashtable ^ m_generated_structs;
+
+ ::System::Type ^ get_type(
+ ::System::String ^ cli_name, bool throw_exc );
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XConstantTypeDescription > const & xType );
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XConstantsTypeDescription > const & xType );
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XEnumTypeDescription > const & xType );
+ /* returns the type for a struct or exception. In case of a polymorphic struct it may
+ return a ::uno::PolymorphicType (cli_basetypes.dll) only if the struct is already
+ complete.
+ */
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XCompoundTypeDescription > const & xType );
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XInterfaceTypeDescription2 > const & xType );
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XSingletonTypeDescription2 > const & xType );
+
+ /*
+ May return NULL if the service description is an obsolete. See
+ description of
+ com.sun.star.reflection.XServiceTypeDescription2.isSingleInterfaceBased
+ */
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XServiceTypeDescription2 > const & xType );
+public:
+ TypeEmitter(
+ ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
+ array< ::System::Reflection::Assembly^>^ assemblies );
+ // must be called to finish up uncompleted types
+ ~TypeEmitter();
+
+ ::System::Reflection::Assembly ^ type_resolve(
+ ::System::Object ^ sender, ::System::ResolveEventArgs ^ args );
+
+ ::System::Type ^ get_type(
+ css::uno::Reference<
+ css::reflection::XTypeDescription > const & xType );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/cliuno.snk b/cli_ure/source/cliuno.snk
new file mode 100644
index 000000000..938f16939
--- /dev/null
+++ b/cli_ure/source/cliuno.snk
Binary files differ
diff --git a/cli_ure/source/native/assembly.cxx b/cli_ure/source/native/assembly.cxx
new file mode 100644
index 000000000..75e33e8c7
--- /dev/null
+++ b/cli_ure/source/native/assembly.cxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+[assembly:System::Reflection::AssemblyProduct("CLI-UNO Language Binding")];
+[assembly:System::Reflection::AssemblyDescription("CLI-UNO Helper Library")];
+[assembly:System::Reflection::AssemblyDelaySign(true)];
+[assembly:System::Reflection::AssemblyCompany("OpenOffice.org")];
+[assembly:System::Reflection::AssemblyVersion("@CLI_CPPUHELPER_NEW_VERSION@")];
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/native/cli_cppuhelper_config b/cli_ure/source/native/cli_cppuhelper_config
new file mode 100644
index 000000000..627a3a564
--- /dev/null
+++ b/cli_ure/source/native/cli_cppuhelper_config
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="cli_cppuhelper" publicKeyToken="ce2cb7e279207b9e"/>
+ <bindingRedirect oldVersion="CLI_CPPUHELPER_OLD_VERSION" newVersion="CLI_CPPUHELPER_NEW_VERSION" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/cli_ure/source/native/native_bootstrap.cxx b/cli_ure/source/native/native_bootstrap.cxx
new file mode 100644
index 000000000..f26a634c2
--- /dev/null
+++ b/cli_ure/source/native/native_bootstrap.cxx
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "native_share.h"
+
+#include "rtl/bootstrap.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "cppuhelper/bootstrap.hxx"
+#include <memory>
+#include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <delayimp.h>
+
+#define INSTALL_PATH L"Software\\LibreOffice\\UNO\\InstallPath"
+#define UNO_PATH L"UNO_PATH"
+
+namespace {
+
+/* Gets the installation path from the Windows Registry for the specified
+ registry key.
+
+ @param hroot open handle to predefined root registry key
+ @param subKeyName name of the subkey to open
+
+ @return the installation path or nullptr, if no installation was found or
+ if an error occurred
+*/
+WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName )
+{
+ // open the specified registry key
+ HKEY hkey;
+ if ( RegOpenKeyExW( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
+ return nullptr;
+
+ struct CloseKeyGuard {
+ HKEY m_hkey;
+ ~CloseKeyGuard() { RegCloseKey( m_hkey ); }
+ } aCloseKeyGuard{hkey};
+
+ // find the type and size of the default value
+ DWORD type;
+ DWORD size;
+ if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, nullptr, &size ) != ERROR_SUCCESS )
+ return nullptr;
+
+ // get memory to hold the default value
+ std::unique_ptr<WCHAR[]> data(new WCHAR[size]);
+
+ // read the default value
+ if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, reinterpret_cast<LPBYTE>(data.get()), &size ) != ERROR_SUCCESS )
+ return nullptr;
+
+ return data.release();
+}
+
+/* Returns the path to the program folder of the brand layer,
+ for example C:/Program Files/LibreOffice/program
+ This path is either obtained from the environment variable UNO_PATH
+ or the registry item "Software\\LibreOffice\\UNO\\InstallPath"
+ either in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
+ The return value must be freed with delete[]
+*/
+WCHAR* getInstallPath()
+{
+ std::unique_ptr<WCHAR[]> szInstallPath;
+
+ DWORD cChars = GetEnvironmentVariableW(UNO_PATH, nullptr, 0);
+ if (cChars > 0)
+ {
+ szInstallPath.reset(new WCHAR[cChars]);
+ cChars = GetEnvironmentVariableW(UNO_PATH, szInstallPath.get(), cChars);
+ // If PATH is not set then it is no error
+ if (cChars == 0)
+ return nullptr;
+ }
+
+ if (! szInstallPath)
+ {
+ szInstallPath.reset(getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH ));
+ if (! szInstallPath)
+ {
+ // read the key's default value from HKEY_LOCAL_MACHINE
+ szInstallPath.reset(getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH ));
+ }
+ }
+ return szInstallPath.release();
+}
+
+/* We extend the path to contain the install folder,
+ so that components can use osl_loadModule with arguments, such as
+ "reg3.dll". That is, the arguments are only the library names.
+*/
+void extendPath(LPCWSTR szPath)
+{
+ if (!szPath)
+ return;
+
+ std::unique_ptr<WCHAR[]> sEnvPath;
+ DWORD cChars = GetEnvironmentVariableW(L"PATH", nullptr, 0);
+ if (cChars > 0)
+ {
+ sEnvPath.reset(new WCHAR[cChars]);
+ cChars = GetEnvironmentVariableW(L"PATH", sEnvPath.get(), cChars);
+ // If PATH is not set then it is no error
+ if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
+ return;
+ }
+ // Prepare the new PATH. Add the directory at the front.
+ // Note also adding ';'
+ std::unique_ptr<WCHAR[]> sNewPath(new WCHAR[lstrlenW(sEnvPath.get()) + lstrlenW(szPath) + 2]);
+ lstrcpyW(sNewPath.get(), szPath);
+ if (lstrlenW(sEnvPath.get()))
+ {
+ lstrcatW(sNewPath.get(), L";");
+ lstrcatW(sNewPath.get(), sEnvPath.get());
+ }
+ SetEnvironmentVariableW(L"PATH", sNewPath.get());
+}
+
+HMODULE loadFromPath(LPCSTR sLibName)
+{
+ if (!sLibName)
+ return nullptr;
+
+ // Convert the ansi file name to wchar_t*
+ int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, nullptr, 0);
+ if (size == 0)
+ return nullptr;
+ std::unique_ptr<WCHAR[]> wsLibName(new WCHAR[size]);
+ if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, wsLibName.get(), size))
+ return nullptr;
+
+ std::unique_ptr<WCHAR[]> szPath(getInstallPath());
+ if (!szPath)
+ return nullptr;
+
+ extendPath(szPath.get());
+
+ std::unique_ptr<WCHAR[]> szFullPath(new WCHAR[lstrlenW(wsLibName.get()) + lstrlenW(szPath.get()) + 2]);
+ lstrcpyW(szFullPath.get(), szPath.get());
+ lstrcatW(szFullPath.get(), L"\\");
+ lstrcatW(szFullPath.get(), wsLibName.get());
+ HMODULE handle = LoadLibraryW(szFullPath.get());
+ return handle;
+}
+
+/* Hook for delayed loading of libraries which this library is linked with.
+ This is a failure hook. That is, it is only called when the loading of
+ a library failed. It will be called when loading of cppuhelper failed.
+ Because we extend the PATH to the install folder while this function is
+ executed (see extendPath), all other libraries are found.
+*/
+extern "C" FARPROC WINAPI delayLoadHook(
+ unsigned int dliNotify,
+ PDelayLoadInfo pdli
+ )
+{
+ if (dliNotify == dliFailLoadLib)
+ {
+ HANDLE h = loadFromPath(pdli->szDll);
+ return reinterpret_cast<FARPROC>(h);
+ }
+ return nullptr;
+}
+}
+
+ExternC
+const PfnDliHook __pfnDliFailureHook2 = delayLoadHook;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace uno
+{
+namespace util
+{
+
+/** Bootstrapping native UNO.
+
+ Bootstrapping requires the existence of many libraries which are contained
+ in an URE installation. To find and load these libraries the Windows
+ registry keys HKEY_CURRENT_USER\Software\LibreOffice\Layer\URE\1
+ and HKEY_LOCAL_MACHINE\Software\LibreOffice\Layer\URE\1 are examined.
+ These contain a named value UREINSTALLLOCATION which holds a path to the URE
+ installation folder.
+*/
+public ref class Bootstrap sealed
+{
+ inline Bootstrap() {}
+
+public:
+
+ /** Bootstraps the initial component context from a native UNO installation.
+
+ @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
+ */
+ static ::unoidl::com::sun::star::uno::XComponentContext ^
+ defaultBootstrap_InitialComponentContext();
+
+ /** Bootstraps the initial component context from a native UNO installation.
+
+ @param ini_file
+ a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
+ reside next to the cppuhelper library)
+ @param bootstrap_parameters
+ bootstrap parameters (maybe null)
+
+ @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
+ */
+ static ::unoidl::com::sun::star::uno::XComponentContext ^
+ defaultBootstrap_InitialComponentContext(
+ ::System::String ^ ini_file,
+ ::System::Collections::IDictionaryEnumerator ^
+ bootstrap_parameters );
+
+ /** Bootstraps the initial component context from a native UNO installation.
+
+ @see cppuhelper/bootstrap.hxx:bootstrap()
+ */
+ static ::unoidl::com::sun::star::uno::XComponentContext ^
+ bootstrap();
+};
+
+
+::unoidl::com::sun::star::uno::XComponentContext ^
+Bootstrap::defaultBootstrap_InitialComponentContext(
+ ::System::String ^ ini_file,
+ ::System::Collections::IDictionaryEnumerator ^ bootstrap_parameters )
+{
+ if (nullptr != bootstrap_parameters)
+ {
+ bootstrap_parameters->Reset();
+ while (bootstrap_parameters->MoveNext())
+ {
+ OUString key(
+ String_to_ustring( safe_cast< ::System::String ^ >(
+ bootstrap_parameters->Key ) ) );
+ OUString value(
+ String_to_ustring( safe_cast< ::System::String ^ >(
+ bootstrap_parameters->Value ) ) );
+
+ ::rtl::Bootstrap::set( key, value );
+ }
+ }
+
+ // bootstrap native uno
+ Reference< XComponentContext > xContext;
+ if (nullptr == ini_file)
+ {
+ xContext = ::cppu::defaultBootstrap_InitialComponentContext();
+ }
+ else
+ {
+ xContext = ::cppu::defaultBootstrap_InitialComponentContext(
+ String_to_ustring( safe_cast< ::System::String ^ >( ini_file ) ) );
+ }
+
+ return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
+ to_cli( xContext ) );
+}
+
+
+::unoidl::com::sun::star::uno::XComponentContext ^
+Bootstrap::defaultBootstrap_InitialComponentContext()
+{
+ return defaultBootstrap_InitialComponentContext( nullptr, nullptr );
+}
+
+::unoidl::com::sun::star::uno::XComponentContext ^ Bootstrap::bootstrap()
+{
+ Reference<XComponentContext> xContext = ::cppu::bootstrap();
+ return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
+ to_cli( xContext ) );
+
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/native/native_share.h b/cli_ure/source/native/native_share.h
new file mode 100644
index 000000000..f733d2558
--- /dev/null
+++ b/cli_ure/source/native/native_share.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#using "cli_ure.dll"
+#using "cli_uretypes.dll"
+
+#include "rtl/ustring.hxx"
+#include <uno/lbnames.h>
+#include "uno/mapping.hxx"
+
+#include <vcclr.h>
+
+
+namespace uno
+{
+namespace util
+{
+
+
+inline ::System::String ^ ustring_to_String( OUString const & ustr )
+{
+ return gcnew ::System::String(
+ reinterpret_cast<wchar_t const *>(ustr.getStr()), 0, ustr.getLength());
+}
+
+inline OUString String_to_ustring( ::System::String ^ str )
+{
+ OSL_ASSERT( sizeof (wchar_t) == sizeof (sal_Unicode) );
+ pin_ptr<wchar_t const> chars = PtrToStringChars( str );
+ return OUString(reinterpret_cast<sal_Unicode const *>(chars), str->Length);
+}
+
+template< typename T >
+inline ::System::Object ^ to_cli(
+ css::uno::Reference< T > const & x )
+{
+ css::uno::Mapping mapping(
+ CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_CLI );
+ OSL_ASSERT( mapping.is() );
+ if (! mapping.is())
+ {
+ throw css::uno::RuntimeException(
+ "cannot get mapping from C++ to CLI!",
+ css::uno::Reference<
+ css::uno::XInterface >() );
+ }
+
+ intptr_t intptr =
+ reinterpret_cast< intptr_t >(
+ mapping.mapInterface( x.get(), cppu::UnoType<decltype(x)>::get() ) );
+ ::System::Runtime::InteropServices::GCHandle ^ handle = ::System::Runtime::InteropServices::GCHandle::FromIntPtr(::System::IntPtr(intptr));
+ ::System::Object ^ ret = handle->Target;
+ handle->Free();
+ return ret;
+}
+
+template< typename T >
+inline void to_uno(
+ css::uno::Reference< T > * pRet, ::System::Object ^ x )
+{
+ css::uno::Mapping mapping(
+ UNO_LB_CLI, CPPU_CURRENT_LANGUAGE_BINDING_NAME );
+ OSL_ASSERT( mapping.is() );
+ if (! mapping.is())
+ {
+ throw css::uno::RuntimeException(
+ "cannot get mapping from CLI to C++!",
+ css::uno::Reference<
+ css::uno::XInterface >() );
+ }
+
+ ::System::Runtime::InteropServices::GCHandle handle(
+ ::System::Runtime::InteropServices::GCHandle::Alloc( x ) );
+ T * ret = 0;
+ mapping.mapInterface(
+ reinterpret_cast< void ** >( &ret ),
+ reinterpret_cast< void * >(
+ ::System::Runtime::InteropServices::GCHandle::op_Explicit( handle )
+#if defined _WIN64
+ .ToInt64()
+#elif defined _WIN32
+ .ToInt32()
+#else
+#error ERROR: either _WIN64 or _WIN32 must be defined
+ ERROR: either _WIN64 or _WIN32 must be defined
+#endif
+ ),
+ cppu::UnoType<T>::get() );
+ handle.Free();
+ pRet->set( ret, SAL_NO_ACQUIRE /* takeover ownership */ );
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/native/path.cxx b/cli_ure/source/native/path.cxx
new file mode 100644
index 000000000..6fae51314
--- /dev/null
+++ b/cli_ure/source/native/path.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "sal/config.h"
+
+#if defined(_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "sal/types.h"
+
+namespace cli_ure {
+
+SAL_DLLPUBLIC_EXPORT WCHAR * filename(WCHAR * path) {
+ WCHAR * f = path;
+ for (WCHAR * p = path;;) {
+ switch (*p++) {
+ case L'\0':
+ return f;
+ case L'\\':
+ f = p;
+ break;
+ }
+ }
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/scripts/increment_version.pl b/cli_ure/source/scripts/increment_version.pl
new file mode 100644
index 000000000..df0c677a8
--- /dev/null
+++ b/cli_ure/source/scripts/increment_version.pl
@@ -0,0 +1,273 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+use warnings;
+use strict;
+use diagnostics;
+
+sub trim;
+sub readIncVersions($);
+sub processLine($$);
+sub checkName($);
+sub incrementNewVersion($);
+sub incrementOldVersion($);
+sub incrementPolicyVersion($);
+my $usage =
+"The tool increments the minor version of assemblies and the major version of ".
+"the respective policy files. This is only done if new uno types have been added since".
+"the last product update. This information is obtained from the file which is passed as ".
+"argument changedTypes. The names in the version file must have a particular form. ".
+"They must end on one of following terms: NEW_VERSION, OLD_VERSION, POLICY_VERSION\n".
+"If no new published types have been added then no output, argument newVersions, is written".
+"Usage is: \n increment_version.pl oldVersions incVersions newVersions changedTypes\n\n".
+"oldVersion: Contains name value pairs, which are used for forming the config files of ".
+"the policy assemblies, for building the assemblies. \n\n".
+"incVersions: File containing the names of which the versions are to be incremented. ".
+"Every line may only contain one name. The names must exactly match those from the ".
+"oldVersion file.\n\n".
+"newVersions: Contains all entries from oldVersions, but the values of the names,".
+"which occur in selection, have been incremented.\n\n".
+"changedTypes: File that contains the information if new published types have been added ".
+"since the last product update.\n\n" ;
+
+my $sNameForm =
+"The names must end on one of these names: NEW_VERSION, OLD_VERSION, POLICY_VERSION\n".
+"For example, valid names are: \n".
+"CLI_URETYPES_NEW_VERSION\nCLI_URETYPES_OLD_VERSION\nCLI_URETYPES_POLICY_VERSION\n";
+
+if (scalar @ARGV < 3) {
+ print $usage;
+ exit -1;
+}
+
+-e "$ARGV[0]" or die "Error: wrong arguments. \n".$usage;
+-e "$ARGV[1]" or die "Error: wrong arguments. \n".$usage;
+#-e "$ARGV[3]" or die "Error: wrong arguments. \n".$usage;
+
+# DISABLED: always increment
+#check if new types have been added since last release.
+#If not, then there is nothing to be done.
+#read in oldVersions line by line and apply the increment operation
+#open TYPES, "$ARGV[3]" or die "Cannot open to $ARGV[3] $!";
+
+my $newTypes;
+
+#We look for the line that contains the number of new types
+#while(<TYPES>)
+#{
+# if (/New and published types/i)
+# {
+# $_ =~ /=\s*(\d+)/;
+# if ( ! defined $1)
+# {
+# print "\n###$ARGV[3] contains an invalid entry for 'New and published types'. \n\n";
+# exit -1;
+# }
+# $newTypes = $1;
+# }
+#}
+
+#Check if changeTypes contained the line we are looking for
+#if (! defined $newTypes)
+#{
+# print "\n###$ARGV[3] does not contain entry about the new types ".
+# "or we are looking for the wrong string! \n\n";
+# exit -1;
+#}
+
+#if ( $newTypes == 0)
+#{
+# print "\nNo new UNO types since las product update.\n";
+# exit 0;
+#}
+#else
+#{
+# print "\nNew UNO types were added since last release. The version will be increased.\n\n";
+#}
+
+#read in incVersions in a list
+my @incVersions = readIncVersions($ARGV[1]);
+#print "@incVersions";
+
+#read in oldVersions line by line and apply the increment operation
+open OLDVERSION, "$ARGV[0]" or die "Cannot open to $ARGV[0] $!";
+
+#open file we want to write to
+open NEWVERSION, "> $ARGV[2]" or die "Cannot write to $ARGV[2] $!";
+
+print NEWVERSION processLine($_, @incVersions) while(<OLDVERSION>);
+
+close NEWVERSION;
+close OLDVERSION;
+
+exit 0;
+
+sub processLine($$)
+{
+ my $line = $_[0];
+ #skip empty lines
+ my $trimmed;
+ return $line if (length($trimmed = trim($line)) == 0);
+ #Skip comment symbol: #
+ return $line if ($trimmed =~ /^#/);
+
+ #Get the left part of '='
+ my $i = index($line, "=");
+ if( $i == -1)
+ {
+ print "Error: No '=' found in line:,: \n $line \n";
+ exit -1;
+ }
+ my $name = substr($line, 0, $i);
+ $name = trim($name);
+ #We do not check the names here because the file can contain
+ #other names, e.g. CLI_URETYPES_POLICY_ASSEMBLY
+ if (length($name) == 0) {
+ print "Wrong line in $ARGV[0]\n", $sNameForm;
+ exit -1;
+ }
+ my $value = substr($line, $i + 1);
+ $value = trim($value);
+
+ #Check if the entry shall be incremented, this information is in the second
+ #argument
+ my $found;
+ for(@incVersions) {
+ if ($_ eq $name) {
+ $found = 1;
+ last;
+ }
+ }
+ if ( ! defined($found)) {
+ return $line;
+ }
+
+ #Check if the name represents a version we need to change
+ if ($name =~ /NEW_VERSION$/)
+ {
+ $value = incrementNewVersion($value);
+ }
+ elsif ($name =~ /OLD_VERSION$/)
+ {
+ $value = incrementOldVersion($value);
+ }
+ elsif ($name =~ /POLICY_VERSION$/)
+ {
+ $value = incrementPolicyVersion($value);
+ }
+ else
+ {
+ #other name which we ignore
+ return $line;
+ }
+ return "${name}=${value}\n";
+}
+
+#The value of a new version has the form x.x.x.x
+#We increment the third position from the left.
+#Te argument must already be trimmed.
+sub incrementNewVersion($)
+{
+ my @parts = split /\./,$_[0];
+ if (scalar @parts != 4)
+ {
+ print "Error, no valid version given in $ARGV[0]\n. A 'new version' has four parts.";
+ exit -1;
+ }
+ $parts[2]++;
+ #build the version string and return
+ return "$parts[0].$parts[1].$parts[2].$parts[3]";
+}
+
+#The value of a new version has the form x.x.x.x-x.x.x.x
+#We increment the third position of the second part.
+#Te argument must already be trimmed.
+sub incrementOldVersion($)
+{
+ my @parts = split /[\.-]/,$_[0];
+ if (scalar @parts != 8)
+ {
+ print "Error, no valid version given in $ARGV[0]\n. A 'old version' has the form
+x.x.x.x-x.x.x.x\n.";
+ exit -1;
+ }
+ $parts[6]++;
+ return "$parts[0].$parts[1].$parts[2].$parts[3]-$parts[4].$parts[5].$parts[6].$parts[7]";
+ return $_[0];
+}
+
+sub incrementPolicyVersion($)
+{
+ my @parts = split /\./,$_[0];
+ if (scalar @parts != 4)
+ {
+ print "Error, no valid version given in $ARGV[0]\n. A 'policy version' has four parts.";
+ exit -1;
+ }
+ $parts[0]++;
+ #build the version string and return
+ return "$parts[0].$parts[1].$parts[2].$parts[3]";
+}
+
+
+sub readIncVersions($)
+{
+ open INC, $_[0] or die "Could not open $_[0] $!";
+ my $arg = $_[0];
+ my @names;
+
+ while(<INC>)
+ {
+ chomp;
+ #Skip empty lines
+ my $line;
+ if (length($line = trim($_)) == 0) {
+ next;
+ }
+ #Skip comment symbol: #
+ if ($line =~ /^#/) {
+ next;
+ }
+ if (!checkName($line)) {
+ print "Wrong entry in file $_[0]\n", $sNameForm;
+ exit -1;
+ }
+ push @names, $line;
+ }
+ print "No entries found in $arg\n" if(scalar @names == 0);
+ return @names;
+}
+
+#The argument must already be trimmed
+#returns 1 if ok
+sub checkName($)
+{
+ my $name = $_[0];
+ if ( $name !~/NEW_VERSION$|OLD_VERSION$|POLICY_VERSION$/) {
+ return 0;
+ }
+ return 1;
+}
+
+sub trim($)
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
diff --git a/cli_ure/source/scripts/subst_template.pl b/cli_ure/source/scripts/subst_template.pl
new file mode 100644
index 000000000..b3f90fef6
--- /dev/null
+++ b/cli_ure/source/scripts/subst_template.pl
@@ -0,0 +1,124 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+use warnings;
+use strict;
+use diagnostics;
+
+sub trim;
+sub readRedirectionValues($);
+
+my $usage =
+ "Usage is: \n subst_template.pl configTemplate redirections policyConfig
+
+ configTemplate: The config file which is used for the policy assembly. It
+ contains place holders for the binding redirection.
+
+ redirections: file containing the values for oldVersion and newVersion tags
+ which are used in the BindingRedirect element of the config files.
+
+ policyConfig: Name of the file in which we want to write the config file.
+";
+
+
+if (scalar @ARGV < 3) {
+ print $usage;
+ exit -1;
+}
+
+
+my %redirectionValue = readRedirectionValues($ARGV[1]);
+#print "|$_| |$redirectionValue{$_}|\n", for keys %redirectionValue;
+
+
+#Read config file in which we will replace the versions
+$/ = undef;
+open TEMPLATE, $ARGV[0] or die $!;
+my $templ = <TEMPLATE>;
+
+#Open the config file we are goint to write to
+open CONFIG, "> $ARGV[2]" or die "Cannot write to $ARGV[2] $!";
+
+#No substitute the place holders for oldVersion and new Version in the config template with
+#the values obtained from the redirections file
+for (keys %redirectionValue) {
+ $templ=~ s/\b$_\b/$redirectionValue{$_}/;
+}
+#Write the config file
+print CONFIG $templ;
+
+#Reads the key value pairs from the files, which name must be passed in
+#the parameter. The file contains lines of the form name=value, for example
+#CLI_TYPES_OLD_VERSION=1.1.0.0-1.1.1.0
+sub readRedirectionValues($)
+{
+ #Read in the values for the version redirection
+ open REDIR, $_[0] or die $!;
+
+ my %redirectionValues;
+
+ while (<REDIR>)
+ {
+ chomp;
+ my $trimmed;
+ #Skip empty lines
+ if (length($trimmed = trim($_)) == 0) {
+ next;
+ }
+
+ #Skip comment symbol: #
+ if ($trimmed =~ /^#/) {
+ next;
+ }
+
+ my @lineParts = split /=/,$_;
+
+ #Check if we have valid name value pairs.
+ if (scalar @lineParts != 2) {
+ print "Error: Values in $ARGV[1] are not correct (Entries must have the form name=value). Invalid line: \n$_\n";
+ exit -1;
+ }
+
+ #Trim the strings and check if they still contain characters
+ my $name = trim($lineParts[0]);
+ my $value = trim($lineParts[1]);
+ if (length($name) == 0 || length($value) == 0) {
+ print "Error: Values in $ARGV[1] are not correct. Invalid line: \n$_\n";
+ exit -1;
+ }
+
+ #Check if we have duplicate key names
+ for (keys %redirectionValues) {
+ if ( $name eq $_) {
+ print "Error: Values in $ARGV[1] are not correct. The name $_ is not unique.\n";
+ exit -1;
+ }
+ }
+
+ $redirectionValues{$name} = $value;
+ }
+ return %redirectionValues;
+}
+
+sub trim($)
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
diff --git a/cli_ure/source/uno_bridge/README.txt b/cli_ure/source/uno_bridge/README.txt
new file mode 100644
index 000000000..39b3ce364
--- /dev/null
+++ b/cli_ure/source/uno_bridge/README.txt
@@ -0,0 +1,20 @@
+Because of the LoaderLock bug in .NET Framework 1.0 and 1.1 the cli_uno.dll is linked
+with the /NOENTRY switch, which prevent that the C-runtime is initialized when loading
+the dll.
+
+Also I removed all static c++ objects which need construction by the CRT,
+exception handling seems to need an initialised CRT. Therefore
+I added CRT initialization code in uno_initEnvironment (cli_bridge.cxx)
+However there is no deinitialization done because bridge libraries remain
+in memory until the process dies. There is actually no good place where
+this had to be called. If we would do that we would have to implement that
+the bridge can be disposed.
+
+
+Sell also:
+
+http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconmixeddllloadingproblem.asp
+http://support.microsoft.com/?id=814472
+http://www.ddj.com/dept/windows/184416689
+http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx
+http://msdn2.microsoft.com/en-US/library/ms172219.aspx \ No newline at end of file
diff --git a/cli_ure/source/uno_bridge/cli_base.h b/cli_ure/source/uno_bridge/cli_base.h
new file mode 100644
index 000000000..bca780f7c
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_base.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_BASE_H
+#define INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_BASE_H
+
+#pragma unmanaged
+// Workaround: osl/mutex.h contains only a forward declaration of _oslMutexImpls.
+// When using the inline class in Mutex in osl/mutex.hxx, the loader needs to find
+// a declaration for the struct. If not found a TypeLoadException is being thrown.
+struct _oslMutexImpl
+{
+};
+#pragma managed
+#include <memory>
+#include "rtl/ustring.hxx"
+#include "typelib/typedescription.hxx"
+
+#using <system.dll>
+
+namespace cli_uno
+{
+System::Type^ loadCliType(System::String ^ typeName);
+System::Type^ mapUnoType(typelib_TypeDescription const * pTD);
+System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD);
+typelib_TypeDescriptionReference* mapCliType(System::Type^ cliType);
+OUString mapCliString(System::String ^ data);
+System::String^ mapUnoString(rtl_uString const * data);
+System::String^ mapUnoTypeName(rtl_uString const * typeName);
+
+ref struct Constants
+{
+ static System::String^ sXInterfaceName= gcnew System::String(
+ "unoidl.com.sun.star.uno.XInterface");
+ static System::String^ sObject= gcnew System::String("System.Object");
+ static System::String^ sType= gcnew System::String("System.Type");
+ static System::String^ sUnoidl= gcnew System::String("unoidl.");
+ static System::String^ sVoid= gcnew System::String("System.Void");
+ static System::String^ sAny= gcnew System::String("uno.Any");
+ static System::String^ sArArray= gcnew System::String("System.Array[]");
+ static System::String^ sBoolean= gcnew System::String("System.Boolean");
+ static System::String^ sChar= gcnew System::String("System.Char");
+ static System::String^ sByte= gcnew System::String("System.Byte");
+ static System::String^ sInt16= gcnew System::String("System.Int16");
+ static System::String^ sUInt16= gcnew System::String("System.UInt16");
+ static System::String^ sInt32= gcnew System::String("System.Int32");
+ static System::String^ sUInt32= gcnew System::String("System.UInt32");
+ static System::String^ sInt64= gcnew System::String("System.Int64");
+ static System::String^ sUInt64= gcnew System::String("System.UInt64");
+ static System::String^ sString= gcnew System::String("System.String");
+ static System::String^ sSingle= gcnew System::String("System.Single");
+ static System::String^ sDouble= gcnew System::String("System.Double");
+ static System::String^ sArBoolean= gcnew System::String("System.Boolean[]");
+ static System::String^ sArChar= gcnew System::String("System.Char[]");
+ static System::String^ sArByte= gcnew System::String("System.Byte[]");
+ static System::String^ sArInt16= gcnew System::String("System.Int16[]");
+ static System::String^ sArUInt16= gcnew System::String("System.UInt16[]");
+ static System::String^ sArInt32= gcnew System::String("System.Int32[]");
+ static System::String^ sArUInt32= gcnew System::String("System.UInt32[]");
+ static System::String^ sArInt64= gcnew System::String("System.Int64[]");
+ static System::String^ sArUInt64= gcnew System::String("System.UInt64[]");
+ static System::String^ sArString= gcnew System::String("System.String[]");
+ static System::String^ sArSingle= gcnew System::String("System.Single[]");
+ static System::String^ sArDouble= gcnew System::String("System.Double[]");
+ static System::String^ sArType= gcnew System::String("System.Type[]");
+ static System::String^ sArObject= gcnew System::String("System.Object[]");
+ static System::String^ sBrackets= gcnew System::String("[]");
+ static System::String^ sAttributeSet= gcnew System::String("set_");
+ static System::String^ sAttributeGet= gcnew System::String("get_");
+
+ static System::String^ usXInterface = "com.sun.star.uno.XInterface";
+ static System::String^ usVoid = "void";
+ static System::String^ usType = "type";
+ static System::String^ usAny = "any";
+ static System::String^ usBrackets = "[]";
+ static System::String^ usBool = "boolean";
+ static System::String^ usByte = "byte";
+ static System::String^ usChar = "char";
+ static System::String^ usShort = "short";
+ static System::String^ usUShort = "unsigned short";
+ static System::String^ usLong = "long";
+ static System::String^ usULong = "unsigned long";
+ static System::String^ usHyper = "hyper";
+ static System::String^ usUHyper = "unsigned hyper";
+ static System::String^ usString = "string";
+ static System::String^ usFloat = "float";
+ static System::String^ usDouble = "double";
+};
+
+struct BridgeRuntimeError
+{
+ OUString m_message;
+
+ inline BridgeRuntimeError( OUString const & message )
+ : m_message( message )
+ {}
+};
+
+
+struct rtl_mem
+{
+ inline static void * operator new ( size_t nSize )
+ { return std::malloc( nSize ); }
+ inline static void operator delete ( void * mem )
+ { std::free( mem ); }
+ inline static void * operator new ( size_t, void * mem )
+ { return mem; }
+ inline static void operator delete ( void *, void * )
+ {}
+
+ static inline std::unique_ptr< rtl_mem > allocate( std::size_t bytes );
+};
+
+inline std::unique_ptr< rtl_mem > rtl_mem::allocate( std::size_t bytes )
+{
+ void * p = std::malloc( bytes );
+ if (0 == p)
+ throw BridgeRuntimeError("out of memory!" );
+ return std::unique_ptr< rtl_mem >( (rtl_mem *)p );
+}
+
+
+class TypeDescr
+{
+ typelib_TypeDescription * m_td;
+
+ TypeDescr( TypeDescr const & ) = delete;
+ TypeDescr& operator = ( TypeDescr const & ) = delete;
+
+public:
+ inline explicit TypeDescr( typelib_TypeDescriptionReference * td_ref );
+ inline ~TypeDescr()
+ { TYPELIB_DANGER_RELEASE( m_td ); }
+
+ inline typelib_TypeDescription * get() const
+ { return m_td; }
+};
+
+inline TypeDescr::TypeDescr( typelib_TypeDescriptionReference * td_ref )
+ : m_td( 0 )
+{
+ TYPELIB_DANGER_GET( &m_td, td_ref );
+ if (0 == m_td)
+ {
+ throw BridgeRuntimeError(
+ "cannot get comprehensive type description for " +
+ OUString::unacquired(&td_ref->pTypeName) );
+ }
+}
+
+
+} //end namespace cli_uno
+ #endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_bridge.cxx b/cli_ure/source/uno_bridge/cli_bridge.cxx
new file mode 100644
index 000000000..d9b4cdd0b
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_bridge.cxx
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcclr.h>
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include "uno/environment.hxx"
+#include "uno/lbnames.h"
+#include "uno/mapping.hxx"
+#include "typelib/typedescription.hxx"
+#include "rtl/ustring.hxx"
+#include <sal/log.hxx>
+
+#include "cli_bridge.h"
+#include "cli_proxy.h"
+
+namespace sri= System::Runtime::InteropServices;
+
+namespace cli_uno
+{
+
+extern "C"
+{
+void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ that->m_bridge->acquire();
+}
+
+void SAL_CALL Mapping_release( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ that->m_bridge->release();
+}
+
+
+void SAL_CALL Mapping_cli2uno(
+ uno_Mapping * mapping, void ** ppOut,
+ void * pIn, typelib_InterfaceTypeDescription * td )
+ SAL_THROW_EXTERN_C()
+{
+ uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
+ intptr_t cliI = (intptr_t)pIn;
+
+ OSL_ENSURE( ppUnoI && td, "### null ptr!" );
+
+ if (0 != *ppUnoI)
+ {
+ uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
+ (*pUnoI->release)( pUnoI );
+ *ppUnoI = 0;
+ }
+ try
+ {
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ Bridge * bridge = that->m_bridge;
+
+ if (0 != cliI)
+ {
+ System::Object^ cliObj= sri::GCHandle::FromIntPtr(IntPtr(cliI)).Target;
+ (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+ (void) err;
+ SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
+ }
+}
+
+void SAL_CALL Mapping_uno2cli(
+ uno_Mapping * mapping, void ** ppOut,
+ void * pIn, typelib_InterfaceTypeDescription * td )
+ SAL_THROW_EXTERN_C()
+{
+ try
+ {
+ OSL_ENSURE( td && ppOut, "### null ptr!" );
+ OSL_ENSURE( (sizeof(System::Char) == sizeof(sal_Unicode))
+ && (sizeof(System::Boolean) == sizeof(sal_Bool))
+ && (sizeof(System::SByte) == sizeof(sal_Int8))
+ && (sizeof(System::Int16) == sizeof(sal_Int16))
+ && (sizeof(System::UInt16) == sizeof(sal_uInt16))
+ && (sizeof(System::Int32) == sizeof(sal_Int32))
+ && (sizeof(System::UInt32) == sizeof(sal_uInt32))
+ && (sizeof(System::Int64) == sizeof(sal_Int64))
+ && (sizeof(System::UInt64) == sizeof(sal_uInt64))
+ && (sizeof(System::Single) == sizeof(float))
+ && (sizeof(System::Double) == sizeof(double)),
+ "[cli_uno bridge] incompatible .NET data types");
+ intptr_t * ppDNetI = (intptr_t *)ppOut;
+ uno_Interface * pUnoI = (uno_Interface *)pIn;
+
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ Bridge * bridge = that->m_bridge;
+
+ if (0 != *ppDNetI)
+ {
+ sri::GCHandle::FromIntPtr(IntPtr(ppDNetI)).Free();
+ }
+
+ if (0 != pUnoI)
+ {
+ System::Object^ cliI= bridge->map_uno2cli(pUnoI, td);
+ intptr_t ptr= NULL;
+ if(cliI)
+ {
+ ptr= sri::GCHandle::ToIntPtr(sri::GCHandle::Alloc(cliI))
+#ifdef _WIN64
+ .ToInt64();
+#else /* defined(_WIN32) */
+ .ToInt32();
+#endif
+ }
+ (*ppOut)= reinterpret_cast<void*>(ptr);
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+ (void) err;
+ SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
+ }
+}
+
+
+void SAL_CALL Bridge_free( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * that = static_cast< Mapping * >( mapping );
+ delete that->m_bridge;
+}
+
+} //extern C
+} //namespace
+
+namespace cli_uno
+{
+
+
+/** ToDo
+ I doubt that the case that the ref count raises from 0 to 1
+ can occur. uno_ext_getMapping returns an acquired mapping. Every time
+ that function is called then a new mapping is created. Following the
+ rules of ref counted objects, then if the ref count is null no one has
+ a reference to the object anymore. Hence no one can call acquire. If someone
+ calls acquire then they must have kept an unacquired pointer which is
+ illegal.
+ */
+void Bridge::acquire() const
+{
+ if (1 == osl_atomic_increment( &m_ref ))
+ {
+ if (m_registered_cli2uno)
+ {
+ uno_Mapping * mapping = const_cast<Mapping*>(&m_cli2uno);
+ uno_registerMapping(
+ const_cast<uno_Mapping**>(&mapping), Bridge_free, m_uno_cli_env, (uno_Environment *)m_uno_env, 0 );
+ }
+ else
+ {
+ uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli);
+ uno_registerMapping(
+ &mapping, Bridge_free, (uno_Environment *)m_uno_env, m_uno_cli_env, 0 );
+ }
+ }
+}
+
+void Bridge::release() const
+{
+ if (! osl_atomic_decrement( &m_ref ))
+ {
+ uno_revokeMapping(
+ m_registered_cli2uno
+ ? const_cast<Mapping*>(&m_cli2uno)
+ : const_cast<Mapping*>(&m_uno2cli) );
+ }
+}
+
+Bridge::Bridge(
+ uno_Environment * uno_cli_env, uno_ExtEnvironment * uno_env,
+ bool registered_cli2uno )
+ : m_ref( 1 ),
+ m_uno_env( uno_env ),
+ m_uno_cli_env( uno_cli_env ),
+ m_registered_cli2uno( registered_cli2uno )
+{
+ OSL_ASSERT( 0 != m_uno_cli_env && 0 != m_uno_env );
+ (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env );
+ (*m_uno_cli_env->acquire)( m_uno_cli_env );
+
+ // cli2uno
+ m_cli2uno.acquire = Mapping_acquire;
+ m_cli2uno.release = Mapping_release;
+ m_cli2uno.mapInterface = Mapping_cli2uno;
+ m_cli2uno.m_bridge = this;
+ // uno2cli
+ m_uno2cli.acquire = Mapping_acquire;
+ m_uno2cli.release = Mapping_release;
+ m_uno2cli.mapInterface = Mapping_uno2cli;
+ m_uno2cli.m_bridge = this;
+
+}
+
+
+Bridge::~Bridge()
+{
+ //System::GC::Collect();
+ (*m_uno_cli_env->release)( m_uno_cli_env );
+ (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env );
+}
+
+
+} //namespace cli_uno
+
+extern "C"
+{
+
+namespace cli_uno
+{
+
+void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
+ SAL_THROW_EXTERN_C()
+{
+ uno_cli_env->pContext = 0;
+}
+
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
+ SAL_THROW_EXTERN_C()
+{
+ //ToDo: remove when compiled with .NET 2
+
+ // Unclear whether the above comment refers to this whole function
+ // or a call to __crt_dll_initialize() that used to be here for
+ // _MSC_VER < 1400
+
+ uno_cli_env->environmentDisposing= cli_env_disposing;
+ uno_cli_env->pExtEnv = 0;
+ //Set the console to print Trace messages
+#if OSL_DEBUG_LEVEL >= 1
+ System::Diagnostics::Trace::Listeners->
+ Add( gcnew System::Diagnostics::TextWriterTraceListener(System::Console::Out));
+#endif
+ OSL_ASSERT( 0 == uno_cli_env->pContext );
+
+ // We let the Cli_environment leak, since there is no good point where we could destruct it.
+ //dispose is not used because we would have then also synchronize the calls to proxies. If the
+ //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points
+ //where g_cli_env is accessed.
+ //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot
+ //member in a unmanaged class, such as Bridge.
+ CliEnvHolder::g_cli_env = gcnew Cli_environment();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_ext_getMapping(
+ uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
+ if (*ppMapping)
+ {
+ (*(*ppMapping)->release)( *ppMapping );
+ *ppMapping = 0;
+ }
+
+
+ OUString const & from_env_typename = OUString::unacquired(
+ &pFrom->pTypeName );
+ OUString const & to_env_typename = OUString::unacquired( &pTo->pTypeName );
+
+ uno_Mapping * mapping = 0;
+
+ try
+ {
+ if ( from_env_typename == UNO_LB_CLI && to_env_typename == UNO_LB_UNO )
+ {
+ Bridge * bridge = new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
+ mapping = &bridge->m_cli2uno;
+ uno_registerMapping(
+ &mapping, Bridge_free, pFrom, (uno_Environment *)pTo->pExtEnv, 0 );
+ }
+ else if ( from_env_typename == UNO_LB_UNO && to_env_typename == UNO_LB_CLI )
+ {
+ Bridge * bridge = new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
+ mapping = &bridge->m_uno2cli;
+ uno_registerMapping(
+ &mapping, Bridge_free, (uno_Environment *)pFrom->pExtEnv, pTo, 0 );
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+ (void) err;
+ SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
+ }
+ *ppMapping = mapping;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_bridge.h b/cli_ure/source/uno_bridge/cli_bridge.h
new file mode 100644
index 000000000..95ddb0394
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_bridge.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_BRIDGE_H
+#define INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_BRIDGE_H
+#include <vcclr.h>
+#include "osl/interlck.h"
+#include "uno/mapping.h"
+#include "uno/environment.h"
+#include "uno/dispatcher.h"
+#include "cli_base.h"
+#include "cli_environment.h"
+//#using <cli_uretypes.dll>
+#using <cli_basetypes.dll>
+#using <system.dll>
+
+namespace sr = System::Reflection;
+
+namespace cli_uno
+{
+
+
+// holds environments and mappings
+struct Bridge;
+struct Mapping : public uno_Mapping
+{
+ Bridge* m_bridge;
+};
+
+// The environment will be created in uno_initEnvironment. See also the remarks there
+//Managed cli environment for cli objects a UNO proxies (which are cli
+//objects. The uno_Environment is not used for cli objects.
+ref struct CliEnvHolder {
+static Cli_environment ^ g_cli_env = nullptr;
+};
+
+
+/** An instance of Bridge represents exactly one mapping therefore either
+ m_cli2uno or m_uno2cli is valid.
+*/
+struct Bridge
+{
+ mutable oslInterlockedCount m_ref;
+ uno_ExtEnvironment * m_uno_env;
+ uno_Environment * m_uno_cli_env;
+
+ Mapping m_cli2uno;
+ Mapping m_uno2cli;
+ bool m_registered_cli2uno;
+
+ ~Bridge();
+ Bridge( uno_Environment * java_env, uno_ExtEnvironment * uno_env, bool registered_java2uno );
+
+ void acquire() const;
+ void release() const;
+
+ void map_to_uno(
+ void * uno_data, System::Object^ cli_data,
+ typelib_TypeDescriptionReference * type,
+ bool assign) const;
+
+ /**
+ @param info
+ the type of the converted data. It may be a byref type.
+ */
+ void map_to_cli(
+ System::Object^ *cli_data, void const * uno_data,
+ typelib_TypeDescriptionReference * type, System::Type^ info /* maybe 0 */,
+ bool bDontCreateObj) const;
+
+ System::Object^ map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription* pTD) const;
+
+ System::Object^ call_uno(uno_Interface * pUnoI,
+ typelib_TypeDescription* member_td,
+ typelib_TypeDescriptionReference * return_type,
+ sal_Int32 nParams, typelib_MethodParameter const * pParams,
+ array<System::Object^>^ args, array<System::Type^>^ argTypes,
+ System::Object^* pException) const;
+
+
+ void call_cli(
+ System::Object^ cliI, sr::MethodInfo^ method,
+ typelib_TypeDescriptionReference * return_type,
+ typelib_MethodParameter * params, int nParams,
+ void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const;
+
+ uno_Interface * map_cli2uno(
+ System::Object^ cliI, typelib_TypeDescription* pTD) const;
+
+};
+
+} //namespace cli_uno
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_data.cxx b/cli_ure/source/uno_bridge/cli_data.cxx
new file mode 100644
index 000000000..72b39df48
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_data.cxx
@@ -0,0 +1,1929 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#include <ole2.h>
+
+#include <memory>
+
+#include "rtl/ustring.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "uno/sequence2.h"
+#include "typelib/typedescription.hxx"
+#include "cli_proxy.h"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+#using <cli_uretypes.dll>
+
+#undef VOID
+
+namespace sri = System::Runtime::InteropServices;
+namespace sr = System::Reflection;
+namespace st = System::Text;
+namespace ucss = unoidl::com::sun::star;
+
+
+namespace cli_uno
+{
+System::String^ mapUnoPolymorphicName(System::String^ unoName);
+OUString mapCliTypeName(System::String^ typeName);
+System::String^ mapCliPolymorphicName(System::String^ unoName);
+System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno);
+
+inline std::unique_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize )
+{
+ std::unique_ptr< rtl_mem > seq(
+ rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) );
+ uno_Sequence * p = (uno_Sequence *)seq.get();
+ p->nRefCount = 1;
+ p->nElements = nElements;
+ return seq;
+}
+
+System::Object^ Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const
+{
+ System::Object^ retVal= nullptr;
+ // get oid
+ rtl_uString * pOid = 0;
+ (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
+ OSL_ASSERT( 0 != pOid );
+ OUString oid(pOid, SAL_NO_ACQUIRE);
+
+ // see if the interface was already mapped
+ System::Type^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
+ System::String^ sOid= mapUnoString(oid.pData);
+
+ System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env );
+ try
+ {
+ retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType);
+ if (retVal)
+ {
+ // There is already a registered object. It can either be a proxy
+ // for the UNO object or a real cli object. In the first case we
+ // tell the proxy that it shall also represent the current UNO
+ // interface. If it already does that, then it does nothing
+ if (srr::RemotingServices::IsTransparentProxy(retVal))
+ {
+ UnoInterfaceProxy^ p = static_cast<UnoInterfaceProxy^>(
+ srr::RemotingServices::GetRealProxy(retVal));
+ p->addUnoInterface(pUnoI, pTD);
+ }
+ }
+ else
+ {
+ retVal = UnoInterfaceProxy::create(
+ (Bridge *) this, pUnoI, pTD, oid );
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
+ }
+
+ return retVal;
+}
+
+uno_Interface* Bridge::map_cli2uno(System::Object^ cliObj, typelib_TypeDescription *pTD) const
+{
+ uno_Interface* retIface = NULL;
+ // get oid from dot net environment
+ System::String^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
+ OUString ousOid = mapCliString(ds_oid);
+ // look if interface is already mapped
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ System::Threading::Monitor::Enter(Cli_environment::typeid);
+ try
+ {
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit(Cli_environment::typeid);
+ }
+ }
+ return retIface;
+}
+
+inline System::Type^ loadCliType(rtl_uString * unoName)
+{
+ return loadCliType(mapUnoTypeName(unoName));
+}
+
+System::Type^ loadCliType(System::String ^ unoName)
+{
+ System::Type^ retVal= nullptr;
+ try
+ {
+ //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char>
+ //then we remove the type list, otherwise the type could not be loaded.
+ bool bIsPolymorphic = false;
+
+ System::String ^ loadName = unoName;
+ int index = unoName->IndexOf('<');
+ if (index != -1)
+ {
+ loadName = unoName->Substring(0, index);
+ bIsPolymorphic = true;
+ }
+ System::AppDomain^ currentDomain = System::AppDomain::CurrentDomain;
+ cli::array<sr::Assembly^>^ assems = currentDomain->GetAssemblies();
+ for (int i = 0; i < assems->Length; i++)
+ {
+ retVal = assems[i]->GetType(loadName, false);
+ if (retVal)
+ break;
+ }
+
+ if (retVal == nullptr)
+ {
+ System::String ^ msg = gcnew System::String("A type could not be loaded: ");
+ msg = System::String::Concat(msg, loadName);
+ throw BridgeRuntimeError(mapCliString(msg));
+ }
+
+ if (bIsPolymorphic)
+ {
+ retVal = uno::PolymorphicType::GetType(retVal, unoName);
+ }
+ }
+ catch( System::Exception ^ e)
+ {
+ OUString ouMessage(mapCliString(e->Message));
+ throw BridgeRuntimeError(ouMessage);
+ }
+ return retVal;
+}
+
+System::Type^ mapUnoType(typelib_TypeDescription const * pTD)
+{
+ return mapUnoType(pTD->pWeakRef);
+}
+
+System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD)
+{
+ System::Type ^ retVal = nullptr;
+ switch (pTD->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ retVal= void::typeid; break;
+ case typelib_TypeClass_CHAR:
+ retVal= System::Char::typeid; break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= System::Boolean::typeid; break;
+ case typelib_TypeClass_BYTE:
+ retVal= System::Byte::typeid; break;
+ case typelib_TypeClass_SHORT:
+ retVal= System::Int16::typeid; break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= System::UInt16::typeid; break;
+ case typelib_TypeClass_LONG:
+ retVal= System::Int32::typeid; break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= System::UInt32::typeid; break;
+ case typelib_TypeClass_HYPER:
+ retVal= System::Int64::typeid; break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= System::UInt64::typeid; break;
+ case typelib_TypeClass_FLOAT:
+ retVal= System::Single::typeid; break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= System::Double::typeid; break;
+ case typelib_TypeClass_STRING:
+ retVal= System::String::typeid; break;
+ case typelib_TypeClass_TYPE:
+ retVal= System::Type::typeid; break;
+ case typelib_TypeClass_ANY:
+ retVal= uno::Any::typeid; break;
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ retVal= loadCliType(pTD->pTypeName); break;
+ case typelib_TypeClass_INTERFACE:
+ {
+ //special handling for XInterface, since it does not exist in cli.
+ OUString usXInterface("com.sun.star.uno.XInterface");
+ if (usXInterface.equals(pTD->pTypeName))
+ retVal= System::Object::typeid;
+ else
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ css::uno::TypeDescription seqType(
+ const_cast<typelib_TypeDescriptionReference*>(pTD));
+ typelib_TypeDescriptionReference* pElementTDRef=
+ reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType;
+ switch (pElementTDRef->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArChar)); break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArBoolean));
+ break;
+ case typelib_TypeClass_BYTE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArByte));
+ break;
+ case typelib_TypeClass_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt16));
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt16));
+ break;
+ case typelib_TypeClass_LONG:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt32));
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt32));
+ break;
+ case typelib_TypeClass_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt64));
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt64));
+ break;
+ case typelib_TypeClass_FLOAT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArSingle));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArDouble));
+ break;
+ case typelib_TypeClass_STRING:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArString));
+ break;
+ case typelib_TypeClass_TYPE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArType));
+ break;
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_INTERFACE:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ default:
+ //All cases should be handled by the case statements above
+ OSL_ASSERT(0);
+ break;
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ return retVal;
+}
+
+/** Returns an acquired td.
+ */
+typelib_TypeDescriptionReference* mapCliType(System::Type^ cliType)
+{
+ typelib_TypeDescriptionReference* retVal= NULL;
+ if (cliType == nullptr)
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ return retVal;
+ }
+ //check for Enum first,
+ //because otherwise case System::TypeCode::Int32 applies
+ if (cliType->IsEnum)
+ {
+ OUString usTypeName= mapCliTypeName(cliType->FullName);
+ css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
+ retVal= unoType.getTypeLibType();
+ typelib_typedescriptionreference_acquire(retVal);
+ }
+ else
+ {
+ switch (System::Type::GetTypeCode(cliType))
+ {
+ case System::TypeCode::Boolean:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BOOLEAN );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Char:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_CHAR );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Byte:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BYTE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Single:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_FLOAT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Double:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_DOUBLE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::String:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_STRING );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ default:
+ break;
+ }
+ }
+ if (retVal == NULL)
+ {
+ System::String^ cliTypeName= cliType->FullName;
+ // Void
+ if (const_cast<System::String^>(Constants::sVoid)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Type
+ else if (const_cast<System::String^>(Constants::sType)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_TYPE );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Any
+ else if (const_cast<System::String^>(Constants::sAny)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_ANY );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ //struct, interfaces, sequences
+ else
+ {
+ OUString usTypeName;
+ uno::PolymorphicType ^ poly = dynamic_cast<uno::PolymorphicType^>(cliType);
+ if (poly != nullptr)
+ usTypeName = mapCliTypeName( poly->PolymorphicName);
+ else
+ usTypeName = mapCliTypeName(cliTypeName);
+ typelib_TypeDescription* td = NULL;
+ typelib_typedescription_getByName(&td, usTypeName.pData);
+ if (td)
+ {
+ retVal = td->pWeakRef;
+ typelib_typedescriptionreference_acquire(retVal);
+ typelib_typedescription_release(td);
+ }
+ }
+ }
+ if (retVal == NULL)
+ {
+ throw BridgeRuntimeError("[cli_uno bridge] mapCliType():could not map type: " + mapCliString(cliType->FullName));
+ }
+ return retVal;
+}
+
+/**
+ Otherwise a leading "unoidl." is removed.
+ */
+System::String^ mapUnoTypeName(rtl_uString const * typeName)
+{
+ OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
+ st::StringBuilder^ buf= gcnew st::StringBuilder();
+ //determine if the type is a sequence and its dimensions
+ int dims= 0;
+ if (usUnoName[0] == '[')
+ {
+ sal_Int32 index= 1;
+ while (true)
+ {
+ if (usUnoName[index++] == ']')
+ dims++;
+ if (usUnoName[index++] != '[')
+ break;
+ }
+ usUnoName = usUnoName.copy(index - 1);
+ }
+ System::String ^ sUnoName = mapUnoString(usUnoName.pData);
+ if (sUnoName->Equals(const_cast<System::String^>(Constants::usBool)))
+ buf->Append(const_cast<System::String^>(Constants::sBoolean));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usChar)))
+ buf->Append(const_cast<System::String^>(Constants::sChar));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usByte)))
+ buf->Append(const_cast<System::String^>(Constants::sByte));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usShort)))
+ buf->Append(const_cast<System::String^>(Constants::sInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUShort)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usLong)))
+ buf->Append(const_cast<System::String^>(Constants::sInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usULong)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usFloat)))
+ buf->Append(const_cast<System::String^>(Constants::sSingle));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usDouble)))
+ buf->Append(const_cast<System::String^>(Constants::sDouble));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usString)))
+ buf->Append(const_cast<System::String^>(Constants::sString));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usVoid)))
+ buf->Append(const_cast<System::String^>(Constants::sVoid));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usType)))
+ buf->Append(const_cast<System::String^>(Constants::sType));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usXInterface)))
+ buf->Append(const_cast<System::String^>(Constants::sObject));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usAny)))
+ {
+ buf->Append(const_cast<System::String^>(Constants::sAny));
+ }
+ else
+ {
+ //put "unoidl." at the beginning
+ buf->Append(const_cast<System::String^>(Constants::sUnoidl));
+ //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
+ System::String ^ sName = mapUnoPolymorphicName(sUnoName);
+ buf->Append(sName);
+ }
+ // append []
+ for (;dims--;)
+ buf->Append(const_cast<System::String^>(Constants::sBrackets));
+
+ return buf->ToString();
+}
+
+/** For example, there is a uno type
+ com.sun.star.Foo<char, long>.
+ The values in the type list
+ are uno types and are replaced by cli types, such as System.Char,
+ System.Int32, etc.
+ The prefix unoidl is not added.
+ */
+inline System::String^ mapUnoPolymorphicName(System::String^ unoName)
+{
+ return mapPolymorphicName(unoName, false);
+}
+
+/** For example, there is a type name such as
+ com.sun.star.Foo<System.Char, System.Int32>.
+ The values in the type list
+ are CLI types and are replaced by uno types, such as char,
+ long, etc.
+ The prefix unoidl remains.
+ */
+inline System::String^ mapCliPolymorphicName(System::String^ unoName)
+{
+ return mapPolymorphicName(unoName, true);
+}
+
+System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno)
+{
+ int index = unoName->IndexOf('<');
+ if (index == -1)
+ return unoName;
+
+ System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256);
+ builder->Append(unoName->Substring(0, index +1 ));
+
+ //Find the first occurrence of ','
+ //If the parameter is a polymorphic struct then we need to ignore everything
+ //between the brackets because it can also contain commas
+ //get the type list within < and >
+ int endIndex = unoName->Length - 1;
+ index++;
+ int cur = index;
+ int countParams = 0;
+ while (cur <= endIndex)
+ {
+ System::Char c = unoName[cur];
+ if (c == ',' || c == '>')
+ {
+ //insert a comma if needed
+ if (countParams != 0)
+ builder->Append(",");
+ countParams++;
+ System::String ^ sParam = unoName->Substring(index, cur - index);
+ //skip the comma
+ cur++;
+ //the index to the beginning of the next param
+ index = cur;
+ if (bCliToUno)
+ {
+ builder->Append(mapCliTypeName(sParam).getStr());
+ }
+ else
+ {
+ OUString s = mapCliString(sParam);
+ builder->Append(mapUnoTypeName(s.pData));
+ }
+ }
+ else if (c == '<')
+ {
+ cur++;
+ //continue until the matching '>'
+ int numNested = 0;
+ for (;;cur++)
+ {
+ System::Char curChar = unoName[cur];
+ if (curChar == '<')
+ {
+ numNested ++;
+ }
+ else if (curChar == '>')
+ {
+ if (numNested > 0)
+ numNested--;
+ else
+ break;
+ }
+ }
+ }
+ cur++;
+ }
+
+ builder->Append((System::Char) '>');
+ return builder->ToString();
+}
+
+OUString mapCliTypeName(System::String^ typeName)
+{
+ int dims= 0;
+ // Array? determine the "rank" (number of "[]")
+ // move from the rightmost end to the left, for example
+ // unoidl.PolymorphicStruct<System.Char[]>[]
+ // has only a "dimension" of 1
+ int cur = typeName->Length - 1;
+ bool bRightBracket = false;
+ while (cur >= 0)
+ {
+ System::Char c = typeName[cur];
+ if (c == ']')
+ {
+ bRightBracket = true;
+ }
+ else if (c == '[')
+ {
+ if (!bRightBracket)
+ throw BridgeRuntimeError(
+ "Typename is wrong. No matching brackets for sequence. Name is: " +
+ mapCliString(typeName));
+ bRightBracket = false;
+ dims ++;
+ }
+ else
+ {
+ if (bRightBracket)
+ throw BridgeRuntimeError(
+ "Typename is wrong. No matching brackets for sequence. Name is: " +
+ mapCliString(typeName));
+ break;
+ }
+ cur--;
+ }
+
+ if (bRightBracket || cur < 0)
+ throw BridgeRuntimeError(
+ "Typename is wrong. " +
+ mapCliString(typeName));
+
+ typeName = typeName->Substring(0, cur + 1);
+
+ System::Text::StringBuilder ^ buf = gcnew System::Text::StringBuilder(512);
+
+ //Put the "[]" at the beginning of the uno type name
+ for (;dims--;)
+ buf->Append(const_cast<System::String^>(Constants::usBrackets));
+
+ if (typeName->Equals(const_cast<System::String^>(Constants::sBoolean)))
+ buf->Append(const_cast<System::String^>(Constants::usBool));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sChar)))
+ buf->Append(const_cast<System::String^>(Constants::usChar));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sByte)))
+ buf->Append(const_cast<System::String^>(Constants::usByte));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt16)))
+ buf->Append(const_cast<System::String^>(Constants::usShort));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt16)))
+ buf->Append(const_cast<System::String^>(Constants::usUShort));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt32)))
+ buf->Append(const_cast<System::String^>(Constants::usLong));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt32)))
+ buf->Append(const_cast<System::String^>(Constants::usULong));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt64)))
+ buf->Append(const_cast<System::String^>(Constants::usHyper));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt64)))
+ buf->Append(const_cast<System::String^>(Constants::usUHyper));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sSingle)))
+ buf->Append(const_cast<System::String^>(Constants::usFloat));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sDouble)))
+ buf->Append(const_cast<System::String^>(Constants::usDouble));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sString)))
+ buf->Append(const_cast<System::String^>(Constants::usString));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sVoid)))
+ buf->Append(const_cast<System::String^>(Constants::usVoid));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sType)))
+ buf->Append(const_cast<System::String^>(Constants::usType));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sObject)))
+ buf->Append(const_cast<System::String^>(Constants::usXInterface));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sAny)))
+ buf->Append(const_cast<System::String^>(Constants::usAny));
+ else
+ {
+ System::String ^ sName = mapCliPolymorphicName(typeName);
+ int i= sName->IndexOf(L'.');
+ buf->Append(sName->Substring(i + 1));
+ }
+ return mapCliString(buf->ToString());
+}
+
+/** Maps uno types to dot net types.
+ * If uno_data is null then the type description is converted to System::Type
+ */
+inline System::String^ mapUnoString( rtl_uString const * data)
+{
+ OSL_ASSERT(data);
+ return gcnew System::String((__wchar_t*) data->buffer, 0, data->length);
+}
+
+OUString mapCliString(System::String ^ data)
+{
+
+ if (data != nullptr)
+ {
+ static_assert(sizeof(wchar_t) == sizeof(sal_Unicode), "char mismatch");
+ pin_ptr<wchar_t const> pdata= PtrToStringChars(data);
+ return OUString(
+ reinterpret_cast<sal_Unicode const *>(pdata),
+ const_cast<System::String^>(data)->Length);
+ }
+ else
+ {
+ return OUString();
+ }
+}
+
+// ToDo convert cli types to expected types, e.g a long to a short where the uno type
+// is a sal_Int16. This could be necessary if a scripting language (typeless) is used
+// @param assign the uno_data has to be destructed (in/out args)
+void Bridge::map_to_uno(void * uno_data, System::Object^ cli_data,
+ typelib_TypeDescriptionReference * type,
+ bool assign) const
+{
+ try{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ break;
+ case typelib_TypeClass_CHAR:
+ {
+ System::Char aChar= *safe_cast<System::Char^>(cli_data);
+ *(sal_Unicode*) uno_data= aChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ System::Boolean aBool= *safe_cast<System::Boolean^>(cli_data);
+ *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ System::Byte aByte= *safe_cast<System::Byte^>(cli_data);
+ *(sal_Int8*) uno_data= aByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ System::Int16 aShort= *safe_cast<System::Int16^>(cli_data);
+ *(sal_Int16*) uno_data= aShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ System::UInt16 aUShort= *safe_cast<System::UInt16^>(cli_data);
+ *(sal_uInt16*) uno_data= aUShort;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ System::Int32 aLong= *safe_cast<System::Int32^>(cli_data);
+ *(sal_Int32*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ System::UInt32 aULong= *safe_cast<System::UInt32^>(cli_data);
+ *(sal_uInt32*) uno_data= aULong;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ System::Int64 aHyper= *safe_cast<System::Int64^>(cli_data);
+ *(sal_Int64*) uno_data= aHyper;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ System::UInt64 aLong= *safe_cast<System::UInt64^>(cli_data);
+ *(sal_uInt64*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ System::Single aFloat= *safe_cast<System::Single^>(cli_data);
+ *(float*) uno_data= aFloat;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ System::Double aDouble= *safe_cast<System::Double^>(cli_data);
+ *(double*) uno_data= aDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ if (assign && *(rtl_uString**) uno_data)
+ rtl_uString_release(*(rtl_uString**) uno_data);
+
+ *(rtl_uString **)uno_data = 0;
+ if (cli_data == nullptr)
+ {
+ rtl_uString_new((rtl_uString**) uno_data);
+ }
+ else
+ {
+ System::String ^s= safe_cast<System::String^>(cli_data);
+ pin_ptr<const wchar_t> pdata= PtrToStringChars(s);
+ rtl_uString_newFromStr_WithLength(
+ reinterpret_cast<rtl_uString **>(uno_data),
+ reinterpret_cast<sal_Unicode const *>(pdata), s->Length);
+ }
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ typelib_TypeDescriptionReference* td= mapCliType(safe_cast<System::Type^>(
+ cli_data));
+ if (assign)
+ {
+ typelib_typedescriptionreference_release(
+ *(typelib_TypeDescriptionReference **)uno_data );
+ }
+ *(typelib_TypeDescriptionReference **)uno_data = td;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any * pAny = (uno_Any *)uno_data;
+ if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any
+ {
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+ uno_any_construct( pAny, 0, 0, 0 );
+ break;
+ }
+ uno::Any aAny= *safe_cast<uno::Any^>(cli_data);
+ css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
+
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+
+ try
+ {
+ switch (value_td.getTypeClass())
+ {
+ case css::uno::TypeClass_VOID:
+ pAny->pData = &pAny->pReserved;
+ break;
+ case css::uno::TypeClass_CHAR:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Unicode*) &pAny->pReserved = *safe_cast<System::Char^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_BOOLEAN:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Bool *) &pAny->pReserved = *safe_cast<System::Boolean^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_BYTE:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int8*) &pAny->pReserved = *safe_cast<System::Byte^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int16*) &pAny->pReserved = *safe_cast<System::Int16^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_UNSIGNED_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt16*) &pAny->pReserved = *safe_cast<System::UInt16^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int32*) &pAny->pReserved = *safe_cast<System::Int32^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_UNSIGNED_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt32*) &pAny->pReserved = *safe_cast<System::UInt32^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_HYPER:
+ if (sizeof (sal_Int64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int64*) &pAny->pReserved = *safe_cast<System::Int64^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
+ *(sal_Int64 *) mem.get()= *safe_cast<System::Int64^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_UNSIGNED_HYPER:
+ if (sizeof (sal_uInt64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt64*) &pAny->pReserved = *safe_cast<System::UInt64^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
+ *(sal_uInt64 *) mem.get()= *safe_cast<System::UInt64^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_FLOAT:
+ if (sizeof (float) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(float*) &pAny->pReserved = *safe_cast<System::Single^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
+ *(float*) mem.get() = *safe_cast<System::Single^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_DOUBLE:
+ if (sizeof (double) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(double*) &pAny->pReserved= *safe_cast<System::Double^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
+ *(double*) mem.get()= *safe_cast<System::Double^>(aAny.Value);
+ pAny->pData= mem.release();
+ }
+ break;
+ case css::uno::TypeClass_STRING: // anies often contain strings; copy string directly
+ {
+ pAny->pData= &pAny->pReserved;
+ OUString _s = mapCliString(static_cast<System::String^>(aAny.Value));
+ pAny->pReserved= _s.pData;
+ rtl_uString_acquire(_s.pData);
+ break;
+ }
+ case css::uno::TypeClass_TYPE:
+ case css::uno::TypeClass_ENUM: //ToDo copy enum direct
+ case css::uno::TypeClass_SEQUENCE:
+ case css::uno::TypeClass_INTERFACE:
+ pAny->pData = &pAny->pReserved;
+ pAny->pReserved = 0;
+ map_to_uno(
+ &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ break;
+ case css::uno::TypeClass_STRUCT:
+ case css::uno::TypeClass_EXCEPTION:
+ {
+ css::uno::Type anyType(value_td);
+ typelib_TypeDescription* td= NULL;
+ anyType.getDescription(&td);
+ std::unique_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
+ typelib_typedescription_release(td);
+ map_to_uno(
+ mem.get(), aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ pAny->pData = mem.release();
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + value_td.getTypeName() + "] unsupported value type of any!");
+ }
+ }
+ }
+ catch(System::InvalidCastException^ )
+ {
+// ToDo check this
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ OUString str = "[map_to_uno():Any" + value_td.getTypeName() + "]The Any type " + value_td.getTypeName() + " does not correspond to its value type: ";
+ if(aAny.Value != nullptr)
+ {
+ css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
+ str += td.getTypeName();
+ }
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw BridgeRuntimeError(str);
+ }
+ catch (BridgeRuntimeError& )
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+ catch (...)
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+
+ pAny->pType = value_td.getTypeLibType();
+ typelib_typedescriptionreference_acquire(pAny->pType);
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ // InvalidCastException is caught at the end of this method
+ System::Int32 aEnum= System::Convert::ToInt32((cli_data));
+ *(sal_Int32*) uno_data = aEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ css::uno::TypeDescription td(type);
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription*) td.get();
+
+ typelib_StructTypeDescription * struct_td = NULL;
+ if (type->eTypeClass == typelib_TypeClass_STRUCT)
+ struct_td = (typelib_StructTypeDescription*) td.get();
+
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+ sal_Int32 nMembers = comp_td->nMembers;
+ boolean bException= false;
+ System::Type^ cliType = nullptr;
+ if (cli_data)
+ cliType = cli_data->GetType();
+
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ map_to_uno(
+ uno_data, cli_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
+ assign);
+ }
+ sal_Int32 nPos = 0;
+ try
+ {
+ OUString usUnoException("com.sun.star.uno.Exception");
+ for (; nPos < nMembers; ++nPos)
+ {
+ typelib_TypeDescriptionReference * member_type= comp_td->ppTypeRefs[nPos];
+ System::Object^ val= nullptr;
+ if (cli_data != nullptr)
+ {
+ sr::FieldInfo^ aField= cliType->GetField(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ // special case for Exception.Message property
+ // The com.sun.star.uno.Exception.Message field is mapped to the
+ // System.Exception property. Type.GetField("Message") returns null
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {// get Exception.Message property
+ OUString usMessageMember("Message");
+ if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
+ {
+ sr::PropertyInfo^ pi= cliType->GetProperty(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ val= pi->GetValue(cli_data, nullptr);
+ }
+ else
+ {
+ throw BridgeRuntimeError("[map_to_uno(): Member: " + OUString::unacquired(&comp_td->ppMemberNames[nPos]));
+ }
+ }
+ else
+ {
+ val= aField->GetValue(cli_data);
+ }
+ }
+ void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
+ //When using polymorphic structs then the parameterized members can be null.
+ //Then we set a default value.
+ bool bDefault = (struct_td != NULL
+ && struct_td->pParameterizedTypes != NULL
+ && struct_td->pParameterizedTypes[nPos] == sal_True
+ && val == nullptr)
+ || cli_data == nullptr;
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ if (bDefault)
+ *(sal_Unicode*) p = 0;
+ else
+ *(sal_Unicode*) p = *safe_cast<System::Char^>(val);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ if (bDefault)
+ *(sal_Bool*) p = sal_False;
+ else
+ *(sal_Bool*) p = *safe_cast<System::Boolean^>(val);
+ break;
+ case typelib_TypeClass_BYTE:
+ if (bDefault)
+ *(sal_Int8*) p = 0;
+ else
+ *(sal_Int8*) p = *safe_cast<System::Byte^>(val);
+ break;
+ case typelib_TypeClass_SHORT:
+ if (bDefault)
+ *(sal_Int16*) p = 0;
+ else
+ *(sal_Int16*) p = *safe_cast<System::Int16^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ if (bDefault)
+ *(sal_uInt16*) p = 0;
+ else
+ *(sal_uInt16*) p = *safe_cast<System::UInt16^>(val);
+ break;
+ case typelib_TypeClass_LONG:
+ if (bDefault)
+ *(sal_Int32*) p = 0;
+ else
+ *(sal_Int32*) p = *safe_cast<System::Int32^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ if (bDefault)
+ *(sal_uInt32*) p = 0;
+ else
+ *(sal_uInt32*) p = *safe_cast<System::UInt32^>(val);
+ break;
+ case typelib_TypeClass_HYPER:
+ if (bDefault)
+ *(sal_Int64*) p = 0;
+ else
+ *(sal_Int64*) p = *safe_cast<System::Int64^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (bDefault)
+ *(sal_uInt64*) p = 0;
+ else
+ *(sal_uInt64*) p= *safe_cast<System::UInt64^>(val);
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (bDefault)
+ *(float*) p = 0.;
+ else
+ *(float*) p = *safe_cast<System::Single^>(val);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (bDefault)
+ *(double*) p = 0.;
+ else
+ *(double*) p = *safe_cast<System::Double^>(val);
+ break;
+ default:
+ { // ToDo enum, should be converted here
+ map_to_uno(p, val, member_type, assign);
+ break;
+ }
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ bException= true;
+ OUString str = "[map_to_uno():";
+ if (cliType)
+ {
+ str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]) + " ";
+ }
+ str += e.m_message;
+ throw BridgeRuntimeError(str);
+ }
+ catch (System::InvalidCastException^ )
+ {
+ bException= true;
+ OUString str = "[map_to_uno():";
+ if (cliType)
+ {
+ str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]);
+ }
+ str += "] Value has not the required type.";
+ throw BridgeRuntimeError(str);
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ bException= true;
+ throw;
+ }
+ __finally
+ {
+ if (bException && !assign) // if assign then caller cleans up
+ {
+ // cleanup the members which we have converted so far
+ for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
+ {
+ uno_type_destructData(
+ uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
+ }
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ uno_destructData(
+ uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
+ }
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ std::unique_ptr< rtl_mem > seq;
+
+ System::Array^ ar = nullptr;
+ if (cli_data != nullptr)
+ {
+ ar = safe_cast<System::Array^>(cli_data);
+ sal_Int32 nElements = ar->GetLength(0);
+
+ try
+ {
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ seq = seq_allocate(nElements, sizeof (sal_Unicode));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ seq = seq_allocate(nElements, sizeof (sal_Bool));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_BYTE:
+ seq = seq_allocate( nElements, sizeof (sal_Int8) );
+ sri::Marshal::Copy(safe_cast<cli::array<System::Byte>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_SHORT:
+ seq = seq_allocate(nElements, sizeof (sal_Int16));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int16>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ seq = seq_allocate( nElements, sizeof (sal_uInt16) );
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int16>^>(
+ safe_cast<cli::array<System::UInt16>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_LONG:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int32>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ seq = seq_allocate( nElements, sizeof (sal_uInt32) );
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int32>^>(
+ safe_cast<cli::array<System::UInt32>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_Int64));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int64>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_uInt64));
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int64>^>(
+ safe_cast<cli::array<System::UInt64>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_FLOAT:
+ seq = seq_allocate(nElements, sizeof (float));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Single>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ seq = seq_allocate(nElements, sizeof (double));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Double>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ seq = seq_allocate(nElements, sizeof (rtl_uString*));
+ cli::array<System::String^>^ arStr= safe_cast<cli::array<System::String^>^>(cli_data);
+ for (int i= 0; i < nElements; i++)
+ {
+ pin_ptr<const wchar_t> pdata= PtrToStringChars(arStr[i]);
+ rtl_uString** pStr= & ((rtl_uString**) &
+ ((uno_Sequence*) seq.get())->elements)[i];
+ *pStr= NULL;
+ rtl_uString_newFromStr_WithLength(
+ pStr,
+ reinterpret_cast<sal_Unicode const *>(pdata),
+ arStr[i]->Length);
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ for (int i= 0; i < nElements; i++)
+ {
+ ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
+ System::Convert::ToInt32(ar->GetValue(i));
+ }
+ break;
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ seq = seq_allocate( nElements, element_td.get()->nSize );
+
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
+ {
+ try
+ {
+ void * p= ((uno_Sequence *) seq.get())->elements +
+ (nPos * element_td.get()->nSize);
+ System::Object^ elemData= safe_cast<System::Array^>(cli_data)->GetValue(System::Int32(nPos));
+ map_to_uno(
+ p, elemData, element_td.get()->pWeakRef,
+ false /* no assign */);
+ }
+ catch (...)
+ {
+ // cleanup
+ for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
+ {
+ void * p =
+ ((uno_Sequence *)seq.get())->elements +
+ (nCleanPos * element_td.get()->nSize);
+ uno_destructData( p, element_td.get(), 0 );
+ }
+ throw;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) +
+ "] unsupported sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] conversion failed\n " + e.m_message);
+ }
+ catch (System::InvalidCastException^ )
+ {
+ // Ok, checked
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName) +
+ "] could not convert sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+ __finally
+ {
+ if (assign)
+ uno_destructData( uno_data, td.get(), 0 );
+ }
+ }
+ else
+ {
+ seq = seq_allocate(0, sizeof (sal_Int32));
+ }
+ *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ if (assign)
+ {
+ uno_Interface * p = *(uno_Interface **)uno_data;
+ if (0 != p)
+ (*p->release)( p );
+ }
+ if (nullptr == cli_data) // null-ref
+ {
+ *(uno_Interface **)uno_data = 0;
+ }
+ else
+ {
+ TypeDescr td( type );
+ uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
+ *(uno_Interface **)uno_data = pUnoI;
+ }
+ break;
+ }
+ default:
+ {
+ //ToDo check
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
+ }
+ }
+ }
+ // BridgeRuntimeError are allowed to be thrown
+ catch (System::InvalidCastException^ )
+ {
+ //ToDo check
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] could not convert type!");
+ }
+ catch (System::NullReferenceException ^ e)
+ {
+ throw BridgeRuntimeError("[map_to_uno()] Illegal null reference passed!\n" + mapCliString(e->StackTrace));
+ }
+ catch (BridgeRuntimeError& )
+ {
+ throw;
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+}
+
+/**
+ @param info
+ The expected target type. Currently info is provided when this method is called
+ to convert the in/out and out parameters of a call from cli to uno. Then info
+ is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
+ @param bDontCreateObj
+ false - a new object is created which holds the mapped uno value and is assigned to
+ cli_data.
+ true - cli_data already contains the newly constructed object. This is the case if
+ a struct is converted then on the first call to map_to_cli the new object is created.
+ If the struct inherits another struct then this function is called recursively while the
+ newly created object is passed in cli_data.
+ */
+void Bridge::map_to_cli(
+ System::Object^ *cli_data, void const * uno_data,
+ typelib_TypeDescriptionReference * type, System::Type^ info,
+ bool bDontCreateObj) const
+{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *cli_data= *(__wchar_t const*)uno_data;
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ *cli_data = (*(bool const*)uno_data) == sal_True;
+ break;
+ case typelib_TypeClass_BYTE:
+ *cli_data = *(unsigned char const*) uno_data;
+ break;
+ case typelib_TypeClass_SHORT:
+ *cli_data= *(short const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *cli_data= *(unsigned short const*) uno_data;
+ break;
+ case typelib_TypeClass_LONG:
+ *cli_data= *(int const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *cli_data= *(unsigned int const*) uno_data;
+ break;
+ case typelib_TypeClass_HYPER:
+ *cli_data= *(__int64 const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *cli_data= *(unsigned __int64 const*) uno_data;
+ break;
+ case typelib_TypeClass_FLOAT:
+ *cli_data= *(float const*) uno_data;
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *cli_data= *(double const*) uno_data;
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ rtl_uString const* sVal= NULL;
+ sVal= *(rtl_uString* const*) uno_data;
+ *cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length);
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any const * pAny = (uno_Any const *)uno_data;
+ if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
+ {
+ System::Object^ objCli= nullptr;
+ map_to_cli(
+ &objCli, pAny->pData, pAny->pType, nullptr,
+ false);
+
+ uno::Any anyVal(mapUnoType(pAny->pType), objCli);
+ *cli_data= anyVal;
+ }
+ else
+ { // void any
+ *cli_data= uno::Any::VOID;
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ if (info != nullptr)
+ {
+ OSL_ASSERT(info->IsByRef);
+ info= info->GetElementType();
+ *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
+ }
+ else
+ *cli_data= System::Enum::ToObject(
+ mapUnoType(type), *(System::Int32*) uno_data);
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr td( type );
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription *) td.get();
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+
+ //create the type
+ System::Type^ cliType= loadCliType(td.get()->pTypeName);
+ //detect if we recursively convert inherited structures
+ //If this point is reached because of a recursive call during covering a
+ //struct then we must not create a new object rather we use the one in
+ // cli_data argument.
+ System::Object^ cliObj;
+ if (bDontCreateObj)
+ cliObj = *cli_data; // recursive call
+ else
+ {
+ //Special handling for Exception conversion. We must call constructor System::Exception
+ //to pass the message string
+ if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType))
+ {
+ //We need to get the Message field. Therefore we must obtain the offset from
+ //the typedescription. The base interface of all exceptions is
+ //com::sun::star::uno::Exception which contains the message
+ typelib_CompoundTypeDescription* pCTD = comp_td;
+ while (pCTD->pBaseTypeDescription)
+ pCTD = pCTD->pBaseTypeDescription;
+ int nPos = -1;
+
+ OUString usMessageMember("Message");
+ for (int i = 0; i < pCTD->nMembers; i ++)
+ {
+ if (usMessageMember.equals(pCTD->ppMemberNames[i]))
+ {
+ nPos = i;
+ break;
+ }
+ }
+ OSL_ASSERT (nPos != -1);
+ int offset = pCTD->pMemberOffsets[nPos];
+ //With the offset within the exception we can get the message string
+ System::String^ sMessage = mapUnoString(*(rtl_uString**)
+ ((char*) uno_data + offset));
+ //We need to find a constructor for the exception that takes the message string
+ //We assume that the first argument is the message string
+ cli::array<sr::ConstructorInfo^>^ arCtorInfo = cliType->GetConstructors();
+ sr::ConstructorInfo^ ctorInfo = nullptr;
+ int numCtors = arCtorInfo->Length;
+ //Constructor must at least have 2 params for the base
+ //unoidl.com.sun.star.uno.Exception (String, Object);
+ cli::array<sr::ParameterInfo^>^ arParamInfo;
+ for (int i = 0; i < numCtors; i++)
+ {
+ arParamInfo = arCtorInfo[i]->GetParameters();
+ if (arParamInfo->Length < 2)
+ continue;
+ ctorInfo = arCtorInfo[i];
+ break;
+ }
+ OSL_ASSERT(arParamInfo[0]->ParameterType->Equals(System::String::typeid)
+ && arParamInfo[1]->ParameterType->Equals(System::Object::typeid)
+ && arParamInfo[0]->Position == 0
+ && arParamInfo[1]->Position == 1);
+ //Prepare parameters for constructor
+ int numArgs = arParamInfo->Length;
+ cli::array<System::Object^>^ args = gcnew cli::array<System::Object^>(numArgs);
+ //only initialize the first argument with the message
+ args[0] = sMessage;
+ cliObj = ctorInfo->Invoke(args);
+ }
+ else
+ cliObj = System::Activator::CreateInstance(cliType);
+ }
+ sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
+
+ if (comp_td->pBaseTypeDescription)
+ {
+ //convert inherited struct
+ //cliObj is passed inout (args in_param, out_param are true), hence the passed
+ // cliObj is used by the callee instead of a newly created struct
+ map_to_cli(
+ &cliObj, uno_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, nullptr,
+ true);
+ }
+ OUString usUnoException("com.sun.star.uno.Exception");
+ for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
+ {
+ typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
+ System::String^ sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
+ sr::FieldInfo^ aField= cliType->GetField(sMemberName);
+ // special case for Exception.Message. The field has already been
+ // set while constructing cli object
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {
+ continue;
+ }
+ void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ aField->SetValue(cliObj, *(System::Char*) p);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ aField->SetValue(cliObj, *(System::Boolean*) p);
+ break;
+ case typelib_TypeClass_BYTE:
+ aField->SetValue(cliObj, *(System::Byte*) p);
+ break;
+ case typelib_TypeClass_SHORT:
+ aField->SetValue(cliObj, *(System::Int16*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ aField->SetValue(cliObj, *(System::UInt16*) p);
+ break;
+ case typelib_TypeClass_LONG:
+ aField->SetValue(cliObj, *(System::Int32*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ aField->SetValue(cliObj, *(System::UInt32*) p);
+ break;
+ case typelib_TypeClass_HYPER:
+ aField->SetValue(cliObj, *(System::Int64*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ aField->SetValue(cliObj, *(System::UInt64*) p);
+ break;
+ case typelib_TypeClass_FLOAT:
+ aField->SetValue(cliObj, *(System::Single*) p);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ aField->SetValue(cliObj, *(System::Double*) p);
+ break;
+ default:
+ {
+ System::Object^ cli_val;
+ map_to_cli(
+ &cli_val, p, member_type, nullptr,
+ false);
+ aField->SetValue(cliObj, cli_val);
+ break;
+ }
+ }
+ }
+ *cli_data= cliObj;
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ sal_Int32 nElements;
+ uno_Sequence const * seq = 0;
+ seq = *(uno_Sequence * const *)uno_data;
+ nElements = seq->nElements;
+
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ {
+ cli::array<System::Char>^ arChar= gcnew cli::array<System::Char>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arChar, 0, nElements);
+ *cli_data= arChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ cli::array<System::Byte>^ arBool= gcnew cli::array<System::Byte>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arBool, 0, nElements);
+ *cli_data= dynamic_cast<cli::array<System::Boolean>^>(arBool);
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ cli::array<System::Byte>^ arByte= gcnew cli::array<System::Byte>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arByte, 0, nElements);
+ *cli_data= arByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ cli::array<System::Int16>^ arShort= gcnew cli::array<System::Int16>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arShort, 0, nElements);
+ *cli_data= arShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ cli::array<System::UInt16>^ arUInt16= gcnew cli::array<System::UInt16>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int16>^>(arUInt16),
+ 0, nElements);
+ *cli_data= arUInt16;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ cli::array<System::Int32>^ arInt32= gcnew cli::array<System::Int32>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt32, 0, nElements);
+ *cli_data= arInt32;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ cli::array<System::UInt32>^ arUInt32= gcnew cli::array<System::UInt32>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int32>^>(arUInt32),
+ 0, nElements);
+ *cli_data= arUInt32;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ cli::array<System::Int64>^ arInt64= gcnew cli::array<System::Int64>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt64, 0, nElements);
+ *cli_data= arInt64;
+ break;
+ }
+ //FIXME: Marshal::Copy of UInt64?
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ cli::array<System::IntPtr>^ arUInt64= gcnew cli::array<System::IntPtr>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arUInt64, 0, nElements);
+ *cli_data= dynamic_cast<cli::array<System::UInt64>^>(arUInt64);
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ cli::array<System::Single>^ arSingle= gcnew cli::array<System::Single>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arSingle, 0, nElements);
+ *cli_data= arSingle;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ cli::array<System::Double>^ arDouble= gcnew cli::array<System::Double>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arDouble, 0, nElements);
+ *cli_data= arDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ cli::array<System::String^>^ arString= gcnew cli::array<System::String^>(nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
+ arString[i]= gcnew System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
+ }
+ *cli_data= arString;
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ cli::array<System::Type^>^ arType= gcnew cli::array<System::Type^>(nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ arType[i]=
+ mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
+ }
+ *cli_data= arType;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ cli::array<uno::Any>^ arCli= gcnew cli::array<uno::Any>(nElements);
+ uno_Any const * p = (uno_Any const *)seq->elements;
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ cli_obj = nullptr;
+ map_to_cli(
+ &cli_obj, &p[ nPos ], element_type, nullptr, false);
+ arCli[nPos]= *safe_cast<uno::Any^>(cli_obj);
+ }
+ *cli_data= arCli;
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ //get the Enum type
+ System::Type^ enumType= nullptr;
+ if (info != nullptr)
+ {
+ //info is EnumType[]&, remove &
+ OSL_ASSERT(info->IsByRef);
+ enumType = info->GetElementType();
+ //enumType is EnumType[], remove []
+ enumType = enumType->GetElementType();
+ }
+ else
+ enumType= mapUnoType(element_type);
+
+ System::Array^ arEnum = System::Array::CreateInstance(
+ enumType, nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ arEnum->SetValue(System::Enum::ToObject(enumType,
+ System::Int32(((sal_Int32*) seq->elements)[i])), i);
+ }
+ *cli_data = arEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr element_td( element_type );
+ System::Array^ ar= System::Array::CreateInstance(
+ mapUnoType(element_type),nElements);
+ if (0 < nElements)
+ {
+ // ToDo check this
+ char * p = (char *) &seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, nullptr, false);
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+// ToDo, verify
+ case typelib_TypeClass_SEQUENCE:
+ {
+ System::Array ^ar= System::Array::CreateInstance(
+ mapUnoType(element_type), nElements);
+ if (0 < nElements)
+ {
+ TypeDescr element_td( element_type );
+ uno_Sequence ** elements = (uno_Sequence**) seq->elements;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, &elements[nPos], element_type, nullptr, false);
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ System::Type ^ ifaceType= mapUnoType(element_type);
+ System::Array^ ar= System::Array::CreateInstance(ifaceType, nElements);
+
+ char * p = (char *)seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, nullptr, false);
+
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ *cli_data= ar;
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) +
+ "] unsupported element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
+ if (0 != pUnoI)
+ {
+ TypeDescr td( type );
+ *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
+ typelib_InterfaceTypeDescription*>(td.get())) ;
+ }
+ else
+ *cli_data= nullptr;
+ break;
+ }
+ default:
+ {
+ //ToDo check this exception. The String is probably crippled
+ throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
+ }
+ } //switch
+} // method
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_environment.cxx b/cli_ure/source/uno_bridge/cli_environment.cxx
new file mode 100644
index 000000000..3c054b5be
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_environment.cxx
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Cli_environment.h"
+
+#using <cli_ure.dll>
+#using <system.dll>
+#include "osl/diagnose.h"
+#include "cli_proxy.h"
+
+using namespace System::Runtime::Remoting;
+using namespace System::Runtime::Remoting::Proxies;
+using namespace System::Collections;
+using namespace System::Text;
+using namespace System::Diagnostics;
+using namespace System::Threading;
+
+namespace cli_uno
+{
+
+inline System::String^ Cli_environment::createKey(System::String^ oid, System::Type^ t)
+{
+ return System::String::Concat(oid, t->FullName);
+}
+
+
+inline Cli_environment::Cli_environment()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ _numRegisteredObjects = 0;
+#endif
+}
+
+Cli_environment::~Cli_environment() ///< IDisposable Cli_environment::Dispose()
+{
+ this->!Cli_environment(); // call finalizer
+}
+
+Cli_environment::!Cli_environment() ///< Cli_environment::Finalize()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ OSL_ENSURE(_numRegisteredObjects == 0,
+ "cli uno bridge: CLI environment contains unrevoked objects");
+#endif
+}
+
+System::Object^ Cli_environment::registerInterface(
+ System::Object^ obj, System::String^ oid)
+{
+#if OSL_DEBUG_LEVEL >= 1
+ //obj must be a transparent proxy
+ OSL_ASSERT(RemotingServices::IsTransparentProxy(obj));
+ _numRegisteredObjects ++;
+#endif
+ OSL_ASSERT( ! m_objects->ContainsKey(oid));
+ m_objects->Add(oid, gcnew WeakReference(obj));
+ return obj;
+}
+System::Object^ Cli_environment::registerInterface (
+ System::Object^ obj, System::String^ oid, System::Type^ type)
+{
+#if OSL_DEBUG_LEVEL >= 1
+ //obj must be a real cli object
+ OSL_ASSERT( ! RemotingServices::IsTransparentProxy(obj));
+ _numRegisteredObjects ++;
+#endif
+ System::String^ key = createKey(oid, type);
+ //see synchronization in map_uno2cli in cli_data.cxx
+ OSL_ASSERT( ! m_objects->ContainsKey(key));
+ m_objects->Add(key, gcnew WeakReference(obj));
+ return obj;
+}
+
+void Cli_environment::revokeInterface(System::String^ oid, System::Type^ type)
+{
+ System::String^ key = type != nullptr ? createKey(oid, type) : oid;
+#if OSL_DEBUG_LEVEL >= 1
+ _numRegisteredObjects --;
+#endif
+#if OSL_DEBUG_LEVEL >= 2
+ int i = 1;
+ if (m_objects->ContainsKey(key) == false)
+ {
+ Trace::WriteLine("cli uno bridge: try to revoke unregistered interface");
+ Trace::WriteLine(oid);
+ i = 0;
+ }
+ Trace::WriteLine(System::String::Format(
+ gcnew System::String("cli uno bridge: {0} remaining registered interfaces"),
+ m_objects->Count - 1));
+#endif
+ m_objects->Remove(key);
+}
+
+inline void Cli_environment::revokeInterface(System::String^ oid)
+{
+ return revokeInterface(oid, nullptr);
+}
+
+System::Object^ Cli_environment::getRegisteredInterface(System::String^ oid,
+ System::Type^ type)
+{
+ //try if it is a UNO interface
+ System::Object^ ret = m_objects[oid];
+ if (! ret)
+ {
+ //try if it is a proxy for a cli object
+ oid = createKey(oid, type);
+ ret = m_objects[ oid ];
+ }
+ if (ret != nullptr)
+ {
+ System::WeakReference^ weakIface =
+ static_cast< System::WeakReference ^ >( ret );
+ ret = weakIface->Target;
+ }
+ if (ret == nullptr)
+ m_objects->Remove( oid );
+ return ret;
+}
+
+System::String^ Cli_environment::getObjectIdentifier(System::Object^ obj)
+{
+ System::String^ oId= nullptr;
+ RealProxy^ aProxy= RemotingServices::GetRealProxy(obj);
+ if (aProxy)
+ {
+ UnoInterfaceProxy^ proxyImpl= dynamic_cast<UnoInterfaceProxy^>(aProxy);
+ if (proxyImpl)
+ oId= proxyImpl->getOid();
+ }
+
+ if (oId == nullptr)
+ {
+ StringBuilder ^ buf= gcnew StringBuilder(256);
+ bool bFirst = new bool(false);
+ System::Threading::Monitor::Enter(Cli_environment::typeid);
+ try {
+ buf->Append(m_IDGen->GetId(obj, bFirst));
+ } finally
+ {
+ System::Threading::Monitor::Exit(Cli_environment::typeid);
+ }
+
+ buf->Append(sOidPart);
+ oId= buf->ToString();
+ }
+ return oId;
+}
+} //namespace cli_uno
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_environment.h b/cli_ure/source/uno_bridge/cli_environment.h
new file mode 100644
index 000000000..3828d971c
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_environment.h
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_ENVIRONMENT_H
+#define INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_ENVIRONMENT_H
+
+#include "cli_base.h"
+
+using namespace System;
+using namespace System::Collections;
+using namespace System::Runtime::Serialization;
+
+namespace cli_uno
+{
+public
+ref class Cli_environment
+{
+ static System::String ^ sOidPart;
+ static Hashtable ^ m_objects;
+ static System::Runtime::Serialization::ObjectIDGenerator ^ m_IDGen;
+ inline static System::String ^ createKey(System::String ^ oid, System::Type ^ t);
+
+#if OSL_DEBUG_LEVEL >= 1
+ int _numRegisteredObjects;
+#endif
+
+ static Cli_environment()
+ {
+ m_objects = Hashtable::Synchronized(gcnew Hashtable());
+ m_IDGen = gcnew System::Runtime::Serialization::ObjectIDGenerator();
+ System::Text::StringBuilder ^ buffer = gcnew System::Text::StringBuilder(256);
+ Guid gd = Guid::NewGuid();
+ buffer->Append(";cli[0];");
+ buffer->Append(gd.ToString());
+ sOidPart = buffer->ToString();
+ }
+
+public:
+ inline Cli_environment();
+
+ ~Cli_environment();
+ !Cli_environment();
+
+ /**
+ Registers a UNO object as being mapped by this bridge. The resulting
+ cli object is represents all interfaces of the UNO object. Therefore the
+ object can be registered only with its OID; a type is not necessary.
+ */
+ Object ^ registerInterface(Object ^ obj, System::String ^ oid);
+ /**
+ Registers a CLI object as being mapped by this bridge. The resulting
+ object represents exactly one UNO interface.
+ */
+ Object ^ registerInterface(Object ^ obj, System::String ^ oid, System::Type ^ type);
+
+ /**
+ By revoking an interface it is declared that the respective interface has
+ not been mapped. The proxy implementations call revoke interface in their
+ destructors.
+ */
+ inline void revokeInterface(System::String ^ oid);
+
+ void revokeInterface(System::String ^ oid, System::Type ^ type);
+ /**
+ * Retrieves an interface identified by its object id and type from this
+ * environment.
+ *
+ * @param oid object id of interface to be retrieved
+ * @param type the type description of the interface to be retrieved
+ * @see com.sun.star.uno.IEnvironment#getRegisteredInterface
+ */
+ Object ^ getRegisteredInterface(System::String ^ oid, System::Type ^ type);
+
+ /**
+ * Generates a worldwide unique object identifier (oid) for the given object. It is
+ * guaranteed, that subsequent calls to the method with the same object
+ * will give the same id.
+ * <p>
+ * @return the generated oid.
+ * @param object the object for which an Oid should be generated.
+ */
+ static System::String ^ getObjectIdentifier(Object ^ obj);
+};
+
+} //namespace cli_uno
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_proxy.cxx b/cli_ure/source/uno_bridge/cli_proxy.cxx
new file mode 100644
index 000000000..22c478177
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_proxy.cxx
@@ -0,0 +1,1105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "typelib/typedescription.h"
+#include "rtl/ustrbuf.hxx"
+#include <sal/log.hxx>
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "cli_proxy.h"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+#using <cli_ure.dll>
+#using <cli_uretypes.dll>
+
+namespace sr = System::Reflection;
+namespace st = System::Text;
+namespace sc = System::Collections;
+namespace srrm = System::Runtime::Remoting::Messaging;
+namespace srr = System::Runtime::Remoting;
+namespace srrp = System::Runtime::Remoting::Proxies;
+namespace sd = System::Diagnostics;
+namespace ucss = unoidl::com::sun::star;
+
+using namespace cli_uno;
+
+extern "C"
+{
+
+void SAL_CALL cli_proxy_free( uno_ExtEnvironment * env, void * proxy )
+ SAL_THROW_EXTERN_C();
+
+void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
+ SAL_THROW_EXTERN_C();
+
+void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
+ SAL_THROW_EXTERN_C();
+
+void SAL_CALL cli_proxy_dispatch(
+ uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
+ void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
+ SAL_THROW_EXTERN_C();
+
+
+}
+
+namespace cli_uno
+{
+
+UnoInterfaceInfo::UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
+ typelib_InterfaceTypeDescription* td):
+
+ m_unoI(unoI),
+ m_typeDesc(td),
+ m_bridge(bridge)
+{
+ m_bridge->acquire();
+ m_type = mapUnoType(reinterpret_cast<typelib_TypeDescription*>(td));
+ m_unoI->acquire(m_unoI);
+ typelib_typedescription_acquire(&m_typeDesc->aBase);
+ if ( ! m_typeDesc->aBase.bComplete)
+ {
+ typelib_TypeDescription* _pt = &m_typeDesc->aBase;
+ sal_Bool bComplete = ::typelib_typedescription_complete( & _pt);
+ if( ! bComplete)
+ {
+ throw BridgeRuntimeError("cannot make type complete: " + OUString::unacquired(& m_typeDesc->aBase.pTypeName));
+ }
+ }
+}
+
+UnoInterfaceInfo::~UnoInterfaceInfo() ///< IDisposable UnoInterfaceInfo::Dispose()
+{
+ this->!UnoInterfaceInfo(); // call finalizer
+}
+
+UnoInterfaceInfo::!UnoInterfaceInfo() ///< UnoInterfaceInfo::Finalize()
+{
+ //accessing unmanaged objects is ok.
+ m_bridge->m_uno_env->revokeInterface(
+ m_bridge->m_uno_env, m_unoI );
+ m_bridge->release();
+
+ m_unoI->release(m_unoI);
+ typelib_typedescription_release(
+ reinterpret_cast<typelib_TypeDescription*>(m_typeDesc));
+}
+
+UnoInterfaceProxy::UnoInterfaceProxy(
+ Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTD,
+ const OUString& oid )
+ :RealProxy(MarshalByRefObject::typeid),
+ m_bridge(bridge),
+ m_oid(mapUnoString(oid.pData)),
+ m_sTypeName(m_system_Object_String)
+{
+ m_bridge->acquire();
+ // create the list that holds all UnoInterfaceInfos
+ m_listIfaces = gcnew ArrayList(10);
+ m_numUnoIfaces = 0;
+ m_listAdditionalProxies = gcnew ArrayList();
+ m_nlistAdditionalProxies = 0;
+ //put the information of the first UNO interface into the arraylist
+#if OSL_DEBUG_LEVEL >= 2
+ _numInterfaces = 0;
+ _sInterfaces = NULL;
+#endif
+ addUnoInterface(pUnoI, pTD);
+
+}
+
+UnoInterfaceProxy::~UnoInterfaceProxy() ///< IDisposable UnoInterfaceProxy::Dispose()
+{
+ this->!UnoInterfaceProxy(); // call finalizer
+}
+
+UnoInterfaceProxy::!UnoInterfaceProxy() ///< UnoInterfaceProxy::Finalize()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ sd::Trace::WriteLine(System::String::Format(
+ gcnew System::String("cli uno bridge: Destroying proxy "
+ "for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
+ m_oid));
+
+ sd::Trace::WriteLine( mapUnoString(_sInterfaces));
+ rtl_uString_release(_sInterfaces);
+#endif
+ //m_bridge is unmanaged, therefore we can access it in this finalizer
+ CliEnvHolder::g_cli_env->revokeInterface(m_oid);
+ m_bridge->release();
+}
+
+System::Object^ UnoInterfaceProxy::create(
+ Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTD,
+ const OUString& oid)
+{
+ UnoInterfaceProxy^ proxyHandler=
+ gcnew UnoInterfaceProxy(bridge, pUnoI, pTD, oid);
+ System::Object^ proxy= proxyHandler->GetTransparentProxy();
+ CliEnvHolder::g_cli_env->registerInterface(proxy, mapUnoString(oid.pData));
+ return proxy;
+}
+
+
+void UnoInterfaceProxy::addUnoInterface(uno_Interface* pUnoI,
+ typelib_InterfaceTypeDescription* pTd)
+{
+ sc::IEnumerator^ enumInfos = m_listIfaces->GetEnumerator();
+ System::Threading::Monitor::Enter(this);
+ try
+ {
+ while (enumInfos->MoveNext())
+ {
+ UnoInterfaceInfo^ info = static_cast<UnoInterfaceInfo^>(
+ enumInfos->Current);
+ if (typelib_typedescription_equals(
+ reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc),
+ reinterpret_cast<typelib_TypeDescription*>(pTd)))
+ {
+ return;
+ }
+ }
+ OUString oid(mapCliString(m_oid));
+ (*m_bridge->m_uno_env->registerInterface)(
+ m_bridge->m_uno_env, reinterpret_cast< void ** >( &pUnoI ),
+ oid.pData, pTd);
+ //This proxy does not contain the uno_Interface. Add it.
+ m_listIfaces->Add(gcnew UnoInterfaceInfo(m_bridge, pUnoI, pTd));
+ m_numUnoIfaces = m_listIfaces->Count;
+#if OSL_DEBUG_LEVEL >= 2
+ System::String^ sInterfaceName = static_cast<UnoInterfaceInfo^>(
+ m_listIfaces[m_numUnoIfaces - 1])->m_type->FullName;
+ sd::Trace::WriteLine(System::String::Format(
+ gcnew System::String("cli uno bridge: Creating proxy for uno object, "
+ "id:\n\t{0}\n\t{1}"), m_oid, sInterfaceName));
+ // add to the string that contains all interface names
+ _numInterfaces++;
+ OUString _sNewInterface = "\t" + OUString::number(_numInterfaces) + ". " + mapCliString(sInterfaceName) + "\n";
+ pin_ptr<rtl_uString *> pp_sInterfaces = &_sInterfaces;
+ rtl_uString_newConcat( pp_sInterfaces, * pp_sInterfaces,
+ _sNewInterface.pData);
+#endif
+ }
+ __finally {
+ System::Threading::Monitor::Exit(this);
+ }
+}
+
+
+// IRemotingTypeInfo
+bool UnoInterfaceProxy::CanCastTo(System::Type^ fromType,
+ System::Object^)
+{
+ if (fromType == System::Object::typeid) // trivial case
+ return true;
+
+ System::Threading::Monitor::Enter(this);
+ try
+ {
+ if (nullptr != findInfo( fromType )) // proxy supports demanded interface
+ return true;
+
+ //query a uno interface for the required type
+
+ // we use the first interface in the list (m_listIfaces) to make
+ // the queryInterface call
+ UnoInterfaceInfo^ info =
+ static_cast<UnoInterfaceInfo^>(m_listIfaces[0]);
+ css::uno::TypeDescription membertd(
+ reinterpret_cast<typelib_InterfaceTypeDescription*>(
+ info->m_typeDesc)->ppAllMembers[0]);
+ array<System::Object^>^ args = gcnew array<System::Object^>(1);
+
+ args[0] = fromType;
+ uno::Any ^ pAny;
+ System::Object^ pException = nullptr;
+
+ pAny= static_cast<uno::Any ^>(
+ m_bridge->call_uno(
+ info->m_unoI,
+ membertd.get(),
+ ((typelib_InterfaceMethodTypeDescription*)
+ membertd.get())->pReturnTypeRef,
+ 1,
+ ((typelib_InterfaceMethodTypeDescription*)
+ membertd.get())->pParams,
+ args, nullptr, &pException) );
+
+ // handle regular exception from target
+ OSL_ENSURE(
+ nullptr == pException,
+ OUStringToOString(
+ mapCliString( pException->ToString()),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ if (pAny->Type != void::typeid) // has value?
+ {
+ if (nullptr != findInfo( fromType ))
+ {
+ // proxy now supports demanded interface
+ return true;
+ }
+
+ // via aggregation: it is possible that queryInterface() returns
+ // and interface with a different oid.
+ // That way, this type is supported for the CLI
+ // interpreter (CanCastTo() returns true)
+ ::System::Object ^ obj = pAny->Value;
+ OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj ) );
+ if (srr::RemotingServices::IsTransparentProxy( obj ))
+ {
+ UnoInterfaceProxy ^ proxy =
+ static_cast< UnoInterfaceProxy ^ >(
+ srr::RemotingServices::GetRealProxy( obj ) );
+ OSL_ASSERT( nullptr != proxy->findInfo( fromType ) );
+ m_listAdditionalProxies->Add( proxy );
+ m_nlistAdditionalProxies = m_listAdditionalProxies->Count;
+ OSL_ASSERT( nullptr != findInfo( fromType ) );
+ return true;
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ (void) e; // avoid warning
+ OSL_FAIL(
+ OUStringToOString(
+ e.m_message, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ catch (System::Exception^ e)
+ {
+ System::String^ msg= gcnew System::String(
+ "An unexpected CLI exception occurred in "
+ "UnoInterfaceProxy::CanCastTo(). Original"
+ "message: \n");
+ msg= System::String::Concat(msg, e->Message);
+ OSL_FAIL(
+ OUStringToOString(
+ mapCliString(msg), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ catch (...)
+ {
+ OSL_FAIL(
+ "An unexpected native C++ exception occurred in "
+ "UnoInterfaceProxy::CanCastTo()" );
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit(this);
+ }
+ return false;
+}
+
+srrm::IMessage^ UnoInterfaceProxy::invokeObject(
+ sc::IDictionary^ props,
+ srrm::LogicalCallContext^ context,
+ srrm::IMethodCallMessage^ mcm)
+{
+ System::Object^ retMethod = nullptr;
+ System::String^ sMethod = static_cast<System::String^>
+ (props[m_methodNameString]);
+ array<System::Object^>^ args = static_cast<array<System::Object^>^>(
+ props[m_ArgsString]);
+ if (m_Equals_String->Equals(sMethod))
+ {
+ // Object.Equals
+ OSL_ASSERT(args->Length == 1);
+ srrp::RealProxy^ rProxy = srr::RemotingServices::GetRealProxy(args[0]);
+ bool bDone = false;
+ if (rProxy)
+ {
+ UnoInterfaceProxy^ unoProxy =
+ dynamic_cast<UnoInterfaceProxy^>(rProxy);
+ if (unoProxy)
+ {
+ bool b = m_oid->Equals(unoProxy->getOid());
+ retMethod = b;
+ bDone = true;
+ }
+ }
+ if (bDone == false)
+ {
+ //no proxy or not our proxy, therefore Equals must be false
+ retMethod = false;
+ }
+ }
+ else if (m_GetHashCode_String->Equals(sMethod))
+ {
+ // Object.GetHashCode
+ int nHash = m_oid->GetHashCode();
+ retMethod = nHash;
+ }
+ else if (m_GetType_String->Equals(sMethod))
+ {
+ // Object.GetType
+ retMethod = System::Object::typeid;
+ }
+ else if (m_ToString_String->Equals(sMethod))
+ {
+ // Object.ToString
+ st::StringBuilder^ sb = gcnew st::StringBuilder(256);
+// sb->AppendFormat("Uno object proxy. Implemented interface: {0}"
+// ". OID: {1}", m_type->ToString(), m_oid);
+ sb->AppendFormat("Uno object proxy. OID: {0}", m_oid);
+ retMethod = sb->ToString();
+ }
+ else
+ {
+ //Either Object has new functions or a protected method was called
+ //which should not be possible
+ OSL_ASSERT(0);
+ }
+ srrm::IMessage^ retVal= gcnew srrm::ReturnMessage(
+ retMethod, gcnew array<System::Object^>(0), 0, context, mcm);
+ return retVal;
+}
+
+UnoInterfaceInfo ^ UnoInterfaceProxy::findInfo( ::System::Type ^ type )
+{
+ for (int i = 0; i < m_numUnoIfaces; i++)
+ {
+ UnoInterfaceInfo^ tmpInfo = static_cast<UnoInterfaceInfo^>(
+ m_listIfaces[i]);
+ if (type->IsAssignableFrom(tmpInfo->m_type))
+ return tmpInfo;
+ }
+ for ( int i = 0; i < m_nlistAdditionalProxies; ++i )
+ {
+ UnoInterfaceProxy ^ proxy =
+ static_cast< UnoInterfaceProxy ^ >(
+ m_listAdditionalProxies[ i ] );
+ UnoInterfaceInfo ^ info = proxy->findInfo( type );
+ if (nullptr != info)
+ return info;
+ }
+ return nullptr;
+}
+
+srrm::IMessage^ UnoInterfaceProxy::Invoke(srrm::IMessage^ callmsg)
+{
+ try
+ {
+ sc::IDictionary^ props= callmsg->Properties;
+ srrm::LogicalCallContext^ context=
+ static_cast<srrm::LogicalCallContext^>(
+ props[m_CallContextString]);
+ srrm::IMethodCallMessage^ mcm=
+ static_cast<srrm::IMethodCallMessage^>(callmsg);
+
+ //Find out which UNO interface is being called
+ System::String^ sTypeName = static_cast<System::String^>(
+ props[m_typeNameString]);
+ sTypeName = sTypeName->Substring(0, sTypeName->IndexOf(','));
+
+ // Special Handling for System.Object methods
+ if(sTypeName->IndexOf(m_system_Object_String) != -1)
+ {
+ return invokeObject(props, context, mcm);
+ }
+
+ System::Type^ typeBeingCalled = loadCliType(sTypeName);
+ UnoInterfaceInfo^ info = findInfo( typeBeingCalled );
+ OSL_ASSERT( nullptr != info );
+
+ // ToDo do without string conversion, an OUString is not needed here
+ // get the type description of the call
+ OUString usMethodName(mapCliString(static_cast<System::String^>(
+ props[m_methodNameString])));
+ typelib_TypeDescriptionReference ** ppAllMembers =
+ info->m_typeDesc->ppAllMembers;
+ sal_Int32 numberMembers = info->m_typeDesc->nAllMembers;
+ for ( sal_Int32 nPos = numberMembers; nPos--; )
+ {
+ typelib_TypeDescriptionReference * member_type = ppAllMembers[nPos];
+
+ // check usMethodName against fully qualified usTypeName
+ // of member_type; usTypeName is of the form
+ // <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
+ OUString const & usTypeName =
+ OUString::unacquired( & member_type->pTypeName );
+
+#if OSL_DEBUG_LEVEL >= 2
+ System::String^ pTypeName;
+ pTypeName = mapUnoString(usTypeName.pData);
+#endif
+ sal_Int32 offset = usTypeName.indexOf( ':' ) + 2;
+ OSL_ASSERT(
+ offset >= 2 && offset < usTypeName.getLength()
+ && usTypeName[offset - 1] == ':' );
+ sal_Int32 remainder = usTypeName.getLength() - offset;
+
+ if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass)
+ {
+ if ((usMethodName.getLength() == remainder
+ || (usMethodName.getLength() < remainder
+ && usTypeName[offset + usMethodName.getLength()] == ':'))
+ && usTypeName.match(usMethodName, offset))
+ {
+ TypeDescr member_td( member_type );
+ typelib_InterfaceMethodTypeDescription * method_td =
+ (typelib_InterfaceMethodTypeDescription *)
+ member_td.get();
+
+ array<System::Object^>^ args = static_cast<array<System::Object^>^>(
+ props[m_ArgsString]);
+ array<System::Type^>^ argTypes = static_cast<array<System::Type^>^>(
+ props[m_methodSignatureString]);
+ System::Object^ pExc = nullptr;
+ System::Object ^ cli_ret = m_bridge->call_uno(
+ info->m_unoI, member_td.get(),
+ method_td->pReturnTypeRef, method_td->nParams,
+ method_td->pParams, args, argTypes, &pExc);
+ return constructReturnMessage(cli_ret, args, method_td,
+ callmsg, pExc);
+ }
+ }
+ else
+ {
+ OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE ==
+ member_type->eTypeClass );
+ if (usMethodName.getLength() > 4
+ && (usMethodName.getLength() - 4 == remainder
+ || (usMethodName.getLength() - 4 < remainder
+ && usTypeName[
+ offset + (usMethodName.getLength() - 4)] == ':'))
+ && usMethodName[1] == 'e' && usMethodName[2] == 't'
+ && rtl_ustr_compare_WithLength(
+ usTypeName.getStr() + offset,
+ usMethodName.getLength() - 4,
+ usMethodName.getStr() + 4,
+ usMethodName.getLength() - 4) == 0)
+ {
+ if ('g' == usMethodName[0])
+ {
+ TypeDescr member_td( member_type );
+ typelib_InterfaceAttributeTypeDescription * attribute_td =
+ (typelib_InterfaceAttributeTypeDescription*)
+ member_td.get();
+
+ System::Object^ pExc = nullptr;
+ System::Object^ cli_ret= m_bridge->call_uno(
+ info->m_unoI, member_td.get(),
+ attribute_td->pAttributeTypeRef,
+ 0, 0,
+ nullptr, nullptr, &pExc);
+ return constructReturnMessage(cli_ret, nullptr, NULL,
+ callmsg, pExc);
+ }
+ else if ('s' == usMethodName[0])
+ {
+ TypeDescr member_td( member_type );
+ typelib_InterfaceAttributeTypeDescription * attribute_td =
+ (typelib_InterfaceAttributeTypeDescription *)
+ member_td.get();
+ if (! attribute_td->bReadOnly)
+ {
+ typelib_MethodParameter param;
+ param.pTypeRef = attribute_td->pAttributeTypeRef;
+ param.bIn = sal_True;
+ param.bOut = sal_False;
+
+ array<System::Object^>^ args =
+ static_cast<array<System::Object^>^>(
+ props[m_ArgsString]);
+ System::Object^ pExc = nullptr;
+ m_bridge->call_uno(
+ info->m_unoI, member_td.get(),
+ cppu::UnoType<void>::get().getTypeLibType(),
+ 1, &param, args, nullptr, &pExc);
+ return constructReturnMessage(nullptr, nullptr, NULL,
+ callmsg, pExc);
+ }
+ else
+ {
+ return constructReturnMessage(nullptr, nullptr, NULL,
+ callmsg, nullptr);
+ }
+ }
+ break;
+ }
+ }
+ }
+ // ToDo check if the message of the exception is not crippled
+ // the thing that should not be... no method info found!
+ throw BridgeRuntimeError("[cli_uno bridge]calling undeclared function on interface " +
+ OUString::unacquired(& ((typelib_TypeDescription *)info->m_typeDesc)->pTypeName) +
+ ": " + usMethodName);
+ }
+ catch (BridgeRuntimeError & err)
+ {
+ srrm::IMethodCallMessage^ mcm =
+ static_cast<srrm::IMethodCallMessage^>(callmsg);
+ return gcnew srrm::ReturnMessage(gcnew ucss::uno::RuntimeException(
+ mapUnoString(err.m_message.pData), nullptr), mcm);
+ }
+ catch (System::Exception^ e)
+ {
+ st::StringBuilder ^ sb = gcnew st::StringBuilder(512);
+ sb->Append(gcnew System::String(
+ "An unexpected CLI exception occurred in "
+ "UnoInterfaceProxy::Invoke. Original"
+ "message: \n"));
+ sb->Append(e->Message);
+ sb->Append((__wchar_t) '\n');
+ sb->Append(e->StackTrace);
+ srrm::IMethodCallMessage^ mcm =
+ static_cast<srrm::IMethodCallMessage^>(callmsg);
+ return gcnew srrm::ReturnMessage(gcnew ucss::uno::RuntimeException(
+ sb->ToString(), nullptr), mcm);
+ }
+ catch (...)
+ {
+ System::String^ msg = gcnew System::String(
+ "An unexpected native C++ exception occurred in "
+ "UnoInterfaceProxy::Invoke.");
+ srrm::IMethodCallMessage^ mcm =
+ static_cast<srrm::IMethodCallMessage^>(callmsg);
+ return gcnew srrm::ReturnMessage(gcnew ucss::uno::RuntimeException(
+ msg, nullptr), mcm);
+ }
+ return nullptr;
+}
+/** If the argument args is NULL then this function is called for an attribute
+ method (either setXXX or getXXX).
+ For attributes the argument mtd is also NULL.
+*/
+srrm::IMessage^ UnoInterfaceProxy::constructReturnMessage(
+ System::Object^ cliReturn,
+ array<System::Object^>^ args,
+ typelib_InterfaceMethodTypeDescription* mtd,
+ srrm::IMessage^ msg, System::Object^ exc)
+{
+ srrm::IMessage ^ retVal= nullptr;
+ srrm::IMethodCallMessage^ mcm = static_cast<srrm::IMethodCallMessage^>(msg);
+ if (exc)
+ {
+ retVal = gcnew srrm::ReturnMessage(
+ dynamic_cast<System::Exception^>(exc), mcm);
+ }
+ else
+ {
+ sc::IDictionary^ props= msg->Properties;
+ srrm::LogicalCallContext^ context=
+ static_cast<srrm::LogicalCallContext^>(
+ props[m_CallContextString]);
+ if (args != nullptr)
+ {
+ // Method
+ //build the array of out parameters, allocate max length
+ array<System::Object^>^ arOut= gcnew array<System::Object^>(mtd->nParams);
+ int nOut = 0;
+ for (int i= 0; i < mtd->nParams; i++)
+ {
+ if (mtd->pParams[i].bOut)
+ {
+ arOut[i]= args[i];
+ nOut++;
+ }
+ }
+ retVal= gcnew srrm::ReturnMessage(cliReturn, arOut, nOut,
+ context, mcm);
+ }
+ else
+ {
+ // Attribute (getXXX)
+ retVal= gcnew srrm::ReturnMessage(cliReturn, nullptr, 0,
+ context, mcm);
+ }
+ }
+ return retVal;
+}
+
+
+CliProxy::CliProxy(Bridge const* bridge, System::Object^ cliI,
+ typelib_TypeDescription const* td,
+ const OUString& usOid):
+ m_ref(1),
+ m_bridge(bridge),
+ m_cliI(cliI),
+ m_unoType(const_cast<typelib_TypeDescription*>(td)),
+ m_usOid(usOid),
+ m_oid(mapUnoString(usOid.pData)),
+ m_nInheritedInterfaces(0)
+{
+ m_bridge->acquire();
+ uno_Interface::acquire = cli_proxy_acquire;
+ uno_Interface::release = cli_proxy_release;
+ uno_Interface::pDispatcher = cli_proxy_dispatch;
+
+ m_unoType.makeComplete();
+ m_type= mapUnoType(m_unoType.get());
+
+ makeMethodInfos();
+#if OSL_DEBUG_LEVEL >= 2
+ sd::Trace::WriteLine(System::String::Format(
+ gcnew System::String("cli uno bridge: Creating proxy for cli object, "
+ "id:\n\t{0}\n\t{1}"), m_oid, m_type));
+#endif
+
+}
+
+void CliProxy::makeMethodInfos()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ System::Object^ cliI;
+ System::Type^ type;
+ cliI = m_cliI;
+ type = m_type;
+#endif
+
+ if (m_type->IsInterface == false)
+ return;
+ array<sr::MethodInfo^>^ arThisMethods = m_type->GetMethods();
+ //get the inherited interfaces
+ array<System::Type^>^ arInheritedIfaces = m_type->GetInterfaces();
+ m_nInheritedInterfaces = arInheritedIfaces->Length;
+ //array containing the number of methods for the interface and its
+ //inherited interfaces
+ m_arInterfaceMethodCount = gcnew array<int^>(m_nInheritedInterfaces + 1);
+ //determine the number of all interface methods, including the inherited
+ //interfaces
+ int numMethods = arThisMethods->Length;
+ for (int i= 0; i < m_nInheritedInterfaces; i++)
+ {
+ numMethods += arInheritedIfaces[i]->GetMethods()->Length;
+ }
+ //array containing MethodInfos of the cli object
+ m_arMethodInfos = gcnew array<sr::MethodInfo^>(numMethods);
+ //array containing MethodInfos of the interface
+ m_arInterfaceMethodInfos = gcnew array<sr::MethodInfo^>(numMethods);
+ //array containing the mapping of Uno interface pos to pos in
+ //m_arMethodInfos
+ m_arUnoPosToCliPos = gcnew array<System::Int32>(numMethods);
+ // initialize with -1
+ for (int i = 0; i < numMethods; i++)
+ m_arUnoPosToCliPos[i] = -1;
+
+ //fill m_arMethodInfos with the mappings
+ // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
+ // to documentation
+ // but it is Type*[] instead. Bug in the framework?
+ System::Type^ objType = m_cliI->GetType();
+ try
+ {
+ int index = 0;
+ // now get the methods from the inherited interface
+ //arInheritedIfaces[0] is the direct base interface
+ //arInheritedIfaces[n] is the furthest inherited interface
+ //Start with the base interface
+ int nArLength = arInheritedIfaces->Length;
+ for (;nArLength > 0; nArLength--)
+ {
+ sr::InterfaceMapping mapInherited = objType->GetInterfaceMap(
+ arInheritedIfaces[nArLength - 1]);
+ int numMethods = mapInherited.TargetMethods->Length;
+ m_arInterfaceMethodCount[nArLength - 1] = numMethods;
+ for (int i = 0; i < numMethods; i++, index++)
+ {
+ m_arMethodInfos[index] = safe_cast<sr::MethodInfo^>(
+ mapInherited.TargetMethods[i]);
+
+ m_arInterfaceMethodInfos[index] = safe_cast<sr::MethodInfo^>(
+ mapInherited.InterfaceMethods[i]);
+ }
+ }
+ //At last come the methods of the furthest derived interface
+ sr::InterfaceMapping map = objType->GetInterfaceMap(m_type);
+ nArLength = map.TargetMethods->Length;
+ m_arInterfaceMethodCount[m_nInheritedInterfaces] = nArLength;
+ for (int i = 0; i < nArLength; i++,index++)
+ {
+ m_arMethodInfos[index]= safe_cast<sr::MethodInfo^>(
+ map.TargetMethods[i]);
+ m_arInterfaceMethodInfos[index]= safe_cast<sr::MethodInfo^>(
+ map.InterfaceMethods[i]);
+ }
+ }
+ catch (System::InvalidCastException^ )
+ {
+ throw BridgeRuntimeError("[cli_uno bridge] preparing proxy for cli interface: " + mapCliString(m_type->ToString()) + " \nfailed!");
+ }
+}
+
+sr::MethodInfo^ CliProxy::getMethodInfo(int nUnoFunctionPos,
+ const OUString& usMethodName, MethodKind methodKind)
+{
+ sr::MethodInfo^ ret = nullptr;
+ //deduct 3 for XInterface methods
+ nUnoFunctionPos -= 3;
+ System::Threading::Monitor::Enter(m_arUnoPosToCliPos);
+ try
+ {
+ int cliPos = m_arUnoPosToCliPos[nUnoFunctionPos];
+ if (cliPos != -1)
+ return m_arMethodInfos[cliPos];
+
+ //create the method function name
+ System::String^ sMethodName = mapUnoString(usMethodName.pData);
+ switch (methodKind)
+ {
+ case MK_METHOD:
+ break;
+ case MK_SET:
+ sMethodName = System::String::Concat(
+ const_cast<System::String^>(Constants::sAttributeSet),
+ sMethodName);
+ break;
+ case MK_GET:
+ sMethodName = System::String::Concat(
+ const_cast<System::String^>(Constants::sAttributeGet),
+ sMethodName);
+ break;
+ default:
+ OSL_ASSERT(0);
+ }
+ //Find the cli interface method that corresponds to the Uno method
+// System::String* sMethodName= mapUnoString(usMethodName.pData);
+ int indexCliMethod = -1;
+ //If the cli interfaces and their methods are in the same order
+ //as they were declared (inheritance chain and within the interface)
+ //then nUnoFunctionPos should lead to the correct method. However,
+ //the documentation does not say that this ordering is given.
+ if (sMethodName->Equals(m_arInterfaceMethodInfos[nUnoFunctionPos]->Name))
+ indexCliMethod = nUnoFunctionPos;
+ else
+ {
+ int cMethods = m_arInterfaceMethodInfos->Length;
+ for (int i = 0; i < cMethods; i++)
+ {
+ System::String^ cliMethod = m_arInterfaceMethodInfos[i]->Name;
+ if (cliMethod->Equals(sMethodName))
+ {
+ indexCliMethod = i;
+ break;
+ }
+ }
+ }
+ if (indexCliMethod == -1)
+ {
+ throw BridgeRuntimeError("[cli_uno bridge] CliProxy::getMethodInfo():cli object does not implement interface method: " + usMethodName);
+ }
+ m_arUnoPosToCliPos[nUnoFunctionPos] = indexCliMethod;
+ ret = m_arMethodInfos[indexCliMethod];
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit(m_arUnoPosToCliPos);
+ }
+
+ return ret;
+}
+
+CliProxy::~CliProxy()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ sd::Trace::WriteLine(System::String::Format(
+ gcnew System::String(
+ "cli uno bridge: Destroying proxy for cli object, "
+ "id:\n\t{0}\n\t{1}\n"),
+ m_oid, m_type));
+#endif
+ CliEnvHolder::g_cli_env->revokeInterface(m_oid, mapUnoType(m_unoType.get()));
+ m_bridge->release();
+}
+
+uno_Interface* CliProxy::create(Bridge const * bridge,
+ System::Object^ cliI,
+ typelib_TypeDescription const* pTD,
+ const OUString& ousOid)
+{
+ uno_Interface* proxy= static_cast<uno_Interface*>(
+ new CliProxy(bridge, cliI, pTD, ousOid));
+
+ //register proxy with target environment (uno)
+ (*bridge->m_uno_env->registerProxyInterface)(
+ bridge->m_uno_env,
+ reinterpret_cast<void**>(&proxy),
+ cli_proxy_free,
+ ousOid.pData, (typelib_InterfaceTypeDescription*) pTD);
+ //register original interface
+ CliEnvHolder::g_cli_env->registerInterface(cliI, mapUnoString(ousOid.pData),
+ mapUnoType((pTD)));
+
+ return proxy;
+}
+
+
+void SAL_CALL CliProxy::uno_DispatchMethod(
+ struct _uno_Interface *,
+ const struct _typelib_TypeDescription *,
+ void *,
+ void **,
+ uno_Any ** )
+{
+}
+inline void CliProxy::acquire() const
+{
+ if (1 == osl_atomic_increment( &m_ref ))
+ {
+ // rebirth of proxy zombie
+ void * that = const_cast< CliProxy * >( this );
+ // register at uno env
+ (*m_bridge->m_uno_env->registerProxyInterface)(
+ m_bridge->m_uno_env, &that,
+ cli_proxy_free, m_usOid.pData,
+ (typelib_InterfaceTypeDescription *)m_unoType.get() );
+#if OSL_DEBUG_LEVEL >= 2
+ OSL_ASSERT( this == (void const * const)that );
+#endif
+ }
+}
+
+inline void CliProxy::release() const
+{
+ if (0 == osl_atomic_decrement( &m_ref ))
+ {
+ // revoke from uno env on last release,
+ // The proxy can be resurrected if acquire is called before the uno
+ // environment calls cli_proxy_free. cli_proxy_free will
+ //delete the proxy. The environment does not acquire a registered
+ //proxy.
+ (*m_bridge->m_uno_env->revokeInterface)(
+ m_bridge->m_uno_env, const_cast< CliProxy * >( this ) );
+ }
+}
+}
+
+
+extern "C"
+void SAL_CALL cli_proxy_free( uno_ExtEnvironment *, void * proxy )
+ SAL_THROW_EXTERN_C()
+{
+ cli_uno::CliProxy * cliProxy = reinterpret_cast<
+ cli_uno::CliProxy * >( proxy );
+
+ delete cliProxy;
+}
+
+extern "C"
+void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
+ SAL_THROW_EXTERN_C()
+{
+ CliProxy const * cliProxy = static_cast< CliProxy const * >( pUnoI );
+ cliProxy->acquire();
+}
+
+extern "C"
+void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
+ SAL_THROW_EXTERN_C()
+{
+ CliProxy * cliProxy = static_cast< CliProxy * >( pUnoI );
+ cliProxy->release();
+}
+
+
+extern "C"
+
+void SAL_CALL cli_proxy_dispatch(
+ uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
+ void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
+ SAL_THROW_EXTERN_C()
+{
+ CliProxy * proxy = static_cast< CliProxy* >( pUnoI );
+ try
+ {
+ Bridge const* bridge = proxy->m_bridge;
+
+ switch (member_td->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+
+ sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
+ member_td)->nPosition;
+ typelib_InterfaceTypeDescription * iface_td =
+ (typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
+ OSL_ENSURE(
+ member_pos < iface_td->nAllMembers,
+ "### member pos out of range!" );
+ sal_Int32 function_pos =
+ iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
+ OSL_ENSURE(
+ function_pos < iface_td->nMapFunctionIndexToMemberIndex,
+ "### illegal function index!" );
+
+ if (uno_ret) // is getter method
+ {
+ OUString const& usAttrName= *(rtl_uString**)&
+ ((typelib_InterfaceMemberTypeDescription*) member_td)
+ ->pMemberName;
+ sr::MethodInfo^ info = proxy->getMethodInfo(function_pos,
+ usAttrName, CliProxy::MK_GET);
+ bridge->call_cli(
+ proxy->m_cliI,
+ info,
+ ((typelib_InterfaceAttributeTypeDescription *)member_td)
+ ->pAttributeTypeRef,
+ 0, 0, // no params
+ uno_ret, 0, uno_exc );
+ }
+ else // is setter method
+ {
+ OUString const& usAttrName= *(rtl_uString**) &
+ ((typelib_InterfaceMemberTypeDescription*) member_td)
+ ->pMemberName;
+ sr::MethodInfo^ info = proxy->getMethodInfo(function_pos + 1,
+ usAttrName, CliProxy::MK_SET);
+ typelib_MethodParameter param;
+ param.pTypeRef =
+ ((typelib_InterfaceAttributeTypeDescription *)member_td)
+ ->pAttributeTypeRef;
+ param.bIn = sal_True;
+ param.bOut = sal_False;
+
+ bridge->call_cli(
+ proxy->m_cliI,
+ // set follows get method
+ info,
+ 0 /* indicates void return */, &param, 1,
+ 0, uno_args, uno_exc );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
+ member_td)->nPosition;
+ typelib_InterfaceTypeDescription * iface_td =
+ (typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
+ OSL_ENSURE(
+ member_pos < iface_td->nAllMembers,
+ "### member pos out of range!" );
+ sal_Int32 function_pos =
+ iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
+ OSL_ENSURE(
+ function_pos < iface_td->nMapFunctionIndexToMemberIndex,
+ "### illegal function index!" );
+
+ switch (function_pos)
+ {
+ case 0: // queryInterface()
+ {
+ TypeDescr demanded_td(
+ *reinterpret_cast<typelib_TypeDescriptionReference **>(
+ uno_args[0]));
+ if (typelib_TypeClass_INTERFACE
+ != demanded_td.get()->eTypeClass)
+ {
+ throw BridgeRuntimeError(
+ "queryInterface() call demands an INTERFACE type!");
+ }
+
+ uno_Interface * pInterface = 0;
+ (*bridge->m_uno_env->getRegisteredInterface)(
+ bridge->m_uno_env,
+ (void **)&pInterface, proxy->m_usOid.pData,
+ (typelib_InterfaceTypeDescription *)demanded_td.get() );
+
+ if (0 == pInterface)
+ {
+ System::Type^ mgdDemandedType =
+ mapUnoType(demanded_td.get());
+ if (mgdDemandedType->IsInstanceOfType( proxy->m_cliI ))
+ {
+#if OSL_DEBUG_LEVEL > 0
+ OUString usOid(
+ mapCliString(
+ CliEnvHolder::g_cli_env->getObjectIdentifier(
+ proxy->m_cliI )));
+ OSL_ENSURE(usOid.equals( proxy->m_usOid ),
+ "### different oids!");
+#endif
+ uno_Interface* pUnoI = bridge->map_cli2uno(
+ proxy->m_cliI, demanded_td.get() );
+ uno_any_construct(
+ (uno_Any *)uno_ret, &pUnoI, demanded_td.get(), 0 );
+ (*pUnoI->release)( pUnoI );
+ }
+ else // object does not support demanded interface
+ {
+ uno_any_construct( (uno_Any *)uno_ret, 0, 0, 0 );
+ }
+ // no exception occurred
+ *uno_exc = 0;
+ }
+ else
+ {
+ uno_any_construct(
+ reinterpret_cast< uno_Any * >( uno_ret ),
+ &pInterface, demanded_td.get(), 0 );
+ (*pInterface->release)( pInterface );
+ *uno_exc = 0;
+ }
+ break;
+ }
+ case 1: // acquire this proxy
+ cli_proxy_acquire(proxy);
+ *uno_exc = 0;
+ break;
+ case 2: // release this proxy
+ cli_proxy_release(proxy);
+ *uno_exc = 0;
+ break;
+ default: // arbitrary method call
+ {
+ typelib_InterfaceMethodTypeDescription * method_td =
+ (typelib_InterfaceMethodTypeDescription *)member_td;
+ OUString const& usMethodName= *(rtl_uString**) &
+ ((typelib_InterfaceMemberTypeDescription*) member_td)
+ ->pMemberName;
+
+ sr::MethodInfo^ info = proxy->getMethodInfo(function_pos,
+ usMethodName, CliProxy::MK_METHOD);
+ bridge->call_cli(
+ proxy->m_cliI,
+ info,
+ method_td->pReturnTypeRef, method_td->pParams,
+ method_td->nParams,
+ uno_ret, uno_args, uno_exc);
+ return;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError(
+ "illegal member type description!" );
+ }
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+ // binary identical struct
+ css::uno::RuntimeException exc(
+ "[cli_uno bridge error] " + err.m_message,
+ css::uno::Reference<
+ css::uno::XInterface >() );
+ css::uno::Type const & exc_type = cppu::UnoType<decltype(exc)>::get();
+ uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0);
+ SAL_WARN( "cli", exc);
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_proxy.h b/cli_ure/source/uno_bridge/cli_proxy.h
new file mode 100644
index 000000000..25f7d2801
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_proxy.h
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_PROXY_H
+#define INCLUDED_CLI_URE_SOURCE_UNO_BRIDGE_CLI_PROXY_H
+
+#include "uno/environment.hxx"
+#include "uno/mapping.hxx"
+#include "uno/dispatcher.h"
+#include "cli_bridge.h"
+#include "cli_environment.h"
+
+#using <cli_ure.dll>
+
+namespace srrp = System::Runtime::Remoting::Proxies;
+namespace srrm = System::Runtime::Remoting::Messaging;
+namespace srr = System::Runtime::Remoting;
+namespace sr = System::Reflection;
+namespace sc = System::Collections;
+using namespace uno;
+
+namespace cli_uno
+{
+
+public ref class UnoInterfaceInfo
+{
+public:
+ UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
+ typelib_InterfaceTypeDescription* td);
+ ~UnoInterfaceInfo();
+ !UnoInterfaceInfo();
+
+ uno_Interface * m_unoI; // wrapped interface
+ System::Type ^ m_type;
+ typelib_InterfaceTypeDescription* m_typeDesc;
+
+ Bridge const* m_bridge;
+};
+
+public ref class UnoInterfaceProxy: public srrp::RealProxy,
+ public srr::IRemotingTypeInfo
+{
+ /** used for IRemotingTypeInfo.TypeName
+ */
+ System::String^ m_sTypeName;
+ /** The list is filled with UnoInterfaceInfo objects. The list can only
+ grow and elements are never changed. If an element was added it
+ must not be changed!
+ */
+ sc::ArrayList^ m_listIfaces;
+ /** The number of UNO interfaces this proxy represents. It corresponds
+ to the number of elements in m_listIfaces.
+ */
+ int m_numUnoIfaces;
+ /** The list is filled with additional UnoInterfaceProxy object due
+ to aggregation via bridges. Though the latter is strongly
+ discouraged, this has to be supported.
+ */
+ sc::ArrayList^ m_listAdditionalProxies;
+ int m_nlistAdditionalProxies;
+
+ UnoInterfaceInfo ^ findInfo( ::System::Type ^ type );
+
+ Bridge const* m_bridge;
+ System::String^ m_oid;
+
+#if OSL_DEBUG_LEVEL >= 2
+ /** The string contains all names of UNO interfaces which are
+ represented by this proxy. It is used to print out the interfaces
+ when this proxy dies. In the destructor it is not allowed to
+ access m_listIfaces or any other managed object.
+ */
+ rtl_uString * _sInterfaces;
+// /** Count of interfaces. Used in conjunction with _sInterfaces.
+// */
+ int _numInterfaces;
+#endif
+
+public:
+
+ /** Creates a proxy and registers it on the dot NET side.
+ */
+ static System::Object^ create(Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTd,
+ const OUString& oid);
+
+ /** RealProxy::Invoke */
+ virtual srrm::IMessage^ Invoke(srrm::IMessage^ msg) override;
+
+ /** Must be called from within a synchronized section.
+ Add only the interface if it is not already contained.
+ This method is called from the constructor and as a result
+ of IRemotingTypeInfo::CanCastTo
+ */
+ void addUnoInterface(uno_Interface* pUnoI,
+ typelib_InterfaceTypeDescription* pTd);
+ ~UnoInterfaceProxy();
+ !UnoInterfaceProxy();
+
+ inline System::String ^ getOid()
+ { return m_oid; }
+
+ //IRemotingTypeInfo ----------------------------------------------
+ virtual bool CanCastTo(System::Type^ fromType, System::Object^ o);
+
+ virtual property System::String^ TypeName
+ {
+ System::String^ get()
+ {
+ return m_sTypeName;
+ };
+ void set(System::String^ name)
+ {
+ m_sTypeName = name;
+ };
+ }
+
+
+private:
+ UnoInterfaceProxy(
+ Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTD,
+ const OUString& oid );
+
+ static srrm::IMessage^ constructReturnMessage(System::Object^ retVal,
+ array<System::Object^>^ outArgs,
+ typelib_InterfaceMethodTypeDescription* mtd,
+ srrm::IMessage^ msg, System::Object^ exc);
+
+ static System::String^ m_methodNameString =
+ gcnew System::String("__MethodName");
+ static System::String^ m_typeNameString = gcnew System::String("__TypeName");
+ static System::String^ m_ArgsString = gcnew System::String("__Args");
+ static System::String^ m_CallContextString =
+ gcnew System::String("__CallContext");
+ static System::String^ m_system_Object_String =
+ gcnew System::String("System.Object");
+ static System::String^ m_methodSignatureString =
+ gcnew System::String("__MethodSignature");
+ static System::String^ m_Equals_String = gcnew System::String("Equals");
+ static System::String^ m_GetHashCode_String =
+ gcnew System::String("GetHashCode");
+ static System::String^ m_GetType_String = gcnew System::String("GetType");
+ static System::String^ m_ToString_String = gcnew System::String("ToString");
+
+protected:
+ srrm::IMessage^ invokeObject(sc::IDictionary^ properties,
+ srrm::LogicalCallContext^ context,
+ srrm::IMethodCallMessage^ mcm);
+};
+
+
+//Cannot make this __gc because a managed type cannot derive from unmanaged type
+struct CliProxy: public uno_Interface
+{
+ mutable oslInterlockedCount m_ref;
+ const Bridge* m_bridge;
+ const gcroot<System::Object^> m_cliI;
+ gcroot<System::Type^> m_type;
+ const css::uno::TypeDescription m_unoType;
+ const gcroot<System::String^> m_oid;
+ const OUString m_usOid;
+
+ enum MethodKind {MK_METHOD = 0, MK_SET, MK_GET};
+ /** The array contains MethodInfos of the cli object. Each one reflects an
+ implemented interface method of the interface for which this proxy was
+ created. The MethodInfos are from the object's method and not from the
+ interface type. That is, they can be used to invoke the methods. The
+ order of the MethodInfo objects corresponds to the order of the
+ interface methods (see member m_type). Position 0 contains the
+ MethodInfo of the first method of the interface which represents the
+ root of the inheritance chain. The last MethodInfo represents the last
+ method of the furthest derived interface.
+
+ The array is completely initialized in the constructor of this object.
+
+ When the uno_DispatchMethod is called for this proxy then it receives
+ a typelib_TypeDescription of the member which is either an attribute
+ (setter or getter) or method. After determining the position of the
+ method within the UNO interface one can use the position to obtain the
+ MethodInfo of the corresponding cli method. To obtain the index for the
+ m_arMethodInfos array the function position has to be decreased by 3.
+ This is because, the cli interface does not contain the XInterface
+ methods.
+ */
+ gcroot<array<sr::MethodInfo^>^> m_arMethodInfos;
+
+ /** This array is similar to m_arMethodInfos but it contains the MethodInfo
+ objects of the interface (not the object). When a call is made from uno
+ to cli then the uno method name is compared to the cli method name. The
+ cli method name can be obtained from the MethodInfo object in this
+ array. The name of the actual implemented method may not be the same as
+ the interface method.
+ */
+ gcroot<array<sr::MethodInfo^>^> m_arInterfaceMethodInfos;
+
+ /** Maps the position of the method in the UNO interface to the position of
+ the corresponding MethodInfo in m_arMethodInfos. The Uno position must
+ not include the XInterface methods. For example,
+ pos 0 = XInterface::queryInterface
+ pos 1 = XInterface::acquire
+ pos 2 = XInterface::release
+
+ That is the real Uno position has to be deducted by 3. Then
+ arUnoPosToCliPos[pos] contains the index for m_arMethodInfos.
+
+ */
+ gcroot<array<System::Int32>^> m_arUnoPosToCliPos;
+
+ /** Count of inherited interfaces of the cli interface.
+ */
+ int m_nInheritedInterfaces;
+ /** Contains the number of methods of each interface.
+ */
+ gcroot<array<System::Int32^>^> m_arInterfaceMethodCount;
+
+ CliProxy( Bridge const* bridge, System::Object^ cliI,
+ typelib_TypeDescription const* pTD,
+ const OUString& usOid);
+ ~CliProxy();
+
+ static uno_Interface* create(Bridge const * bridge,
+ System::Object^ cliI,
+ typelib_TypeDescription const * TD,
+ OUString const & usOid );
+
+ /** Prepares an array (m_arMethoInfos) containing MethodInfo object of the
+ interface and all inherited interfaces. At index null is the first
+ method of the base interface and at the last position is the last method
+ of the furthest derived interface.
+ If a UNO call is received then one can determine the position of the
+ method (or getter or setter for an attribute) from the passed type
+ information. The position minus 3 (there is no XInterface in the cli
+ mapping) corresponds to the index of the cli interface method in the
+ array.
+ */
+ void makeMethodInfos();
+
+ /**Obtains a MethodInfo which can be used to invoke the cli object.
+ Internally it maps nUnoFunctionPos to an index that is used to get the
+ corresponding MethodInfo object from m_arMethoInfos. The mapping table
+ is dynamically initialized. If the cli interface has no base interface
+ or exactly one then the mapping table is initialized in one go at the
+ first call. In all ensuing calls the MethodInfo object is immediately
+ retrieved through the mapping table.
+
+ If the interface has more than one interface in its inheritance chain,
+ that is Type.GetInterfaces return more than one Type, then the mapping
+ table is partially initialized. On the first call the mappings for the
+ methods of the belonging interface are created.
+
+ The implementation assumes that the order of interface methods as
+ provided by InterfaceMapping.InterfaceMethods corresponds to the order
+ of methods in the interface declaration.
+
+ @param nUnoFunctionPos
+ Position of the method in the uno interface.
+ */
+ sr::MethodInfo^ getMethodInfo(int nUnoFunctionPos,
+ const OUString & usMethodName,
+ MethodKind mk);
+
+ void SAL_CALL uno_DispatchMethod(
+ struct _uno_Interface * pUnoI,
+ const struct _typelib_TypeDescription * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException );
+
+ inline void acquire() const;
+ inline void release() const;
+};
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/uno_bridge/cli_uno.cxx b/cli_ure/source/uno_bridge/cli_uno.cxx
new file mode 100644
index 000000000..6af17e065
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_uno.cxx
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <sal/alloca.h>
+#include <osl/diagnose.h>
+#include "rtl/ustrbuf.hxx"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+namespace sr=System::Reflection;
+
+
+namespace cli_uno
+{
+
+union largest
+{
+ sal_Int64 n;
+ double d;
+ void * p;
+ uno_Any a;
+};
+
+System::Object^ Bridge::call_uno(uno_Interface * pUnoI,
+ typelib_TypeDescription* member_td,
+ typelib_TypeDescriptionReference * return_type,
+ sal_Int32 nParams, typelib_MethodParameter const * pParams,
+ array<System::Object^>^ args, array<System::Type^>^ argTypes,
+ System::Object^* ppExc) const
+{
+ // return mem
+ sal_Int32 return_size = sizeof (largest);
+ if ((0 != return_type) &&
+ (typelib_TypeClass_STRUCT == return_type->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == return_type->eTypeClass))
+ {
+ TypeDescr return_td( return_type );
+ if (return_td.get()->nSize > sizeof (largest))
+ return_size = return_td.get()->nSize;
+ }
+ //Prepare memory that contains all converted arguments and return value
+ //The memory block contains first pointers to the arguments which are in the same block
+ // For example, 2 arguments, 1 ret.
+ //
+ // | Pointer
+ // | Pointer
+ // | Return value
+ // | Arg 1
+ // | Arg 2
+ //
+ // If an argument is larger then union largest, such as some structures, then the pointer
+ // points to an extra block of memory. The same goes for a big return value.
+
+ char * mem = (char *)alloca(
+ (nParams * sizeof (void *)) + return_size + (nParams * sizeof (largest)) );
+ //array of pointers to args
+ void ** uno_args = (void **)mem;
+ //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int )
+ void * uno_ret= NULL;
+ if ( !(member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE && nParams == 1))
+ uno_ret = (mem + (nParams * sizeof (void *)));
+ largest * uno_args_mem = (largest *)(mem + (nParams * sizeof (void *)) + return_size);
+
+ OSL_ASSERT( (0 == nParams) || (nParams == args->Length) );
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ typelib_TypeDescriptionReference * type = param.pTypeRef;
+
+ uno_args[ nPos ] = &uno_args_mem[ nPos ];
+ if (typelib_TypeClass_STRUCT == type->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == type->eTypeClass)
+ {
+ TypeDescr td( type );
+ if (td.get()->nSize > sizeof (largest))
+ uno_args[ nPos ] = alloca( td.get()->nSize );
+ }
+
+ if (param.bIn)
+ {
+ try
+ {
+ // in, in/out params
+ map_to_uno(
+ uno_args[ nPos ],args[nPos] , type, false /* no assign */);
+ }
+ catch (...)
+ {
+ // cleanup uno in args
+ for (sal_Int32 n = 0; n < nPos; ++n)
+ {
+ typelib_MethodParameter const & param = pParams[n];
+ if (param.bIn)
+ {
+ uno_type_destructData(uno_args[n], param.pTypeRef, 0);
+ }
+ }
+ throw;
+ }
+ }
+ }
+ uno_Any uno_exc_holder;
+ uno_Any * uno_exc = &uno_exc_holder;
+ // call binary uno
+
+ (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc );
+
+ if (0 == uno_exc)
+ {
+ // convert out args; destruct uno args
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ typelib_TypeDescriptionReference * type = param.pTypeRef;
+ if (param.bOut)
+ {
+ try
+ {
+ pin_ptr<System::Object^> ptr = &args[nPos];
+ map_to_cli(
+ ptr, uno_args[nPos], param.pTypeRef,
+ argTypes != nullptr ? argTypes[nPos] : nullptr, false );
+ }
+ catch (...)
+ {
+ // cleanup further uno args
+ for ( sal_Int32 n = nPos; n < nParams; ++n )
+ {
+ uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 );
+ }
+ // cleanup uno return value
+ uno_type_destructData( uno_ret, return_type, 0 );
+ throw;
+ }
+ }
+ //cleanup args
+ if (typelib_TypeClass_DOUBLE < type->eTypeClass &&
+ typelib_TypeClass_ENUM != type->eTypeClass) // opt
+ {
+ uno_type_destructData(uno_args[nPos], type, 0);
+ }
+ }
+
+ if ((0 != return_type) &&
+ (typelib_TypeClass_VOID != return_type->eTypeClass))
+ {
+ // convert uno return value
+ try
+ {
+ System::Object^ cli_ret;
+ map_to_cli(
+ &cli_ret, uno_ret, return_type, nullptr, false);
+ uno_type_destructData(uno_ret, return_type, 0);
+ return cli_ret;
+ }
+ catch (...)
+ {
+ uno_type_destructData(uno_ret, return_type, 0);
+ throw;
+ }
+ }
+ return nullptr; // void return
+ }
+ else // exception occurred
+ {
+ // destruct uno in args
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ if (param.bIn)
+ {
+ uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 );
+ }
+ }
+ map_to_cli(ppExc, uno_exc_holder.pData,
+ uno_exc_holder.pType, nullptr, false);
+ return nullptr;
+ }
+}
+
+void Bridge::call_cli(
+ System::Object^ cliI,
+ sr::MethodInfo^ method,
+ typelib_TypeDescriptionReference * return_type,
+ typelib_MethodParameter * params, int nParams,
+ void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
+{
+ array<System::Object^>^ args= gcnew array<System::Object^>(nParams);
+ for (int nPos= 0; nPos < nParams; nPos++)
+ {
+ typelib_MethodParameter const & param= params[nPos];
+ if (param.bIn)
+ {
+ pin_ptr<System::Object^> ptr = &args[nPos];
+ map_to_cli( ptr,
+ uno_args[nPos], param.pTypeRef, nullptr, false);
+ }
+ }
+ System::Object^ retInvoke= nullptr;
+ try
+ {
+ retInvoke= method->Invoke(cliI, args);
+ }
+ catch (sr::TargetInvocationException^ e)
+ {
+ System::Exception^ exc= e->InnerException;
+ css::uno::TypeDescription td(mapCliType(exc->GetType()));
+ // memory for exception
+ std::unique_ptr< rtl_mem > memExc(rtl_mem::allocate(td.get()->nSize));
+ map_to_uno(memExc.get(), exc, td.get()->pWeakRef, false);
+ (*uno_exc)->pType= td.get()->pWeakRef;
+ (*uno_exc)->pData= memExc.release();
+ return;
+ }
+ catch (System::Exception^ e)
+ {
+ throw BridgeRuntimeError("Unexpected exception during invocation of cli object. Original message is: \n" + mapCliString(e->Message));
+ }
+
+ //convert out, in/out params
+ for (int nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = params[ nPos ];
+
+ if (param.bOut)
+ {
+ try
+ {
+ map_to_uno(
+ uno_args[ nPos ], args[ nPos ], param.pTypeRef,
+ sal_True == param.bIn /* assign if inout */);
+ // out array
+ }
+ catch (...)
+ {
+ // cleanup uno pure out
+ for ( sal_Int32 n = 0; n < nPos; ++n )
+ {
+ typelib_MethodParameter const & param = params[ n ];
+ if (! param.bIn)
+ uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 );
+ }
+ throw;
+ }
+ }
+ }
+ // return value
+ if (0 != return_type)
+ {
+ map_to_uno(
+ uno_ret, retInvoke, return_type, false /* no assign */);
+ }
+ // no exception occurred
+ *uno_exc = 0;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cli_ure/source/ure/assembly.cs b/cli_ure/source/ure/assembly.cs
new file mode 100644
index 000000000..1b946180d
--- /dev/null
+++ b/cli_ure/source/ure/assembly.cs
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+[assembly:System.Reflection.AssemblyDescription( "CLI-UNO Runtime Library" )]
+[assembly:System.Reflection.AssemblyCompany( "OpenOffice.org" )]
+[assembly:System.Reflection.AssemblyVersion( "@CLI_URE_NEW_VERSION@" )]
diff --git a/cli_ure/source/ure/cli_ure_config b/cli_ure/source/ure/cli_ure_config
new file mode 100644
index 000000000..14dfd7a5a
--- /dev/null
+++ b/cli_ure/source/ure/cli_ure_config
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="cli_ure" publicKeyToken="ce2cb7e279207b9e"/>
+ <bindingRedirect oldVersion="CLI_URE_OLD_VERSION" newVersion="CLI_URE_NEW_VERSION" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/cli_ure/source/ure/uno/util/DisposeGuard.cs b/cli_ure/source/ure/uno/util/DisposeGuard.cs
new file mode 100644
index 000000000..ce2e90ddf
--- /dev/null
+++ b/cli_ure/source/ure/uno/util/DisposeGuard.cs
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using unoidl.com.sun.star.lang;
+
+namespace uno.util
+{
+
+/** Helper class to conveniently auto dispose UNO objects from within
+ managed code.
+*/
+public struct DisposeGuard : IDisposable
+{
+ private XComponent m_xComponent;
+
+ /** ctor.
+
+ @param obj target object
+ */
+ public DisposeGuard( XComponent obj )
+ {
+ m_xComponent = obj;
+ }
+
+ /** System.IDisposable impl
+ */
+ public void Dispose()
+ {
+ if (null != m_xComponent)
+ m_xComponent.dispose();
+ }
+}
+
+}
diff --git a/cli_ure/source/ure/uno/util/WeakAdapter.cs b/cli_ure/source/ure/uno/util/WeakAdapter.cs
new file mode 100644
index 000000000..508a4b0f1
--- /dev/null
+++ b/cli_ure/source/ure/uno/util/WeakAdapter.cs
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using unoidl.com.sun.star.uno;
+using unoidl.com.sun.star.lang;
+
+namespace uno.util
+{
+
+/** An XAdapter implementation that holds a weak reference
+ (System.WeakReference) to an object.
+ Clients can register listeners (unoidl.com.sun.star.lang.XReference)
+ which are notified when the object (the one which is kept weak) is
+ being finalized. That is, that object is being destroyed because there
+ are not any hard references to it.
+*/
+public class WeakAdapter : XAdapter
+{
+ // references the XWeak implementation
+ private WeakReference m_weakRef;
+ // contains XReference objects registered by addReference
+ private delegate void XReference_dispose();
+ private XReference_dispose m_XReference_dispose;
+
+ /** ctor.
+
+ @param obj the object that is to be held weakly
+ */
+ public WeakAdapter( Object obj )
+ {
+ m_weakRef = new WeakReference( obj );
+ m_XReference_dispose = null;
+ }
+
+ /** Called by the XWeak implementation (WeakBase) when it is being
+ finalized. It is only being called once.
+ The registererd XReference listeners are notified. On notification
+ they are to unregister themselves. The notification is thread-safe.
+ However, it is possible to add a listener during the notification
+ process, which will never receive a notification.
+ To prevent this, one would have to synchronize this method with
+ the addReference method. But this can result in deadlocks in a
+ multithreaded environment.
+ */
+ internal /* non-virtual */ void referentDying()
+ {
+ XReference_dispose call;
+ lock (this)
+ {
+ call = m_XReference_dispose;
+ m_XReference_dispose = null;
+ }
+ if (null != call)
+ call();
+ }
+
+ // XAdapter impl
+
+ /** Called to obtain a hard reference o the object which is kept weakly
+ by this instance.
+
+ @return hard reference to the object
+ */
+ public Object queryAdapted()
+ {
+ return m_weakRef.Target;
+ }
+ /** Called by clients to register listener which are notified when the
+ weak object is dying.
+
+ @param xReference a listener
+ */
+ public void removeReference( XReference xReference )
+ {
+ lock (this)
+ {
+ m_XReference_dispose -=
+ new XReference_dispose( xReference.dispose );
+ }
+ }
+ /** Called by clients to unregister listeners.
+
+ @param xReference a listener
+ */
+ public void addReference( XReference xReference )
+ {
+ lock (this)
+ {
+ m_XReference_dispose +=
+ new XReference_dispose( xReference.dispose );
+ }
+ }
+}
+
+}
diff --git a/cli_ure/source/ure/uno/util/WeakBase.cs b/cli_ure/source/ure/uno/util/WeakBase.cs
new file mode 100644
index 000000000..561d2e577
--- /dev/null
+++ b/cli_ure/source/ure/uno/util/WeakBase.cs
@@ -0,0 +1,135 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using System.Collections;
+using unoidl.com.sun.star.uno;
+using unoidl.com.sun.star.lang;
+
+namespace uno.util
+{
+
+/** This class can be used as a base class for UNO objects.
+ It implements the capability to be kept weakly
+ (unoidl.com.sun.star.uno.XWeak) and it implements
+ unoidl.com.sun.star.lang.XTypeProvider which is necessary for
+ using the object from StarBasic.
+*/
+public class WeakBase : XWeak, XTypeProvider
+{
+ // Contains all WeakAdapter which have been created in this class
+ // They have to be notified when this object dies
+ private WeakAdapter m_adapter = null;
+
+ protected static Hashtable s_types = new Hashtable();
+ protected static Hashtable s_impl_ids = new Hashtable();
+
+ // XWeak impl
+ /** The returned XAdapter implementation can be used to keap a
+ weak reference to this object.
+
+ @return a weak adapter
+ */
+ public XAdapter queryAdapter()
+ {
+ if (null == m_adapter)
+ {
+ lock (this)
+ {
+ if (null == m_adapter)
+ m_adapter = new WeakAdapter( this );
+ }
+ }
+ return m_adapter;
+ }
+
+ /** Overrides of Object.Finalize method.
+ When there are no references to this object anymore, then the
+ garbage collector calls this method, thereby causing the adapter
+ object to be notified. The adapter, in turn, notifies all
+ listeners (unoidl.com.sun.star.uno.XReference).
+ */
+ ~WeakBase()
+ {
+ if (null != m_adapter)
+ m_adapter.referentDying();
+ }
+
+ // XTypeProvider impl
+
+ /** Returns an array of Type objects which represent all implemented
+ UNO interfaces of this object.
+
+ @return Type objects of all implemented interfaces.
+ */
+ public Type [] getTypes()
+ {
+ Type [] types;
+ Type type = GetType();
+ lock (s_types)
+ {
+ types = (Type []) s_types[ type ];
+ if (null == types)
+ {
+ Type [] interfaces = type.GetInterfaces();
+ ArrayList list = new ArrayList( interfaces.Length );
+ for ( Int32 pos = 0; pos < interfaces.Length; ++pos )
+ {
+ Type iface = interfaces[ pos ];
+ // xxx todo: as long as the bridge cannot introduce
+ // native CTS types into UNO on the fly
+ if (iface.FullName.StartsWith( "unoidl." ))
+ {
+ list.Add( iface );
+ }
+ }
+ Int32 len = list.Count;
+ Type [] ar = new Type [ len ];
+ for ( Int32 pos = 0; pos < len; ++pos )
+ ar[ pos ] = (Type) list[ pos ];
+ s_types[ type ] = ar;
+ types = ar;
+ }
+ }
+ return types;
+ }
+
+ public byte [] getImplementationId()
+ {
+ return new byte[0];
+ }
+
+ // System.Object
+ public override String ToString()
+ {
+ System.Text.StringBuilder buf =
+ new System.Text.StringBuilder( base.ToString(), 256 );
+ buf.Append( "\nUNO Object Implementation:\n\tInterfaces: " );
+ Type [] types = getTypes();
+ for ( Int32 pos = 0; pos < types.Length; ++pos )
+ {
+ buf.Append( types[ pos ].FullName );
+ if (pos < (types.Length -1))
+ buf.Append( ", " );
+ }
+ return buf.ToString();
+ }
+}
+
+}
+
diff --git a/cli_ure/source/ure/uno/util/WeakComponentBase.cs b/cli_ure/source/ure/uno/util/WeakComponentBase.cs
new file mode 100644
index 000000000..48715afc6
--- /dev/null
+++ b/cli_ure/source/ure/uno/util/WeakComponentBase.cs
@@ -0,0 +1,185 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+using System;
+using unoidl.com.sun.star.lang;
+
+namespace uno.util
+{
+
+/** This class can be used as a base class for UNO objects.
+ It implements the capability to be kept weakly
+ (unoidl.com.sun.star.uno.XWeak) and it implements
+ unoidl.com.sun.star.lang.XTypeProvider which is necessary for
+ using the object from StarBasic.
+ In addition, it implements the interface
+ unoidl.com.sun.star.lang.XComponent to be disposed explicitly.
+*/
+public class WeakComponentBase : WeakBase, XComponent
+{
+ private delegate void t_disposing( EventObject evt );
+ private t_disposing m_disposing = null;
+ private bool m_inDispose = false;
+ private bool m_disposed = false;
+
+ /** Indicates whether object is already disposed.
+
+ @return
+ true, if object has been disposed
+ */
+ protected bool isDisposed()
+ {
+ lock (this)
+ {
+ return m_disposed;
+ }
+ }
+
+ /** Checks whether this object is disposed and throws a DisposedException
+ if it is already disposed.
+ */
+ protected void checkUnDisposed()
+ {
+ if (! isDisposed())
+ {
+ throw new unoidl.com.sun.star.lang.DisposedException(
+ "object already disposed!", this );
+ }
+ }
+
+ ~WeakComponentBase()
+ {
+ bool doDispose;
+ lock (this)
+ {
+ doDispose = (!m_inDispose && !m_disposed);
+ }
+ if (doDispose)
+ {
+ dispose();
+ }
+ }
+
+ /** Override to perform extra clean-up work. Provided for subclasses.
+ It is called during dispose()
+ */
+ protected void preDisposing()
+ {
+ }
+
+ /** Override to become notified right before the disposing action is
+ performed.
+ */
+ protected void postDisposing()
+ {
+ }
+
+ // XComponent impl
+ /** This method is called by the owner of this object to explicitly
+ dispose it. This implementation of dispose() first notifies this object
+ via preDisposing(), then all registered event listeners and
+ finally this object again calling postDisposing().
+ */
+ public void dispose()
+ {
+ // Determine in a thread-safe way if this is the first call to this
+ // method. Only then we proceed with the notification of event
+ // listeners. It is an error to call this method more than once.
+ bool doDispose = false;
+ t_disposing call = null;
+ lock (this)
+ {
+ if (! m_inDispose && !m_disposed)
+ {
+ call = m_disposing;
+ m_disposing = null;
+ m_inDispose = true;
+ doDispose = true;
+ }
+ }
+ // The notification occurs in an unsynchronized block in order to avoid
+ // deadlocks if one of the listeners calls back in a different thread on
+ // a synchronized method which uses the same object.
+ if (doDispose)
+ {
+ try
+ {
+ // call sub class
+ preDisposing();
+ // send disposing notifications to listeners
+ if (null != call)
+ {
+ EventObject evt = new EventObject( this );
+ call( evt );
+ }
+ // call sub class
+ postDisposing();
+ }
+ finally
+ {
+ // finally makes sure that the flags are set ensuring
+ // that this function is only called once.
+ m_disposed = true;
+ m_inDispose = false;
+ }
+ }
+ else
+ {
+ // in a multithreaded environment, it can't be avoided,
+ // that dispose is called twice.
+ // However this condition is traced, because it MAY indicate an
+ // error.
+#if DEBUG
+ Console.WriteLine(
+ "WeakComponentBase.dispose() - dispose called twice" );
+#endif
+// Debug.Fail( "WeakComponentBase.dispose() - dispose called twice" );
+ }
+ }
+ /** Registers an event listener being notified when this object is disposed.
+
+ @param xListener event listener
+ */
+ public void addEventListener( XEventListener xListener )
+ {
+ bool add;
+ lock (this)
+ {
+ add = (! m_inDispose && !m_disposed);
+ if (add)
+ m_disposing += new t_disposing( xListener.disposing );
+ }
+ if (! add)
+ xListener.disposing( new EventObject( this ) );
+ }
+ /** Revokes an event listener from being notified when this object
+ is disposed.
+
+ @param xListener event listener
+ */
+ public void removeEventListener( XEventListener xListener )
+ {
+ lock (this)
+ {
+ if (! m_inDispose && !m_disposed)
+ m_disposing -= new t_disposing( xListener.disposing );
+ }
+ }
+}
+
+}