JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Solaris WBEM Developer's Guide
search filter icon
search icon

Document Information

Preface

1.  Overview of Solaris Web-Based Enterprise Management

2.  Using the CIM Object Manager

3.  Using the Sample Programs

4.  Writing a Client Program

5.  Writing WBEM Queries

6.  Writing a Provider Program

About Providers

Provider Data Sources

Types of Providers

Provider Naming Conventions

Implementing the Provider Interfaces

Writing an Instance Provider

Writing a Method Provider

Writing an Associator Provider

Writing an Indication Provider

How To Generate an Event Indication

Event Provider Methods

Creating and Delivering Indications

About Authorizations

Writing a Native Provider

Creating a Provider

How to Set the Provider CLASSPATH

How to Register a Provider

7.  Creating JavaBeans Components Using the MOF Compiler

8.  Administering Security

9.  Troubleshooting

A.  Solaris Platform Schema

Index

Implementing the Provider Interfaces

When you write a provider, you must determine the interfaces that your provider supports. You must implement all the methods of each interface that your provider supports. In addition, every provider must implement the CIMProvider interface, which has two methods:

Writing an Instance Provider

This following sample code implements the enumerateInstances and getInstance methods of the Ex_SimpleCIMInstanceProvider class. For brevity, the implementations of the deleteInstance, createInstance, setInstance, and execQuery methods in this example just throw a CIMException.


Note - For information on implementing the execQuery method, see Parsing Queries.


Example 6-1 CIMInstance Provider

/*
 * "@(#)SimpleCIMInstanceProvider.java"
 */
import javax.wbem.cim.*;
import javax.wbem.client.*;
import javax.wbem.provider.CIMProvider;
import javax.wbem.provider.CIMInstanceProvider;
import javax.wbem.provider.MethodProvider;
import java.util.*;
import java.io.*;

public class SimpleCIMInstanceProvider implements CIMInstanceProvider {
     static int loop = 0;
     public void initialize(CIMOMHandle cimom) throws CIMException {
     }
     public void cleanup() throws CIMException {
     }
     public CIMObjectPath[] enumerateInstanceNames(CIMObjectPath op, 
                                                   CIMClass cc) 
         throws CIMException {
            return null;
     }
     /*
      * enumerateInstances:
      * The entire instances and not just the names are returned.
      */
     public CIMInstance[] enumerateInstances(CIMObjectPath op,
                          boolean localOnly,boolean includeQualifiers,
                          boolean includeClassOrigin,String[] 
                          propertyList, CIMClass cc) throws CIMException
     {
     if (op.getObjectName().equalsIgnoreCase
                            ("Ex_SimpleCIMInstanceProvider")) {
         Vector instances = new Vector();
         CIMInstance ci = cc.newInstance();
         if (loop == 0){
             ci.setProperty("First", new CIMValue("red"));
             ci.setProperty("Last", new CIMValue("apple"));
             // only include the properties that were requested
             ci = ci.filterProperties(propertyList, includeQualifier,
                                                 includeClassOrigin);
             instances.addElement(ci);
             loop += 1;
         } else {
             ci.setProperty("First", new CIMValue("red"));
             ci.setProperty("Last", new CIMValue("apple"));
             // only include the requested properties
             ci = ci.filterProperties(propertyList, includeQualifier,
                                                 includeClassOrigin);
             instances.addElement(ci);
             ci = cc.newInstance();
             ci.setProperty("First", new CIMValue("green"));
             ci.setProperty("Last", new CIMValue("apple"));
             // only include the requested properties
             ci = ci.filterProperties(propertyList, includeQualifier,
                                                 includeClassOrigin);
             instances.addElement(ci);
         }
         return (CIMInstance[])instances.toArray();
     }
     throw new CIMException(CIM_ERR_INVALID_CLASS);
     }

     public CIMInstance getInstance(CIMObjectPath op, 
                                    boolean localOnly, 
                                    boolean includeQualifiers, 
                                    boolean includeClassOrigin,
                                    String[] propertyList, 
                                    CIMClass cc) 
         throws CIMException {
             if (op.getObjectName().equalsIgnoreCase
                             ("Ex_SimpleCIMInstanceProvider"))
             {
                 CIMInstance ci = cc.newInstance();
                 // we need to get the keys from the passed in object path,
                 // this will uniquely identify the instance we want to get
                 java.util.Vector keys = cop.getKeys();
                 // Since this is a contrived example we will simply place 
                 // the keys into the instance and be done.
                 ci.setProperties(keys);
                 // if we had other non-key properties we should add them 
                 //here.

                 // only include the properties that were requested
                 ci = ci.filterProperties(propertyList, includeQualifiers,
                                                      includeClassOrigin);
                 return ci;
             }
             throw new CIMException(CIM_ERR_INVALID_CLASS);
      }

     public CIMInstance[] execQuery(CIMObjectPath op, \
                            String query, String ql, CIMClass cc)
           throws CIMException {
           throw(new CIMException(CIMException.CIM_ERR_NOT_SUPPORTED));
    }

     public void setInstance(CIMObjectPath op, CIMInstance ci, boolean 
                             includeQualifiers, String[] propertyList)
           throws CIMException {
           throw(new CIMException(CIMException.CIM_ERR_NOT_SUPPORTED));
    }

     public CIMObjectPath createInstance(CIMObjectPath op, 
                                         CIMInstance ci) 
                                         throws CIMException {
           throw(new CIMException(
                     CIMException.CIM_ERR_NOT_SUPPORTED));
    }

     public void deleteInstance(CIMObjectPath cp) 
         throws CIMException {
         throw(new CIMException(CIMException.CIM_ERR_NOT_SUPPORTED));
     }
 }

Writing a Method Provider

The method invokeMethod is the only way that a client program can call the methods of Solaris WBEM providers. This condition is true for both providers that are built in or that are added by developers.

The following sample code creates the Solaris_ComputerSystem provider class that routes requests from the CIMOM to one or more specialized providers. These providers handle requests for dynamic data for a particular type of managed object. For example, the Solaris_Package provider handles requests to execute methods in the Solaris_Package class.

The method provider implements a single method, invokeMethod. This method calls the appropriate provider to either reboot a system, shut down a system, or delete a serial port.

Example 6-2 Method Provider

...
public class Solaris_ComputerSystem implements MethodProvider {
    ProviderCIMOMHandle pch = null;
    public void initialize(CIMOMHandle ch) throws CIMException {
        pch = (ProviderCIMOMHandle)ch;
    }

    public void cleanup() throws CIMException {
    }

    public CIMValue invokeMethod(CIMObjectPath op, String methodName,
            Vector inParams, Vector outParams)  throws CIMException {
        if (op.getObjectName().equalsIgnoreCase("solaris_computersystem")) {
            if (methodName.equalsIgnoreCase("reboot")) {
                // call helper function, not shown here
                return new CIMValue(rebootSystem());
            }
            if (methodName.equalsIgnoreCase("shutdown")) {
                // call helper function, not shown here
                return new CIMValue(shutdownSystem());
            }
        }
        if (op.getObjectName().equalsIgnoreCase("solaris_serialport")) {
            if (methodName.equalsIgnoreCase("disableportservice")) {
                // call helper function, not shown here
                return new CIMValue(deletePort(op));
            }
        }
        // error if we get here
        throw new CIMException(CIMException.CIM_ERR_NOT_SUPPORTED,
            "The requested function does not exist");
    }
    // helper functions would be defined below
    ...
}

Writing an Associator Provider


Note - The objectName argument in each of the association methods called by your client program. In other words, CIMObjectPath must be the object path of an instance, not a class.


Unless the CIMOM can locate the object path of an instance, it assumes that the client wants the class definitions of the association that are in the CIM Object Manager Repository. The class definition of the association includes the templates from which the association's member instances are derived. Therefore, the CIMOM uses the client API's association method and not the provider's association method.

The most important part of designing and coding an association is the association class. Your association will only be as complex as the contents of the association class. The number of members of the association equals the number of references in the association class. Roles can be used to model more complicated associations. The following examples show some sample association classes.

The following code sample implements the associators method. The CIMOM passes values for associatorNames, objectName, role, resultRole, includeQualifiers, includeClassOrigin, and propertyList to the association provider. In addition, the code prints the name of the CIM associator class and the CIM class or instance whose associated objects are to be returned. This provider handles instances of example_teacher and example_student classes.

Example 6-3 CIMAssociator Provider

...

public CIMInstance[] associators(CCIMObjectPath assocName, CIMObjectPath 
                objectName, String resultClass, String role, String
                resultRole, boolean includeQualifiers, boolean 
                includeClassOrigin, String[] propertyList)
                throws CIMException {
        
    System.out.println("Associators "+assocName+" "+objectName);
    if (objectName.getObjectName()equalsIgnoreCase("example_teacher")) {
        Vector v = new Vector();
        if ((role != null)  && (!role.equalsIgnoreCase("teaches"))) {
            // Teachers only play the teaches role.
            return v;
        }
        if ((resultRole != null)  && (!resultRole.equalsIgnoreCase
                                     ("taughtby"))) {
            // Teachers only result in taughtby role
            return v;
        }
        // Get the associators of a teacher
        CIMProperty nameProp = (CIMProperty)objectName.getKeys().elementAt
                               (0);
        String name = (String)nameProp.getValue().getValue();
        // Get the student class
        CIMObjectPath tempOp = new CIMObjectPath("example_student");
        tempOp.setNameSpace(assocName.getNameSpace());
        CIMClass cc = cimom.getClass(tempOp, false);
        // Test the instance name passed by objectName
        // and return the associated instances of the student class.
        if(name.equals("teacher1")) {
            // Get students for teacher1
            CIMInstance ci = cc.newInstance();
            ci.setProperty("name", new CIMValue("student1"));
            v.addElement(ci.filterProperties(propertyList, 
                             includeQualifiers,
                             includeClassOrigin));
            ci = cc.newInstance();
            ci.setProperty("name", new CIMValue("student2"));
            v.addElement(ci.filterProperties(propertyList,
                        includeQualifiers, includeClassOrigin));
            return v;
        }
    }
}

Writing an Indication Provider

To generate an indication for a CIM event, you need to perform the following tasks:

How To Generate an Event Indication

  1. Implement the EventProvider interface.

    For example:

    public class sampleEventProvider 
    implements InstanceProvider EventProvider{
    
        // Reference for provider to contact the CIM Object Manager
        private ProviderCIMOMHandle cimom;
       }
  2. Execute each of the methods listed in Table 6-2 for each instance indication that the provider handles.
  3. Create an indication for create, modify, and delete instance event type.

    For example, in the createInstance method:

    public CIMObjectPath createInstance(CIMObjectPath op, 
            CIMInstance ci)
        throws CIMException {
            CIMObjectpath newop = ip.createInstance(op, ci);
           
            CIMInstance indication = new CIMInstance();
            indication.setClassName("CIM_InstCreation");
            
            CIMProperty cp = new CIMProperty();
            cp.setName("SourceInstance");
            cp.setValue(new CIMValue(ci));
            
            Vector v = new Vector();
            v.addElement(cp);
            indication.setProperties(v);
            ...
        }
  4. Deliver the event indication to the CIM Object Manager.
    cimom.deliverEvent(op.getNameSpace(), indication);
Event Provider Methods

An event provider implements the EventProvider interface. This interface contains methods that the CIMOM uses to notify the provider when a client has subscribed for indications of CIM events. This method is also used when a client has cancelled the subscription for CIM events. These methods allow the provider to indicate whether the CIMOM should poll for some event indications and whether the provider should authorize the return of an indication to a handler.

The following table lists the methods in the EventProvider interface that must be implemented by an event provider.

Table 6-2 EventProvider Methods

Method
Description
activateFilter
When a client creates a subscription, the CIMOM calls this method to ask the provider to check for CIM events.
authorizeFilter
When a client creates a subscription, the CIMOM calls this method to test if the specified filter expression is allowed.
deActivateFilter
When a client removes a subscription, the CIMOM calls this method to ask the provider to deactivate the specified event filter.
mustPoll
When a client creates a subscription, the CIMOM calls this method to test whether the specified filter expression is allowed by the provider, and if it must be polled.

The CIMOM passes values for the following arguments to all methods:

In addition, the activateFilter method takes the boolean firstActivation, indicating that this filter is the first filter for this event type. The deActivateFilter method takes the boolean lastActivation, indicating that this filter is the last filter for this event type.

Creating and Delivering Indications

A client application subscribes for indications of CIM events by creating an instance of the CIM_IndicationSubscription class. The CIMOM then forwards the request to the appropriate provider. If the provider implements the EventProvider interface, the CIMOM notifies the provider when to start sending indications for the specified events. The provider performs this notification by calling the provider's activateFilter method. In addition, the CIMOM notifies the provider when to stop sending indications for the specified events by calling the provider's deActivateFilter method.

The provider responds to the CIMOM's requests by creating and delivering an indication each time the provider creates, modifies, or deletes an instance. A provider typically defines a flag variable that is set when the CIMOM calls the activateFilter method. This flag is cleared when the CIMOM calls the deActivateFilter method. Then in each method that creates, modifies, or deletes an instance, the provider checks the status of the activate filter flag. If the flag is set, the provider creates an indication containing the created CIM instance object. The provider uses the deliverEvent method to return the indication to the CIMOM. If the flag is not set, the provider does not create and deliver an indication of the event.

A provider starts delivering indications when the activateFilter method is called. The provider creates instances of concrete subclasses of CIM_Indication and invokes the ProviderCIMOMHandled.deliverIndication method. The CIMOM receives the indication and delivers the indication to the appropriate indication handlers. A provider can handle multiple event types. For example, in the case of life cycle indications, a provider can handle CIM_InstCreation, CIM_InstDeletion, and CIM_InstModification.

To keep track of types that have subscriber interest, the provider can use the firstActivation and lastActivation flags passed in the activateFilter and deActivateFilter calls, respectively. The firstActivation flag is true when the subscription is the first subscription for the particular event type. Similarly, lastActivation is true when the last subscription for the particular event type is removed. By checking these flags, the provider can easily allocate or deallocate resources to monitor the specified event types.

About Authorizations

A provider that handles sensitive data can check authorizations for requests for indications. The provider must implement the Authorizable interface to indicate that the provider handles authorization checking. The provider also implements the authorizeFilter method. The CIMOM calls this method to test whether the owner (UID) of an event handler is authorized to receive the indications that result from evaluating a filter expression. The UID for the owner of the event destination, the event handler, can be different than the owner of the client application requesting the filter activation.

Writing a Native Provider

Providers get information from and set information on managed devices. A native provider is a program specifically written for a particular managed device. For example, a provider that accesses data on a Solaris system usually includes C functions to query the system.

The common reasons for writing a native provider are as follows:

The Java Native Interface is part of the JDK software. By writing programs using the Java Native Interface, you ensure that your code is completely portable across all platforms. The Java Native Interface enables Java code to operate with applications and libraries that are written in other languages, such as C, C++, and assembly.

For more information on writing and integrating Java programs with native methods, visit the Java Web site at http://java.sun.com.