Sie sind auf Seite 1von 10

Component Object Model

• Language independent
COM - Component Object Model • OS independent (in theory)
• Way to allow components to be designed,
deployed, upgraded
– Need to interact with code written after you
were deployed

Immutable interfaces COM


• Interact through interfaces • A binary compatibility standard
– No direct access to fields – interface pointers
– Interfaces must never be changed
IStream Method 1
– Interfaces assigned a GUID
• avoid name clashes Method 2
• allow versioning by assigning a new GUID Method 3
Method 4

Multiple interfaces Multiple interfaces


• Components can implement multiple IStream Method 1
interfaces Method 2
• Different interfaces may correspond to Method 3
different entry points to object Method 4
– C++ multiple inheritance IPrint Method 1
– adaptors
Method 2
Method 3
Method 4

1
Interfaces in COM Reference counting
• Similar to interfaces in Java • COM objects are reference counted
– no variables – each object keeps track of the number of
• Interfaces have a 128 bit Unique ID pointers to it
– immutable, never changed, no collisions • When ref count goes to zero, element
• In writing COM code, always use interfaces deletes itself
pointers/references • Cycles can be a problem
• Remembering where to put all increments
and decrements can be a problem

Each interface counted separately IUnknown


• Each entry point/interface to a COM object • All COM interfaces must extend IUnknown
is ref counted separately – HRESULT QueryInterface(const IID& iid,
– allows an adaptor to be garbage collected void ** ppv)
– ULONG AddRef() // inc ref count
– ULONG Release() // dec ref count

Query interface QueryInterface rules


• Like a C++ dynamic cast • You always get the same IUnknown
– Do you support this interface? • You can get an interface if you got it before
– If so, give me back a pointer of that kind • You can get the interface you have
• incrementing the ref count for that interface
• You can get back to where you started
– Else, signal failure

2
HRESULT Creating objects in COM
• COM doesn’t understand exceptions • Each component has a CLSID (class ID)
• So almost all methods return an HRESULT • Can call CoCreateInstance
– numerical indication of success or a specific • Can get Class Factory, then create instances
error directly
• Each DLL has a function that can return
class factories for all classes that can be
created by that DLL

Smart Pointers Smart Pointers


• Automatically take care of reference template <class T> class Iptr T* operator T*() { return p; }
{ T& operator*() { return *p;}
counting T* p; T* operator->() { return p; }
– Some versions of COM smart pointers Iptr() : p(0) {};
T** operator&() {
automatically perform dynamic casting (via Iptr(T* q) : p(q) {
assert(p == NULL);
calls to QueryInterface) if (p) p->AddRef();
} return &p; }
– Not recommended Iptr(Iptr<T> q) : p(q.p) { //
if (p) p->AddRef(); // operator = left as exercise
}
~Iptr() {
if (p) p->Release(); }

FooBar
• interface IFoo : public IUnknown { … }
COM, part 2 • interface IBar : public IUnknown { … }
• class Foo : public IFoo { … }
• class Bar : public IBar { … }
• class FooBar : public Foo, public Bar { … }

3
Implementing QueryInterface Things to note
STDMETHODIMP QueryInterface(const IID& iid, • If you support 100 interfaces, cascaded if
void **ppv) {
if (iid == IID_IUnknown || iid == IID_IFoo) statements are going to get expensive
*ppv = static_cast<Foo*>(this); – can’t use case statements (UIID’s aren’t ints)
else if (iid == IID_IBar)
*ppv = static_cast<Bar *>(this); – could use custom hashtable
else {
*ppv = null; return E_NOINTERFACE; • Separate ref counts
} – could put call to AddRef in each branch
reinterpret_cast< IUnknown *>(*ppv)->AddRef();
return S_OK; – would eliminate reinterprete_cast
} – but would increase code size

I want everything Component categories


• Why can’t I ask • Assigned a GUID
– what is the list of all of the interfaces you • Corresponds to a set of interfaces
support? – If a component is registered as members of a
• What would you do with the list of all category
interfaces a component supports? – instances of that component support all of those
• Can use component categories interfaces
– will still need to use QueryInterface to move
between interfaces

Categories in Java Component reuse


• Just define a Mega-interface • How to reuse components?
– An interface that extends all of the interfaces in – Base class (implementation inheritance)
the category – Containment (have as a member)
– Ask if class/component implements that • Delegation - Some methods get directly forwarded
– Can use reference of Megainterface type to • Adapter - Some methods get translated
invoke all methods from any interface in – Aggregation
category
– No casting needed

4
Aggregation Using Aggregation
• Say I have a component Bar • When someone asks a Bar for its IFoo
– which uses a component Foo interface
– just hand them a reference to your Foo
• Foo implements the IFoo interface
– handles all IFoo function calls
• Bar also implements the IFoo interface • But what if you invoke QueryInterface on
– by handling things off to its Foo the IFoo reference and ask for an IBar
• Could handle by delegation interface?
– but that adds an additional level of indirection

Delegation/Forwarding Aggregation
IUnknown IUnknown

IUnknown IUnknown
inner inner
IBar IBar

outer
IFoo IFoo

Foo Foo

Bar Bar

Supporting aggregation Automation/IDispatch interfaces


• You must be able to be told that you have • Can ask a interface which methods it
an outer component supports, and invoke those methods
• Calls to QueryInterface should be routed to • Visiual Basic example
your outer component Dim Bullwinkle As Object
Set Bullwinkle = CreateObject(“TalkingMoose”)
• Reference counts are a little tricky Bullwinkle.PullFromHat 1, “Rabbit”
– cycle could prevent stuff from being collected • Look for method “PullFromHat”
– guess that it takes a LONG and a BSTR

5
Automation interfaces are a pain Dual interfaces
• All argument types must be one of a • Support both Dispatch invocation and
predefined VARIANT list regular method invocation
– primitive types • Code for dispatch invocation can be built
• how do you pass a 1? automatically
– long, byte, short, ushort, ulong, int, uint
– if you limit yourself to VARIANT argument
– IUnknown and IDispatch types
types
• No method overloading
• No way to ask the types of a method

Reflection in Java Reflection, continued


• Allows you to ask a class or interfaces • All classes/objects support reflection
questions such as – accessing private fields/methods needs
– which methods do you support? permission from the security manager
• what type are there arguments?
– what fields do you have?
• On an object
– invoke a method
– get or set a field

Topics
• Marshalling
COM and software components • Threads

6
Marshalling/Serialization Example IDL for Marshalling
• COM allows objects to be marshalled • interface IY : IUnknown {
HRESULT fCount([out] int * sizeArray);
– same as Serialization in Java HRESULT fArrayIn([in] int sizeIn,
• Need to give extra data in IDL file [in, size_is(sizeIn) int arrayIn[]);
HRESULT fArrayOut([in] int maxSize,
– IDL = interface definition language [in, size_is(maxSize)] int arrayOut[],
[out] int * sizeOut);
}

COM Threads Apartment threads


• Free threads • Single thread for entire apartment
– similar to Java threads, must use explicit • Call from a free thread, or from a different
synchronization apartment, are marshalled
• Apartment threads – like a RMI call
– COM objects can be grouped into an apartment – Apartment thread must have a message loop to
– Each apartment has a designated thread receive and dispatch calls

Apartment threads Servers in COM


• Simple synchronization model • COM objects don’t have to be local
– backwards compatible with WIN32? – can make a remote call (like Java RMI)
• Similar to having a single synchronization • A COM object can be
object for an entire set of components – in process
• Still have potential problems such as – in process, different apartment
deadlock – same machine, separate process
– different machine

7
Advantages of COM servers Java Beans
• Seg fault only kills one process • A Java-based Software component
• OS services can be provided as COM technology
services – not the only way to do components in Java
• A Java Bean is a reusable software
component that can be manipulated visually
in a builder tool

Visual builder tools Design patterns


• No, not a text editor • Could allow you to view and change any
• Used to combine and customize existing fields of a component
components, not write from scratch – Doable using reflection
• What can be customized? – But a bad idea
• could make inconsistent changes, change fields that
• What can be attached? aren’t a part of public interface
• Set of design patterns to define how to
customize Java Beans

Design patterns Why reuse design patterns?


• Very hot buzz word • Sometimes, because the pattern is a really
– some actual substance cool and wonderful idea
• A common/standard way of doing • But mainly, so that when another
something programmer looks at your code
– can’t be captured by standard forms of OO
– They will instantly see what idea you are trying
reuse
to implement

8
Tools and patterns Properties
• If a pattern is simple • If a component supports functions:
– automatic tools can understand it – public void setMyValue(int v)
– extract pattern information – public int getMyValue()
– generate code • It has a MyValue property of type int
• For boolean types, getter function can be
named is<Prop>()

Properties, continued Java Bean Event Patterns


• Can have read-only, read/write or write- • A Bean Event must extend
only properties – class java.util.EventObject {
– don’t have to define both getter and setter public EventObject(Object src);
method public Object getSource();
}
• Name should end in Event
– e.g., tempChangeEvent

Event Listeners Event sources


• must implement java.util.EventListener • Event sources fire events
– just a marker interface • Have methods to attach/dettach Listeners
• have event-Listener methods – public void add<ListenerType>(ListenerType ls);
– void <eventName>(<EventObjectType> e); – public void remove<ListenerType>(ListenerType ls);

• interface TempChangeListener {
void tempChanged(TempChangedEvent e);
}

9
Event Adapters Bound properties
• Easy to construct event adapters • Can set things up so that changes to bean
– For example, an adapter that receives property are indicated by an event
temperatureChanged events, and generates – events are a subtype of
temperatureIncreased and java.beans.PropertyChangeEvent
temperatureDecreasedEvents – Listeners implement PropertyChangeListener
– One Listener for all change events on the bean
• may optionally support listeners for specific
properties

Constrained Properties Builder tools


• Listeners can veto property changes • Example: Sun’s BeanBox
– Listener throws PropertyVetoException • Can create instances of beans
– set<Property> method throws … • Modify their properties
– Default mechanism
– Special code for manipulating bean
• Attach Listeners, create adapters, ...

Serialization and Persistence


• OK, so we can manipulate Java Beans in a
builder tool
• Doesn’t help if we can’t distribute the beans
• Serialize the beans
• application loads beans from Serialized
form

10