Distributed Object Systems 8 DCOM 2 COM (and some Corba) Dynamic Invocation Containment/Aggregation/Delegation Automation Monikers Piet van Oostrum Oct 7, 2008 Piet van Oostrum 1 Dynamic Invocation in COM Can Dynamic invocation in COM be done as in Corba? Use Request object instead of stub marshalling/protocol remains the same NO! In case of inproc object there is no stub/skeleton involved i.e. call is direct Dynamic invocation through the IDispatch interface Server must implement the IDispatch interface Is used for dynamic programming languages (Visual Basic, scripting languages,... ) Wizards can help you implement IDispatch IDispatch interface often uses special parameter types: VARIANT, BSTRING, SAFEARRAY These are just complicated struct/unions to represent Visual Basic datatypes. Piet van Oostrum 2 Dynamic Invocation The server object must implement this special IDispatch interface (compare Corba s DSI) Every method that the server offers through IDispatch gets a number (index) called DISPID In Corba you use method name, in COM number The server will usually switch on the DISPID GetTypeInfo can be called to get info about the types of the methods (if available usually from a type library) Type Library = file containing compiled IDL (AST) Piet van Oostrum 3 Client side The client can then use this IDispatch interface So the client must be able to call at least one static interface The client must do QueryInterface to get the IDispatch interface method GetIDsofNames is used to couple names of methods and DISPIDs It has an array of names as in parameter and an array of DISPIDs as out parameter The Invoke method is used to make the call The client calls the Invoke method A special VARIANT type is used for the parameters VARIANT contains type info for the marshaller Visual Basic types can be used and some special structs (BSTRING, SAFEARRAY, DATE, DECIMAL) Interfaces Multiple Interfaces If multiple dispinterfaces are defined by the object, one has to be designated as default. This is what Visual Basic uses. The QueryInterface for IDispatch will give the default interface The others can be obtained by explicit QueryInterface Dual Interface A dual interface is an interface that can be called both statically and dynamically It inherits from IDispatch and adds also the static methods This may be important for high performance applications Piet van Oostrum 4 Piet van Oostrum 5 slides8.pdf October 7, 2008 1
IDL notation dispinterface IDL notation dual interface [uuid(3cfdb282-ccc5-11d0-ba0b-00a0c90df8bc)] dispinterface IStat { properties: methods: [id(1)] void init(); [id(2)] void additem(double item); [id(3)] double getavg(); [id(4)] long getnum(); }; [object, uuid(3cfdb282-ccc5-11d0-ba0b-00a0c90df8bc), dual ] interface IStat: IDispatch [id(1)] HRESULT init(); [id(2)] HRESULT additem([in] double item); [id(3)] HRESULT getavg([out] double avg); [id(4)] HRESULT getnum([out] long num); }; Piet van Oostrum 6 Piet van Oostrum 7 Contents Dynamic Invocation Containment/Aggregation/Delegation Automation Monikers Implementation inheritance in COM Microsoft literature about COM discourages inheritance Fragile Base Class problem: Mostly for compiled languages Subclass is dependent of base class (superclass) Later changes to base class may damage subclass if not recompiled The size of objects (i.e. structs or classes) The offsets to "visible" (public or protected) data The offsets to the virtual functions in the vtable Instead of inheritance use Containment/Delegation or Aggregation Please note: In.NET one of the strong points is the possibility to inherit even across programming languages. But there are strong checks at load time. Piet van Oostrum 8 Piet van Oostrum 9 Containment or Delegation Aggregation IUnknown IUnknown IUnknown Interface A Interface B Interface A IUnknown Outer Object Inner Object Interface B Inner Object Outer Object implements A methods and B methods (because interface A extends B) Outer object s implementation of B methods just calls Inner object s B methods void m(int x) { b.m(x); } Inner Object is not aware of the special relationship Inner Object can be considered as a helper object Outer Object Outer object puts inner object s method pointer in its own method table Problem: normally Inner object would return its own IUnknown pointer if QueryInterface is done on interface B Solution: When Outer object creates Inner object, it passes its own IUnknown pointer as Controlling Unknown CoCreateInstance(CLSID_CStat, pouter,... Piet van Oostrum 10 Piet van Oostrum 11 slides8.pdf October 7, 2008 2
Inheritance and Delegation in Corba Delegation can be used when a programming language does not support multiple inheritance A m() C m() n() p() B n() Delegation class A { void m(); } class B { void n(); } class C { private A a; private B b; } C(A a, B b) { this.a = a; this.b = b; } m() { a.m(); } n() { b.n(); } p() {... } Piet van Oostrum 12 Piet van Oostrum 13 Inheritance problem The problem with this solution is that C cannot be used where an A or B is required. A solution is to use interfaces and implementation classes interface A {... } interface B {... } class A_impl implements A {... } class B_impl implements B {... } class C implements A, B { private A_impl a; // or private A a; private B_impl b; // or private B b;... etc... } or even interface C and class C_impl Piet van Oostrum 14 Corba Servant (Inheritance Model) Interface MyInterface Abstract Interface MyInterfaceOperations (generated by IDL compiler) Skeleton MyInterfacePOA implements MyInterfaceOperations Servant extends Skeleton class Operations Skeleton Servant implement. Problem if you want Servant to extend other class Piet van Oostrum 15 Corba Delegation Model (Tie) Servant class doesn t have to extend skeleton Only implement MyInterfaceOperations Servant can inherit from another class IDL compiler generates Tie class that inherits from skeleton Tie class delegates to implementation class Tie+implementation = actual servant Operations Skeleton Tie class (generated by IDL compiler) public class HelloPOATie extends HelloPOA { public HelloPOATie(HelloOperations delegate) { this._impl = delegate; }... public String sayhello () { return _impl.sayhello(); // delegation } // sayhello Servant implement. Delegation Tie Piet van Oostrum 16 Piet van Oostrum 17 slides8.pdf October 7, 2008 3
Corba Delegation Model (Tie) class HelloImpl extends SomeOtherClass implements HelloOperations... method implementations as usual // Server class: create a servant. HelloImpl helloimpl = new HelloImpl(); // create a tie, with servant being the delegate. HelloPOATie tie = new HelloPOATie(helloImpl); COM Dynamic Invocation Containment/Aggregation/Delegation Automation Monikers // obtain the objectref for the tie // this step also implicitly activates the object Hello href = tie._this(orb); Piet van Oostrum 18 Piet van Oostrum 19 (OLE) Automation Automation (formerly known as OLE Automation) is a way to script a program from another program E.g. Microsoft Word: Open a document, insert some text and save it. Usually done from scripting languages, e.g. Visual Basic, Python, Ruby. Application must make its operations available as (Automation) COM interfaces (IDispatch). Collection of interfaces known as OLE. For use in web browsers a stripped down collection is ActiveX. Visual Basic and COM Visual Basic (up to version 6) Developed as COM programming language Seamless integration with COM Dim statvar as Stat.Stat Dim statvar as Object Set statvar = CreateObject("Stat") Set statvar = New Stat.Stat Dim statvar as New Stat.Stat statvar.init statvar.additem 3.14 Set result = statvar.getavg When declared as Object uses runtime resolution When declared as specific class uses compile time resolution Type info comes from Type Library (loaded at compile time or runtime). Piet van Oostrum 20 Piet van Oostrum 21 Automation with Visual Basic Dim Word As Object Dim Doc As Object Dim Spot As Object Set Word = CreateObject("Word.Application") Word.Visible = True Set Doc = Word.Documents.Add() Set Spot = Doc.Range(0, 0) Spot.InsertBefore "Hello From Visual Basic" Doc.SaveAs "test.doc" Doc.Close Word.Quit Early/Late Binding VB looks up the type info from the type library The Windows registry contains mapping from Program Id ("Word.Application") to Class Id The registry contains the location of the type library Variables declared as Object (Dim Word As Object) must be resolved at runtime This is called Late Binding. VB can also do the lookup at compile time: Early Binding: Register the type library at compile time Use: Dim Word As New Word.Application Piet van Oostrum 22 Piet van Oostrum 23 slides8.pdf October 7, 2008 4
Automation with Python Can be used with ActiveState Python, or Standard Python + win32all extensions from win32com.client import Dispatch word = Dispatch("Word.Application") word.visible = True doc = word.documents.add() spot = doc.range(0, 0) spot.insertbefore("hello from Python") doc.saveas("test.doc") doc.close() word.quit() Python/COM observations Python is very simple to use for Automation Python looks up the type library and makes all decisions at runtime You can even do it interactively This makes development and try-out very easy You can also run the makepy script This generates additional Python files containing the methods of the interface (like stubs) At runtime these are used if available This is comparable to Early Binding (faster) Piet van Oostrum 24 Piet van Oostrum 25 Java and (D)COM J-Integra example Originally with Microsoft Java Virtual Machine (now defunct) Visual J++ 6.0 or MS Java SDK Almost transparent Java virtual machine does all the administration Build Interface pointers, refcounts etc. Special language extension is used (in specially formatted comments) Jactivex program generates interface and class files from TLB (Type Library) Wrapper classes: CCW (Com callable wrapper) to call Java from COM, JCW (Java callable wrapper) to call COM from Java J-Integra and EZ JCom are commercial implementations of the COM protocol in Java (any Java). import excel.*;... Application app = new Application(); app.setvisible(true); Workbooks workbooks = app.getworkbooks(); Workbook workbook = workbooks.add(null); Sheets worksheets = workbook.getworksheets(); Worksheet sheet = new Worksheet(worksheets.add(null, null, null, null)); Range range = sheet.getrange("a1:c3", null); Object[][] newvalue = { {"abcd", new Boolean(false), new Double(98.0/12)}, {new Date(), new Integer(5454), new Float(22.0/7)}, {new Boolean(true), "xyzt", new Date() } }; range.setvalue(newvalue); // Update the spreadsheet Piet van Oostrum 26 Piet van Oostrum 27 Python OpenOffice.org automation Python OpenOffice.org automation Python as a separate process: Script programmer explicitely writes application startup code. Startup code must connect to Ooo. Code executes slow, as every call to OOo is going through the inter process bridge. Python process must be started separately. Python embedded in OpenOffice.org process: OOo Process Python Process PyUNO Runtime OOo Process PyUNO Runtime Python Code Python UNO component Script must be written as a PyUNO component (adding a coding overhead) OOo listens on an inter process resource (socket or named pipe). This must be switched on seperately either on command line or with the OOo configuration. Piet van Oostrum 28 Piet van Oostrum 29 slides8.pdf October 7, 2008 5
Py-UNO example Py-UNO example import uno # get the uno component context from the PyUNO runtime localcontext = uno.getcomponentcontext() # create the UnoUrlResolver resolver = localcontext.servicemanager \.createinstancewithcontext( "com.sun.star.bridge.unourlresolver", localcontext ) # connect to the running office ctx = resolver.resolve( "uno:socket,host=localhost,\ port=2002;urp;staroffice.\ ComponentContext" ) smgr = ctx.servicemanager # get the central desktop object desktop = smgr.createinstancewithcontext( "com.sun.star.frame.desktop",ctx) # access the current writer document model = desktop.getcurrentcomponent() # access the document s text property text = model.text # create a cursor cursor = text.createtextcursor() # insert the text into the document text.insertstring( cursor, "Hello World", 0 ) Piet van Oostrum 30 Piet van Oostrum 31 Mac OS X Applescript COM tell application "Microsoft Word" set newdoc to make new document insert text "Hello from Applescript" at end of text object of active document save as newdoc file name "test.doc" end tell Dynamic Invocation Containment/Aggregation/Delegation Automation Monikers Piet van Oostrum 32 Piet van Oostrum 33 COM Monikers Moniker Implementation Monikers are (persistent) names for persistent objects If you want to revive a persistent object (e.g. Excel worksheet): Create an object of that class (CoCreateInstance) Force the object to load its persistent data (IPersist...) There can be many parameters to specify where the data comes from, e.g file name, which part of an object E.g. linked worksheet in Word document: filename and range of the worksheet How does Word know what parameters to give and what they mean (especially if it is an unknown class)? The object needs to have this information itself Monikers are used to encapsulate this data Word doesn t have to know all the interfaces of all possible linked objects Client only deals with the IMoniker interface E.g. in Object linking the moniker is stored in the structured document Interface IMoniker: BindToObject binds the moniker to an object BindToStorage binds the Moniker to the Storage of the object 13 more methods Also inherits from IPersistsStream (4 methods) which inherits from IPersist (1 method) Piet van Oostrum 34 Piet van Oostrum 35 slides8.pdf October 7, 2008 6
Moniker use 4. Client invokes methods Moniker Examples File Moniker: contents is a file, persistent data is file name Client A 3. Pointer to interface A is returned via moniker Object Server Item Moniker: describes an item in a composite object, e.g. worksheet in an Excel workbook, persistent data is the item s name and the moniker of the object in which it is contained Composite Moniker: groups together other monikers, e.g. File Moniker, worksheet item and range item. Persistent date: the component monikers Java Moniker: describes a Java class (now defunct): 1. client calls IMoniker:: BindToObject(IID_A) 1 Moniker pointer method call/return 2. Moniker instantiates the object and tells it to load its persistent data Piet van Oostrum 36 Dim dat As Object Set dat = CreateObject("java:java.util.Date") Dim s As String s = dat.tostring Piet van Oostrum 37 Composite Moniker COM Structured Storage Word Structured Storage is used for compound documents These documents can contain other (sub)documents Client IMoniker Grades.xls IMoniker Composite moniker IMoniker Sheet1 IMoniker R1C1:R5C4 E.g. a Word document containing an Excel sheet Each subdocument can be accessed more or less independently COM structured documents work like a filesystem within a file It has streams (file-like) and containers (directory-like) Interface IStream for file-like objects Read, Write, Seek... methods Interface Istorage for the containers CreateStream, OpenStream for Streams in the Storage CreateStorage, OpenStorage for sub-storages methods for renaming, destroying, copying and moving Transaction support (Commit, Revert) Setting the class of an object, getting information... File moniker Item moniker Item moniker Piet van Oostrum 38 Other interfaces to deal with persistence OpenDoc document Piet van Oostrum 39 Structured Storage in general Consists Example of document parts Apple and IBM worked together on OpenDoc compound document architecture document consists of parts different parts can have different part editors part editors work in a part of the visible window parts can have different presentations parts can have different versions Now abandoned (sources are available) Piet van Oostrum 40 Piet van Oostrum 41 - Each having its own part editor slides8.pdf - Which editor is user configurable - Parts may be a container for other parts - Parts execute as part of a process for a October 7, 2008 document 7
Presentations Different Part can representations have different presentations What is the problem? Putting parts together in a single document Reinventing the filesystem within a file Better use the real filesystem Or make mountable filesystems No need to rewrite applications Ship a document in a zip file Versioning Use existing tools, like CVS, subversion Contra: not integrated with compound documents Simultaneous access Is usually done with database systems Maybe file access should be upgraded to include transactions Can be done with an additional Transactions layer Part info - Presentation data Piet van Oostrum 42 - Can be stored with the frame Piet van Oostrum 43 View type - Determines the basic kind of presentation Distributed Object Systems 31/03/98 Atze Dijkstra OpenDoc 14 Dept. of Comp.Science, UU slides8.pdf October 7, 2008 8