regcomp
?
PropertyValue
should I use when loading an existing document?
queryInterface?
cannot dump type 'com/star/uno/RuntimeException'
mean?
symbol "component_getImplementationEnvironment" could not be found
mean?
TestOffice.java
?
OpenOffice
running on a different machine?
UnoUrlResolver
?
Great, you're always welcome. To find some ideas on where to help please browse
the open task list.
If you've got questions about any of these tasks
don't hesitate to ask them. Please post them to the
dev@udk.openoffice.org
mailing list.
In the near future, there will be an Office Development Kit available for download beside the openoffice-setup-set. This development kit contains all files (include-files, libraries, tools, etc.) that are necessary to build components. The development kit will also contain samples. These samples are built with makefiles, that only require gnumake (not the whole openoffice build environment). These makefiles can be used as a template to integrate the build of your UNO-components into your build environment.
Yes, UNO can be seen as an component model completely independent from the office itself. It is in direct competition to COM. You can find a feature list here.
The Office Development Kit (ODK) extends the UDK with additional documentation, API's (more IDL's), and examples. The UDK is a subset of the ODK. If you want to extend the OpenOffice, or write solutions with OpenOffice, the ODK fits your needs. The UDK is a standalone object model, which can be used without OpenOffice. The UDK will be the main target of integration discussions with Gnome and XPCOM, for achieving the long term goal of having only one Open Source Object Model. In the future, it should be possible to write components which depend on the ODK and components which are independent from OpenOffice.
The Office Development Kit shall enable software engineers to develop components for OpenOffice without the need of the bulky OpenOffice build environment. Thus, the ODK shall include the binaries of the base libraries (+import libraries), C++ header files, all idl-files, .jar files, and development tools (code generators, tools to register components, etc.) The ODK, additionally, includes some source examples and makefiles, that only require gnumake + C++-compiler, you can take the makefiles, as an example, to integrate them into your build environment. The development kit will be provided in the future alongside every OpenOffice build and will be available as an seperate download.
We wanted a middleware which can be used for components with a fine granularity, at least, in-process. If you use different UNO components in the same language than there is no overhead (e.g., in C++ a call is only a virtual method call). Unfortunately, CORBA has no in-process specification of interfaces and structures. The only way to communicate is through the IIOP protocol. The overhead is too high for in-process communication. And we wanted to be programming language independent: let UNO be a mediator between different languages like Java, C++, C and other languages. This isn't the goal of CORBA. Another goal of UNO is to be the mediator between different object models like COM/DCOM, CORBA, Java, and XPCOM which surely isn't a goal of other object models.
UNO does not generate stub code. We did this in the former UNO2 implementation.
One problem was, that the generated stub code was quite a heavy load (about 12 MB at former
times, even though the API had less types as compared to now!). With UNO3 (the
current version), we decided to generically call implementations, without
having generated stub code, just by providing bridging code that knows the
specific compiler that compiled the implementation. The only thing that
is generated for C++, besides the pure virtual classes, are the
getCppuType()
functions to reflect types. The full type description is
read at runtime from a binary storage. This approach has the advantage
that on increasing numbers of types, less space is consumed.
To see more the differences between UNO and CORBA, please have a look on the following
comparison.
UNO IDL has:
Yes, the OpenOffice bean (OOBean) project enables the use of OpenOffice components in Java applications. Please visit http://whiteboard.openoffice.org/OOBean/index.html for informations, source code, or binary downloads. The OO Bean features
C++ examples | |
Where | What |
udk/remotebridges/examples/officeclient.cxx | The example shows how to build up an interprocess bridge to an OpenOffice document. Please, remember that there are no differences if you write a component for Windows or Linux. |
udk/product/examples/ | More examples. |
HTML documentation | |
Where | What |
http://udk.openoffice.org/cpp/man/tutorial/remotedemo.html | Remote demo tutorial |
http://udk.openoffice.org/cpp/man/component_tutorial.html | Component writing in UNO space |
http://udk.openoffice.org/cpp/man/tutorial/unointro.html | C++ specific guide to UNO |
http://udk.openoffice.org/common/man/concept/unointro.html | Language independent guide to UNO |
We lack a good document on how to start developing using Java. You should have a look at the source, directly, and there are some examples in the jurt project, which you can check out using
$ cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs co oo/udk/jurtYou'll find some examples in the source code demo-tree:
Java examples | |
Where | What |
jurt/demo/com/sun/star/demo/TestOffice.java | Starts up an interprocess bridge and creates several documents in the office |
jurt/demo/com/sun/star/comp/demo/ | Here some sample code can be found on how to setup a JavaComponent. The sample can be registered with an office and thus runs within the same process as the office |
We also suggest having a look at the sun-developer-connection
(http://soldc.sun.com/staroffice), when you click on
Download SDK, you
can download the StarOffice Programmers Tutorial. It contains some
examples on certain API-topics.
Please use the dev@api.openoffice.org
mailing list
for asking highlevel office api questions.
unoidl
regmerge
cppumaker
(for java: use javamaker
)
regcomp
?
The unoidl
converts the IDL description into a binary
type library format; this type information is needed for every IDL
type at runtime. The generated output file of unoidl
contains only the type information of the specified IDL file. It
does not contain the complete type descriptions of all types. So, it is
necessary to install the new types in the type library
applicat.rdb
using regmerge
. If somebody has
developed a UNO component, he must support/export some administration
functions (e.g., component_writeInfo
). In the
component_writeInfo
function the developer gives some
information about the supported services and the implementation name.
This information is later used by the service manager to instantiate
the component. So, if you developed your own component, you must install
your component to the runtime. This could be done with regcomp
.
regcomp
reads the component_writeInfo
function
and does some administration work with the contained information. For
example, all supported services of the component are inserted in a global
SERVICES
section, which is used by the service manager. In
this section a relation between the service name and the
implementation name is established. Under the reserved area
IMPLEMENTATIONS
you'll find the appropriate section
for your own component, which is equal to the key defined in the
component_writeInfo
function. Please have a look at the
installed applicat.rdb
in your office directory:
$ regview applicat.rdb /SERVICES $ regview applicat.rdb /SERVICES/<service_name> $ regview applicat.rdb /IMPLEMENTATIONS $ regview applicat.rdb /IMPLEMENTATIONS/<implementation_name>So
regcomp
is always needed if you want to install
a new component. regmerge
is needed to install new types
in the type library.
Please visit the http://api.openoffice.org project site.
If you develop a new component it'll end up in a shared library or dynamic link library (DLL). The DLL will be loaded on demand if the implemented service is requested. To make the component visible and usable in the OpenOffice, you'll have to register your service as a external component. To achieve this you'll need to follow these steps:
.../program
directory
regcomp
into the .../program
directory. You will find
this tool in the UDK module cpputools
regcomp
tool
$ regcomp -register -r applicat.rdb -c foo.dll
regmerge
which you find in the UDK module registry
.
The unoidl
tool generated a foo.urd
file which contains the
new types. You'll find this file in the output directory of your component.
regmerge
tool
$ regmerge applicat.rdb /UCR foo.urdAll type descriptions of IDL types are stored in the registry under the reserved key UCR (UNO core reflection)
Sub Main s = createUnoService("YourSerivceName") msgbox(s.dbg_supportedinterfaces) End SubIf the instantiation is successful, the message box will show all supported interfaces of the object.
More information can be found in the README files in the directory http://www.openoffice.org/source/browse/udk/product/examples/.
Currently there exist 4 bridges: the C++ bridge, the Java bridge, the UNO Remote Protocol (URP) bridge, and the IIOP bridge.
If you develop your components in C++, remember that for in process calling of components compiled by the same compiler, there is no need to bridge any interface. The component loader recognizes this fact and uses the implemented C++ interface directly. But if you use scripting (e.g., basic) to call a Java component or to do remote UNO to some other process, bridging is indeed involved.
It is not possible to specify default values for structs because
these defaults cannot be used in other object models (e.g., CORBA).
It is also impossible to emulate default values for member variables
by modifying the unoidl
-generated default constructors for structs.
The default constructors set enums to the first enmum value, numbers
to 0, and the other types use their default constructors. The generated
inline default constructor can be found in the .hpp
file. The
constructor sets the members to known initial values only.
Since it's hard to tell from a stack trace only, what is going wrong, please send as much information as possible. If you're lucky, you're the writer of the service and you can send the component implementation code and the code which instantiates the object as well. If you are not the component developer then you're forced to contact the component developer.
The goal behind UNO is to provide the simplest language binding for the UNO component writer and user, the reduction of generated code, and a maximum of execution speed. With the current technique, the goals are reached. For example, in C++ there is no call overhead, because a C++ to C++ call is only a virtual method call. There is no compile time code generation, it is done by the bridge on the fly. The UNO C++ language binding is smarter than all other (CORBA, COM) bindings. On the other hand, writing a C++ bridge is a hard thing to do, but this has to be done only once for each compiler, operating system, and processor. There are simpler ways to achieve language bindings, but they aren't better ways. A bridge from cpp to uno is very compiler and abi dependent, and at first glance, it seems that it isn't portable at all. But it must be noted that the bridge code is pretty similar for most compilers. The main differences are the generated vtables, performing C++ virtual calls, and handling exceptions.
On RICS machines parameters to functions are passed in registers, whereas, the C++ bridge code manipulates a stack between the C++ layout and the required uno layout. For an example of how this is solved, please see the sunpro5 solaris sparc bridge. Registers are pushed right to stack (extending non-register parameters on the stack [if more than 6]).
PropertyValue
should I use when loading an existing document?A document is always opened through a loader with an empty property argument
PropertyValue [] szEmptyArgs = new PropertyValue [0]; String doc = "private:factory/swriter"; aDoc = oCLoader.loadComponentFromURL(doc, "_blank", 0, szEmptyArgs );Using these arguments, you can force OpenOffice to use a certain filter, open the document read-only, and set a password for password protected documents. The csv-filter for spreadsheet documents has some additional options here, which are the same as stored for the picklist in the soffice.ini/sofficerc when entered using the UI.
Here's some sample code for that:
PropertyValue [] mypv = new PropertyValue[1]; mypv[0] = new PropertyValue(); mypv[0].Name = new String("FilterName"); mypv[0].Value = new String("scalc: Text - txt"); mypv[0].Handle = -1; mypv[0].State = PropertyState.DEFAULT_VALUE; aStore.storeAsURL(doc, mypv); //aStore is a XStorable object, and doc is url string
Here's some sample code for that:
sub SaveXML dim mProps(0) as new com.sun.star.beans.PropertyValue mProps(0).Name = "FilterName" 'This works with 614 mProps(0).Value = "swriter: StarOffice XML (Writer)" oDesk = createUNOService("com.sun.star.frame.Desktop") 'For some reason, ActiveComponent no longer works: oComponent = oDesk.CurrentComponent() oComponent.storeAsUrl("file:///C|/Tmp/startemp.xml",_ mProps()) end sub
queryInterface?
You don't need to call queryInterface
directly. A more comfortable way
is to use a special reference constructor for this. Instead of
::com::sun::star::uno::Any x = xI->queryInterface( ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XTransliteration>*)0)); x >>= transRef;you should use:
transRef = Reference< XTransliteration >( xI, UNO_QUERY );
cannot dump type 'com/star/uno/RuntimeException'
mean?
First, make sure that you followed the
FAQ entry 'How do I generate C++ type definitions?'.
That means: you created a .idl
file that "describes" or "defines" the component.
You use the unoidl
tool to compile the idl file.
Run the cppumaker
on the resulting .urd
file.
The cppumaker
generates a C++ representation for idl types and
it works on a typelibrary which is generated by the unoidl
. If you
followed these steps and get the error:
cppumaker ERROR: cannot dump type 'com/star/uno/RuntimeException'
,
you must integrate your new type into the system type library
because the type information is needed at
runtime and also for generating the C++ code. For doing that, the easiest
way is to merge your 'XXX.urd' files into the system type library.
The system type library is called applicat.rdb
and can be found
in the program directory. To merge the type library, you must use the
tool regmerge
which you should find in the build environment.
All type information in the applicat.rdb
are saved under a
reserved area 'UCR'. You must merge your own types also in this
reserved area. Using regmerge
:
$ regmerge applicat.rdb /UCR yourtypes.urdThere exists another nice tool to view the contents of a registry file (= type library):
$ regview applicat.rdb /UCR/com/sun/star/unoThis shows all types of the module
com.sun.star.uno
or
$ regview applicat.rdb /UCR/com/sun/star/uno/XInterfaceshows the type information of
com.sun.star.uno.XInterface
Additional info about generating code: The cppumaker
needs all type
information because the cppumaker
generates the specified type and all
the dependencies. The depended types will be generated recursive, so that you
get all necessary C++ type declarations you need to build your component.
You now have to use the applicat.rdb
, that (after the regmerge
)
contains all types (the one that comes with the office and your new one). Note
that the regmerge
command only modifies the first file, the others are
opened readonly.
You should now check with regview
, that the regmerge
really worked and that it now contains your new type. For example:
$ regview applicat.rdb /UCR/com/sun/star/uno/RuntimeExceptionshould give output about the normal
RuntimeException
.
$ regview applicat.rdb /UCR/your/new/typesshould give output about your new type (of course replace
your/new/types
with the module and typename of the new type in idl).
Then the following command should generate C++ headers below your current working directory:
$ cppumaker -O. -Tyour/new/types -BUCR applicat.rdbIf this doesn't work, at least the following command should work:
$ cppumaker -O. -Tcom/sun/star/uno/RuntimeException -BUCR applicat.rdb
symbol "component_getImplementationEnvironment" could not be found
mean?
If you try to register your DLL with regcomp
like this:
$ regcomp -register -r applicat.rdb -c foo.dlland get the following error:
register component "foo.dll" in registry "applicat.rdb" failed! ERROR: component could not be registered: symbol "component_getImplementationEnvironment" could not be found in "foo.dll"Make sure that you defined the function outside any classes in a
.cxx
file like this:
extern "C" void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; }If you are not using a module definition file (
DEF
file), then you can use a
SAL_DLLEXPORT
macro
in front of your function definition, which expands to
__declspec(dllexport)
.
On Win32 platforms check your exports using
$ dumpbin /EXPORTS foo.dllIf this still doesn't work while registering your DLL, make sure that your path is correct and that all libraries
foo.dll
is linked against are accessible via your path.
On Win32 platforms you can use a tool which is
delivered with Developer Studio 6. It's called
depend
and shows library imports and missing libraries (marked red).
If this still doesn't help
you should debug the function writeRegistryInfo()
of the shared library component loader.
The loader is located in
the CVS module stoc
which
checks out the direcory oo/udk/stoc
.
Inside the stoc
directory the loader
is built in the directory source/loader
.
The built library is called cpld.dll
.
regmerge
overwrites existing keys. However, a tool to delete
existing keys would be nice to have, but there currently is none.
Service descriptions are not stored in the type library because reflective information about services aren't needed at runtime. A service description exists only for modelling purposes.
You can start the IDL compiler with a special option ( -C ) to generate a type library including service descriptions and comments, it is not used in a normal office build, as it approximately doubles the file size.
Some people do it by just copying an existing one and modifying it a
little. This is, of course, disapproved of, but it works for now. We currently don't
have our own tool, but you can use the guidgen.exe
that comes
with the microsoft compiler.
However, the guids are currently not used. They are there for historical reasons (the former UNO component model needed it) and we left it in for a future, maybe, UNO-COM bridge, which would require unique identifiers.
soffice -accept=socket,host=0,port=2002;urp;StarOffice.ServiceManager
( Please ensure to quote the ;
on a unix shell ).
<office-install>/share/config/registry/instance/org/openoffice/Setup.xml
and replace the tag
<ooSetupConnectionURL cfg:type="string"/>
with <ooSetupConnectionURL cfg:type="string">socket,host=0,port=2002;urp;StarOffice.ServiceManager</ooSetupConnectionURL>
Note that this change has effect on the whole network installation, which can easily become a very serious security problem. Please also note, that using the host=0 phrase will make the office listen on every network interface, in case you only want to script your office from the same machine, it is definitly better to replace the 0 with localhost.
If you want to configure it only for a certain user (in a network installation), you need to do the modification into the user dependent configuration directory at the same place.
TestOffice.java
?
As parameters, please use, for example:
uno:socket,host=localhost,port=2002;urp;StarOffice.NamingService
OpenOffice
running on a different machine?When connecting to an OpenOffice you supply an Uno URL, which allows to locate a named Uno object in a different process. A Uno URL consists of four parts:
Those four parts are concatenated to a string
uno:[connection],params;[protocol],params;[objectname]
An example Uno URL looks like:
uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager
For more information about Uno URLs please consult http://udk.openoffice.org/common/man/spec/uno-url.html
A string similiar to the uno-url is used to configure the accepting process, for instance the office. . You can start the office with
soffice "-accept=socket,host=0,port=2002;urp;"
uno
tool coming with the odk expects a different
format).
One speciality of the socket connection part is, that you can use
"host=0"
, which means accept on every
network interface available on the current machine including
localhost. The "host=0" part cannot be used for connecting to
a resource.
Additionally, you don't need to specify the object name, as the office eitherway exports multiple objects (StarOffice.NamingService, StarOffice.ServiceManager and [new] StarOffice.ComponentContext).
UnoUrlResolver
?
The UnoUrlResolver
gets a remote object for a
service name specified in an uno-url
,
especially a StarOffice.ServiceManager
.
Then, you use the the service managers XNamingService
interface in order to retrieve the service manager
'registeredObject'
via getRegisteredObject
in order to be able to
queryInterface()
for a XMultiServiceFactory
.
Remember, that the remote OpenOffice process has fulfilled its
startup phase before the naming service reference is returned.
This is necessary to guarantee the availability of all services.
As you can see, the naming service is only a container for the
service manager. This is done for flexibility reasons, because
future versions may export more objects than only the service
manager. Understand the uno-url
as
an entry point into another process; after that, everything else
should be handled via normal UNO calls.
Perhaps future versions also will remove the naming service's ability
to remove and add objects, which
obviously doesn't make any sense for remote processes.
A XComponent
notifies its event listeners when
it is being disposed. Unfortunately a reference to a
UnoUrlResolver
object is not sufficent
to receive a dispose event notification.
You'll need at least a connector and a bridge factory service
(see com.sun.star.comp.urlresolver.UnoUrlResolver
in the jurt
directory for more details) which you can query for a XComponent
interface. This queried reference can be used to add a dispose event
listener like this:
String connection = "socket,host=localhost,port=2002"; String protocol = "urp"; Object connector = _xMultiServiceFactory.createInstance("com.sun.star.connection.Connector"); XConnector connector_xConnector = (XConnector)UnoRuntime.queryInterface(XConnector.class, connector); XConnection xConnection = connector_xConnector.connect(connection); xBridge = xBridgeFactory.createBridge(connection + ";" + protocol, protocol, xConnection, null); XComponent component = (XComponent)UnoRuntime.queryInterface(XComponent.class, component); component.addEventListener(...);
The documentation for the udk project, which can be viewed via http://udk.openoffice.org, can be checked out using the following CVS command
$ cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/wwwIf you don't want the generated C++ module reference documents you might want to save these commands into a script or batch file and run it from the command shell:
cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/common cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/cpp/man cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/java cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/images cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/bylaws.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/documentation_structure.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/faq.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/index.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/project_discuss.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/project_issues.html cvs -d :pserver:anoncvs@anoncvs.openoffice.org:/cvs -z3 co oo/udk/www/project_navbar.html
Please follow http://udk.openoffice.org/common/man/draft/uno_security.html. The main goal of this draft is to provide a generic API to wrap existing security implementations, though the draft is based on java security and semantics. There are details to be discussed, marked in red, e.g., remote transparency.
Bridging UNO and CORBA is no trivial task, as both component models are based on different fundamental concepts. Therefore, we want to write down the ideas about how to deal with these fundamental differences, before beginning implementation. Please follow http://udk.openoffice.org/common/man/concept/uno_corba.html for more information. The document currently contains only some aspects that we will have to deal with. The document is supposed to grow rapidly during the next weeks. Any input on this from the community is very welcome. The main goal is to get a CORBA-bridge that supports all features necessary to communicate with the GNOME desktop (http://www.gnome.org). The component model used in GNOME is BONOBO, which is built on top of ORBIT, an open source CORBA ORB (Object Request Broker). A CORBA-UNO bridge would, e.g., allow to script OpenOffice with a GNOME scripting language. The secondary goal is to develop a 'generic' CORBA-UNO-bridge, that allows communication with an arbitrary ORB. This would allow OpenOffice to seamlessly integrate into any CORBA environment.
Please have a look at http://udk.openoffice.org/common/man/draft/soap.html.
A brief overview about the project OpenOffice - Bonobo Integration can be found at http://whiteboard.openoffice.org/bonobo/. Something about motivation and goals of this project is written there. We have checked in some code into CVS, enabling OpenOffice to be a Bonobo server for containers like Nautilus. Everyone is welcome to contribute ideas or code, on how to bring OpenOffice and GNOME closer together on the level of component technology.
dev@udk.openoffice.org
mailing list.